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