1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.ipc;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertTrue;
22 import static org.junit.Assert.fail;
23 import static org.mockito.Matchers.anyObject;
24 import static org.mockito.Mockito.spy;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.internal.verification.VerificationModeFactory.times;
27
28 import java.io.IOException;
29 import java.net.ConnectException;
30 import java.net.InetSocketAddress;
31 import java.net.SocketTimeoutException;
32 import java.util.ArrayList;
33 import java.util.List;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.apache.hadoop.conf.Configuration;
38 import org.apache.hadoop.hbase.Cell;
39 import org.apache.hadoop.hbase.CellScanner;
40 import org.apache.hadoop.hbase.CellUtil;
41 import org.apache.hadoop.hbase.HBaseConfiguration;
42 import org.apache.hadoop.hbase.KeyValue;
43 import org.apache.hadoop.hbase.exceptions.ConnectionClosingException;
44 import org.apache.hadoop.hbase.ipc.protobuf.generated.TestProtos.EchoRequestProto;
45 import org.apache.hadoop.hbase.ipc.protobuf.generated.TestProtos.EchoResponseProto;
46 import org.apache.hadoop.hbase.ipc.protobuf.generated.TestProtos.EmptyRequestProto;
47 import org.apache.hadoop.hbase.ipc.protobuf.generated.TestProtos.EmptyResponseProto;
48 import org.apache.hadoop.hbase.ipc.protobuf.generated.TestRpcServiceProtos;
49 import org.apache.hadoop.hbase.monitoring.MonitoredRPCHandler;
50 import org.apache.hadoop.hbase.security.User;
51 import org.apache.hadoop.hbase.util.Bytes;
52 import org.apache.hadoop.hbase.util.Pair;
53 import org.apache.hadoop.io.compress.GzipCodec;
54 import org.apache.hadoop.util.StringUtils;
55 import org.junit.Test;
56
57 import com.google.common.collect.ImmutableList;
58 import com.google.common.collect.Lists;
59 import com.google.protobuf.BlockingService;
60 import com.google.protobuf.Descriptors.MethodDescriptor;
61 import com.google.protobuf.Message;
62 import com.google.protobuf.RpcController;
63 import com.google.protobuf.ServiceException;
64
65
66
67
68 public abstract class AbstractTestIPC {
69
70 private static final Log LOG = LogFactory.getLog(AbstractTestIPC.class);
71
72 private static byte[] CELL_BYTES = Bytes.toBytes("xyz");
73 private static KeyValue CELL = new KeyValue(CELL_BYTES, CELL_BYTES, CELL_BYTES, CELL_BYTES);
74 static byte[] BIG_CELL_BYTES = new byte[10 * 1024];
75 static KeyValue BIG_CELL = new KeyValue(CELL_BYTES, CELL_BYTES, CELL_BYTES, BIG_CELL_BYTES);
76 static final Configuration CONF = HBaseConfiguration.create();
77
78
79
80
81 static final BlockingService SERVICE =
82 TestRpcServiceProtos.TestProtobufRpcProto
83 .newReflectiveBlockingService(new TestRpcServiceProtos.TestProtobufRpcProto.BlockingInterface() {
84
85 @Override
86 public EmptyResponseProto ping(RpcController controller, EmptyRequestProto request)
87 throws ServiceException {
88 return null;
89 }
90
91 @Override
92 public EmptyResponseProto error(RpcController controller, EmptyRequestProto request)
93 throws ServiceException {
94 return null;
95 }
96
97 @Override
98 public EchoResponseProto echo(RpcController controller, EchoRequestProto request)
99 throws ServiceException {
100 if (controller instanceof PayloadCarryingRpcController) {
101 PayloadCarryingRpcController pcrc = (PayloadCarryingRpcController) controller;
102
103
104
105
106
107 CellScanner cellScanner = pcrc.cellScanner();
108 List<Cell> list = null;
109 if (cellScanner != null) {
110 list = new ArrayList<Cell>();
111 try {
112 while (cellScanner.advance()) {
113 list.add(cellScanner.current());
114 }
115 } catch (IOException e) {
116 throw new ServiceException(e);
117 }
118 }
119 cellScanner = CellUtil.createCellScanner(list);
120 ((PayloadCarryingRpcController) controller).setCellScanner(cellScanner);
121 }
122 return EchoResponseProto.newBuilder().setMessage(request.getMessage()).build();
123 }
124 });
125
126
127
128
129
130 static class TestRpcServer extends RpcServer {
131
132 TestRpcServer() throws IOException {
133 this(new FifoRpcScheduler(CONF, 1));
134 }
135
136 TestRpcServer(RpcScheduler scheduler) throws IOException {
137 super(null, "testRpcServer", Lists
138 .newArrayList(new BlockingServiceAndInterface(SERVICE, null)), new InetSocketAddress(
139 "localhost", 0), CONF, scheduler);
140 }
141
142 @Override
143 public Pair<Message, CellScanner> call(BlockingService service, MethodDescriptor md,
144 Message param, CellScanner cellScanner, long receiveTime, MonitoredRPCHandler status)
145 throws IOException {
146 return super.call(service, md, param, cellScanner, receiveTime, status);
147 }
148 }
149
150 protected abstract AbstractRpcClient createRpcClientNoCodec(Configuration conf);
151
152
153
154
155
156
157 @Test
158 public void testNoCodec() throws InterruptedException, IOException {
159 Configuration conf = HBaseConfiguration.create();
160 AbstractRpcClient client = createRpcClientNoCodec(conf);
161 TestRpcServer rpcServer = new TestRpcServer();
162 try {
163 rpcServer.start();
164 MethodDescriptor md = SERVICE.getDescriptorForType().findMethodByName("echo");
165 final String message = "hello";
166 EchoRequestProto param = EchoRequestProto.newBuilder().setMessage(message).build();
167 InetSocketAddress address = rpcServer.getListenerAddress();
168 if (address == null) {
169 throw new IOException("Listener channel is closed");
170 }
171 Pair<Message, CellScanner> r =
172 client.call(null, md, param, md.getOutputType().toProto(), User.getCurrent(), address);
173 assertTrue(r.getSecond() == null);
174
175 assertTrue(r.getFirst().toString().contains(message));
176 } finally {
177 client.close();
178 rpcServer.stop();
179 }
180 }
181
182 protected abstract AbstractRpcClient createRpcClient(Configuration conf);
183
184
185
186
187
188
189
190
191
192
193 @Test
194 public void testCompressCellBlock() throws IOException, InterruptedException, SecurityException,
195 NoSuchMethodException, ServiceException {
196 Configuration conf = new Configuration(HBaseConfiguration.create());
197 conf.set("hbase.client.rpc.compressor", GzipCodec.class.getCanonicalName());
198 List<Cell> cells = new ArrayList<Cell>();
199 int count = 3;
200 for (int i = 0; i < count; i++) {
201 cells.add(CELL);
202 }
203 AbstractRpcClient client = createRpcClient(conf);
204 TestRpcServer rpcServer = new TestRpcServer();
205 try {
206 rpcServer.start();
207 MethodDescriptor md = SERVICE.getDescriptorForType().findMethodByName("echo");
208 EchoRequestProto param = EchoRequestProto.newBuilder().setMessage("hello").build();
209 PayloadCarryingRpcController pcrc =
210 new PayloadCarryingRpcController(CellUtil.createCellScanner(cells));
211 InetSocketAddress address = rpcServer.getListenerAddress();
212 if (address == null) {
213 throw new IOException("Listener channel is closed");
214 }
215 Pair<Message, CellScanner> r =
216 client.call(pcrc, md, param, md.getOutputType().toProto(), User.getCurrent(), address);
217 int index = 0;
218 while (r.getSecond().advance()) {
219 assertTrue(CELL.equals(r.getSecond().current()));
220 index++;
221 }
222 assertEquals(count, index);
223 } finally {
224 client.close();
225 rpcServer.stop();
226 }
227 }
228
229 protected abstract AbstractRpcClient createRpcClientRTEDuringConnectionSetup(Configuration conf)
230 throws IOException;
231
232 @Test
233 public void testRTEDuringConnectionSetup() throws Exception {
234 Configuration conf = HBaseConfiguration.create();
235 TestRpcServer rpcServer = new TestRpcServer();
236 AbstractRpcClient client = createRpcClientRTEDuringConnectionSetup(conf);
237 try {
238 rpcServer.start();
239 MethodDescriptor md = SERVICE.getDescriptorForType().findMethodByName("echo");
240 EchoRequestProto param = EchoRequestProto.newBuilder().setMessage("hello").build();
241 InetSocketAddress address = rpcServer.getListenerAddress();
242 if (address == null) {
243 throw new IOException("Listener channel is closed");
244 }
245 client.call(null, md, param, null, User.getCurrent(), address);
246 fail("Expected an exception to have been thrown!");
247 } catch (Exception e) {
248 LOG.info("Caught expected exception: " + e.toString());
249 assertTrue(StringUtils.stringifyException(e).contains("Injected fault"));
250 } finally {
251 client.close();
252 rpcServer.stop();
253 }
254 }
255
256
257 @Test
258 public void testRpcScheduler() throws IOException, InterruptedException {
259 RpcScheduler scheduler = spy(new FifoRpcScheduler(CONF, 1));
260 RpcServer rpcServer = new TestRpcServer(scheduler);
261 verify(scheduler).init((RpcScheduler.Context) anyObject());
262 AbstractRpcClient client = createRpcClient(CONF);
263 try {
264 rpcServer.start();
265 verify(scheduler).start();
266 MethodDescriptor md = SERVICE.getDescriptorForType().findMethodByName("echo");
267 EchoRequestProto param = EchoRequestProto.newBuilder().setMessage("hello").build();
268 InetSocketAddress address = rpcServer.getListenerAddress();
269 if (address == null) {
270 throw new IOException("Listener channel is closed");
271 }
272 for (int i = 0; i < 10; i++) {
273 client.call(
274 new PayloadCarryingRpcController(
275 CellUtil.createCellScanner(ImmutableList.<Cell> of(CELL))), md, param, md
276 .getOutputType().toProto(), User.getCurrent(), address);
277 }
278 verify(scheduler, times(10)).dispatch((CallRunner) anyObject());
279 } finally {
280 rpcServer.stop();
281 verify(scheduler).stop();
282 }
283 }
284
285 @Test
286 public void testWrapException() throws Exception {
287 AbstractRpcClient client =
288 (AbstractRpcClient) RpcClientFactory.createClient(CONF, "AbstractTestIPC");
289 final InetSocketAddress address = InetSocketAddress.createUnresolved("localhost", 0);
290 assertTrue(client.wrapException(address, new ConnectException()) instanceof ConnectException);
291 assertTrue(client.wrapException(address,
292 new SocketTimeoutException()) instanceof SocketTimeoutException);
293 assertTrue(client.wrapException(address, new ConnectionClosingException(
294 "Test AbstractRpcClient#wrapException")) instanceof ConnectionClosingException);
295 assertTrue(client
296 .wrapException(address, new CallTimeoutException("Test AbstractRpcClient#wrapException"))
297 .getCause() instanceof CallTimeoutException);
298 }
299 }