1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.ipc;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertTrue;
23 import static org.junit.Assert.fail;
24 import static org.mockito.Matchers.anyInt;
25 import static org.mockito.Matchers.anyObject;
26 import static org.mockito.Mockito.doThrow;
27 import static org.mockito.Mockito.spy;
28 import static org.mockito.Mockito.verify;
29 import static org.mockito.internal.verification.VerificationModeFactory.times;
30
31 import java.io.IOException;
32 import java.net.InetSocketAddress;
33 import java.net.Socket;
34 import java.util.ArrayList;
35 import java.util.List;
36
37 import javax.net.SocketFactory;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41 import org.apache.hadoop.conf.Configuration;
42 import org.apache.hadoop.hbase.Cell;
43 import org.apache.hadoop.hbase.CellScannable;
44 import org.apache.hadoop.hbase.CellScanner;
45 import org.apache.hadoop.hbase.CellUtil;
46 import org.apache.hadoop.hbase.HBaseConfiguration;
47 import org.apache.hadoop.hbase.HConstants;
48 import org.apache.hadoop.hbase.HRegionInfo;
49 import org.apache.hadoop.hbase.KeyValue;
50 import org.apache.hadoop.hbase.KeyValueUtil;
51 import org.apache.hadoop.hbase.client.MetricsConnection;
52 import org.apache.hadoop.hbase.client.Put;
53 import org.apache.hadoop.hbase.client.RowMutations;
54 import org.apache.hadoop.hbase.codec.Codec;
55 import org.apache.hadoop.hbase.ipc.protobuf.generated.TestProtos.EchoRequestProto;
56 import org.apache.hadoop.hbase.ipc.protobuf.generated.TestProtos.EchoResponseProto;
57 import org.apache.hadoop.hbase.ipc.protobuf.generated.TestProtos.EmptyRequestProto;
58 import org.apache.hadoop.hbase.ipc.protobuf.generated.TestProtos.EmptyResponseProto;
59 import org.apache.hadoop.hbase.ipc.protobuf.generated.TestRpcServiceProtos;
60 import org.apache.hadoop.hbase.monitoring.MonitoredRPCHandler;
61 import org.apache.hadoop.hbase.protobuf.RequestConverter;
62 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
63 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto;
64 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.RegionAction;
65 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier;
66 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
67 import org.apache.hadoop.hbase.security.User;
68 import org.apache.hadoop.hbase.testclassification.SmallTests;
69 import org.apache.hadoop.hbase.util.Bytes;
70 import org.apache.hadoop.hbase.util.Pair;
71 import org.apache.hadoop.io.compress.GzipCodec;
72 import org.apache.hadoop.net.NetUtils;
73 import org.apache.hadoop.util.StringUtils;
74 import org.junit.Test;
75 import org.junit.experimental.categories.Category;
76 import org.mockito.Mockito;
77 import org.mockito.invocation.InvocationOnMock;
78 import org.mockito.stubbing.Answer;
79
80 import com.google.common.collect.ImmutableList;
81 import com.google.common.collect.Lists;
82 import com.google.protobuf.BlockingService;
83 import com.google.protobuf.ByteString;
84 import com.google.protobuf.Descriptors.MethodDescriptor;
85 import com.google.protobuf.Message;
86 import com.google.protobuf.RpcController;
87 import com.google.protobuf.ServiceException;
88
89
90
91
92 @Category(SmallTests.class)
93 public class TestIPC {
94 public static final Log LOG = LogFactory.getLog(TestIPC.class);
95 static byte [] CELL_BYTES = Bytes.toBytes("xyz");
96 static Cell CELL = new KeyValue(CELL_BYTES, CELL_BYTES, CELL_BYTES, CELL_BYTES);
97 static byte [] BIG_CELL_BYTES = new byte [10 * 1024];
98 static Cell BIG_CELL = new KeyValue(CELL_BYTES, CELL_BYTES, CELL_BYTES, BIG_CELL_BYTES);
99 private final static Configuration CONF = HBaseConfiguration.create();
100
101
102
103
104 private static final BlockingService SERVICE =
105 TestRpcServiceProtos.TestProtobufRpcProto.newReflectiveBlockingService(
106 new TestRpcServiceProtos.TestProtobufRpcProto.BlockingInterface() {
107
108 @Override
109 public EmptyResponseProto ping(RpcController controller,
110 EmptyRequestProto request) throws ServiceException {
111
112 return null;
113 }
114
115 @Override
116 public EmptyResponseProto error(RpcController controller,
117 EmptyRequestProto request) throws ServiceException {
118
119 return null;
120 }
121
122 @Override
123 public EchoResponseProto echo(RpcController controller, EchoRequestProto request)
124 throws ServiceException {
125 if (controller instanceof PayloadCarryingRpcController) {
126 PayloadCarryingRpcController pcrc = (PayloadCarryingRpcController)controller;
127
128
129
130 CellScanner cellScanner = pcrc.cellScanner();
131 List<Cell> list = null;
132 if (cellScanner != null) {
133 list = new ArrayList<Cell>();
134 try {
135 while(cellScanner.advance()) {
136 list.add(cellScanner.current());
137 }
138 } catch (IOException e) {
139 throw new ServiceException(e);
140 }
141 }
142 cellScanner = CellUtil.createCellScanner(list);
143 ((PayloadCarryingRpcController)controller).setCellScanner(cellScanner);
144 }
145 return EchoResponseProto.newBuilder().setMessage(request.getMessage()).build();
146 }
147 });
148
149
150
151
152
153 private static class TestRpcServer extends RpcServer {
154
155 TestRpcServer() throws IOException {
156 this(new FifoRpcScheduler(CONF, 1));
157 }
158
159 TestRpcServer(RpcScheduler scheduler) throws IOException {
160 super(null, "testRpcServer",
161 Lists.newArrayList(new BlockingServiceAndInterface(SERVICE, null)),
162 new InetSocketAddress("localhost", 0), CONF, scheduler);
163 }
164
165 @Override
166 public Pair<Message, CellScanner> call(BlockingService service,
167 MethodDescriptor md, Message param, CellScanner cellScanner,
168 long receiveTime, MonitoredRPCHandler status) throws IOException {
169 return super.call(service, md, param, cellScanner, receiveTime, status);
170 }
171 }
172
173
174
175
176
177
178 @Test
179 public void testNoCodec() throws InterruptedException, IOException {
180 Configuration conf = HBaseConfiguration.create();
181 RpcClient client = new RpcClient(conf, HConstants.CLUSTER_ID_DEFAULT) {
182 @Override
183 Codec getCodec() {
184 return null;
185 }
186 };
187 TestRpcServer rpcServer = new TestRpcServer();
188 try {
189 rpcServer.start();
190 InetSocketAddress address = rpcServer.getListenerAddress();
191 MethodDescriptor md = SERVICE.getDescriptorForType().findMethodByName("echo");
192 final String message = "hello";
193 EchoRequestProto param = EchoRequestProto.newBuilder().setMessage(message).build();
194 Pair<Message, CellScanner> r = client.call(md, param, null,
195 md.getOutputType().toProto(), User.getCurrent(), address, 0);
196 assertTrue(r.getSecond() == null);
197
198 assertTrue(r.getFirst().toString().contains(message));
199 } finally {
200 client.stop();
201 rpcServer.stop();
202 }
203 }
204
205
206
207
208
209
210
211
212
213
214 @Test
215 public void testCompressCellBlock()
216 throws IOException, InterruptedException, SecurityException, NoSuchMethodException {
217 Configuration conf = new Configuration(HBaseConfiguration.create());
218 conf.set("hbase.client.rpc.compressor", GzipCodec.class.getCanonicalName());
219 doSimpleTest(conf, new RpcClient(conf, HConstants.CLUSTER_ID_DEFAULT));
220 }
221
222 private void doSimpleTest(final Configuration conf, final RpcClient client)
223 throws InterruptedException, IOException {
224 TestRpcServer rpcServer = new TestRpcServer();
225 List<Cell> cells = new ArrayList<Cell>();
226 int count = 3;
227 for (int i = 0; i < count; i++) cells.add(CELL);
228 try {
229 rpcServer.start();
230 MethodDescriptor md = SERVICE.getDescriptorForType().findMethodByName("echo");
231 EchoRequestProto param = EchoRequestProto.newBuilder().setMessage("hello").build();
232 InetSocketAddress address = rpcServer.getListenerAddress();
233 if (address == null) {
234 throw new IOException("Listener channel is closed");
235 }
236 Pair<Message, CellScanner> r = client.call(md, param, CellUtil.createCellScanner(cells),
237 md.getOutputType().toProto(), User.getCurrent(), address, 0);
238 int index = 0;
239 while (r.getSecond().advance()) {
240 assertTrue(CELL.equals(r.getSecond().current()));
241 index++;
242 }
243 assertEquals(count, index);
244 } finally {
245 client.stop();
246 rpcServer.stop();
247 }
248 }
249
250 @Test
251 public void testRTEDuringConnectionSetup() throws Exception {
252 Configuration conf = HBaseConfiguration.create();
253 SocketFactory spyFactory = spy(NetUtils.getDefaultSocketFactory(conf));
254 Mockito.doAnswer(new Answer<Socket>() {
255 @Override
256 public Socket answer(InvocationOnMock invocation) throws Throwable {
257 Socket s = spy((Socket)invocation.callRealMethod());
258 doThrow(new RuntimeException("Injected fault")).when(s).setSoTimeout(anyInt());
259 return s;
260 }
261 }).when(spyFactory).createSocket();
262
263 TestRpcServer rpcServer = new TestRpcServer();
264 RpcClient client = new RpcClient(conf, HConstants.CLUSTER_ID_DEFAULT, spyFactory);
265 try {
266 rpcServer.start();
267 InetSocketAddress address = rpcServer.getListenerAddress();
268 MethodDescriptor md = SERVICE.getDescriptorForType().findMethodByName("echo");
269 EchoRequestProto param = EchoRequestProto.newBuilder().setMessage("hello").build();
270 client.call(md, param, null, null, User.getCurrent(), address, 0);
271 fail("Expected an exception to have been thrown!");
272 } catch (Exception e) {
273 LOG.info("Caught expected exception: " + e.toString());
274 assertTrue(StringUtils.stringifyException(e).contains("Injected fault"));
275 } finally {
276 client.stop();
277 rpcServer.stop();
278 }
279 }
280
281
282 @Test
283 public void testRpcScheduler() throws IOException, InterruptedException {
284 RpcScheduler scheduler = spy(new FifoRpcScheduler(CONF, 1));
285 RpcServer rpcServer = new TestRpcServer(scheduler);
286 verify(scheduler).init((RpcScheduler.Context) anyObject());
287 RpcClient client = new RpcClient(CONF, HConstants.CLUSTER_ID_DEFAULT);
288 try {
289 rpcServer.start();
290 verify(scheduler).start();
291 MethodDescriptor md = SERVICE.getDescriptorForType().findMethodByName("echo");
292 EchoRequestProto param = EchoRequestProto.newBuilder().setMessage("hello").build();
293 for (int i = 0; i < 10; i++) {
294 client.call(md, param, CellUtil.createCellScanner(ImmutableList.of(CELL)),
295 md.getOutputType().toProto(), User.getCurrent(), rpcServer.getListenerAddress(), 0);
296 }
297 verify(scheduler, times(10)).dispatch((CallRunner) anyObject());
298 } finally {
299 rpcServer.stop();
300 verify(scheduler).stop();
301 }
302 }
303
304 public static void main(String[] args)
305 throws IOException, SecurityException, NoSuchMethodException, InterruptedException {
306 if (args.length != 2) {
307 System.out.println("Usage: TestIPC <CYCLES> <CELLS_PER_CYCLE>");
308 return;
309 }
310
311
312 int cycles = Integer.parseInt(args[0]);
313 int cellcount = Integer.parseInt(args[1]);
314 Configuration conf = HBaseConfiguration.create();
315 TestRpcServer rpcServer = new TestRpcServer();
316 MethodDescriptor md = SERVICE.getDescriptorForType().findMethodByName("echo");
317 EchoRequestProto param = EchoRequestProto.newBuilder().setMessage("hello").build();
318 RpcClient client = new RpcClient(conf, HConstants.CLUSTER_ID_DEFAULT);
319 KeyValue kv = KeyValueUtil.ensureKeyValue(BIG_CELL);
320 Put p = new Put(kv.getRow());
321 for (int i = 0; i < cellcount; i++) {
322 p.add(kv);
323 }
324 RowMutations rm = new RowMutations(kv.getRow());
325 rm.add(p);
326 try {
327 rpcServer.start();
328 long startTime = System.currentTimeMillis();
329 User user = User.getCurrent();
330 InetSocketAddress address = rpcServer.getListenerAddress();
331 if (address == null) {
332 throw new IOException("Listener channel is closed");
333 }
334 for (int i = 0; i < cycles; i++) {
335 List<CellScannable> cells = new ArrayList<CellScannable>();
336
337 ClientProtos.RegionAction.Builder builder = RequestConverter.buildNoDataRegionAction(
338 HConstants.EMPTY_BYTE_ARRAY, rm, cells,
339 RegionAction.newBuilder(),
340 ClientProtos.Action.newBuilder(),
341 MutationProto.newBuilder());
342 builder.setRegion(RegionSpecifier.newBuilder().setType(RegionSpecifierType.REGION_NAME).
343 setValue(ByteString.copyFrom(HRegionInfo.FIRST_META_REGIONINFO.getEncodedNameAsBytes())));
344 if (i % 100000 == 0) {
345 LOG.info("" + i);
346
347
348
349 }
350 CellScanner cellScanner = CellUtil.createCellScanner(cells);
351 Pair<Message, CellScanner> response =
352 client.call(md, builder.build(), cellScanner, param, user, address, 0,
353 HConstants.NORMAL_QOS, new MetricsConnection.CallStats());
354
355
356
357
358
359
360 }
361 LOG.info("Cycled " + cycles + " time(s) with " + cellcount + " cell(s) in " +
362 (System.currentTimeMillis() - startTime) + "ms");
363 } finally {
364 client.stop();
365 rpcServer.stop();
366 }
367 }
368 }