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 java.io.IOException;
21
22 import org.apache.hadoop.hbase.CellScanner;
23 import org.apache.hadoop.hbase.classification.InterfaceAudience;
24 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
25 import org.apache.hadoop.hbase.protobuf.generated.RPCProtos;
26 import org.apache.hadoop.ipc.RemoteException;
27
28 import com.google.protobuf.Message;
29
30 import io.netty.buffer.ByteBuf;
31 import io.netty.buffer.ByteBufInputStream;
32 import io.netty.channel.ChannelHandlerContext;
33 import io.netty.channel.SimpleChannelInboundHandler;
34
35
36
37
38 @InterfaceAudience.Private
39 public class AsyncServerResponseHandler extends SimpleChannelInboundHandler<ByteBuf> {
40 private final AsyncRpcChannel channel;
41
42
43
44
45
46 public AsyncServerResponseHandler(AsyncRpcChannel channel) {
47 this.channel = channel;
48 }
49
50 @Override
51 protected void channelRead0(ChannelHandlerContext ctx, ByteBuf inBuffer) throws Exception {
52 ByteBufInputStream in = new ByteBufInputStream(inBuffer);
53 int totalSize = inBuffer.readableBytes();
54
55 RPCProtos.ResponseHeader responseHeader = RPCProtos.ResponseHeader.parseDelimitedFrom(in);
56 int id = responseHeader.getCallId();
57 AsyncCall call = channel.removePendingCall(id);
58 if (call == null) {
59
60
61
62
63
64 int readSoFar = IPCUtil.getTotalSizeWhenWrittenDelimited(responseHeader);
65 int whatIsLeftToRead = totalSize - readSoFar;
66
67
68
69
70 inBuffer.skipBytes(whatIsLeftToRead);
71 return;
72 }
73
74 if (responseHeader.hasException()) {
75 RPCProtos.ExceptionResponse exceptionResponse = responseHeader.getException();
76 RemoteException re = createRemoteException(exceptionResponse);
77 if (exceptionResponse.getExceptionClassName()
78 .equals(FatalConnectionException.class.getName())) {
79 channel.close(re);
80 } else {
81 call.setFailed(re);
82 }
83 } else {
84 Message value = null;
85
86 if (call.responseDefaultType != null) {
87 Message.Builder builder = call.responseDefaultType.newBuilderForType();
88 ProtobufUtil.mergeDelimitedFrom(builder, in);
89 value = builder.build();
90 }
91 CellScanner cellBlockScanner = null;
92 if (responseHeader.hasCellBlockMeta()) {
93 int size = responseHeader.getCellBlockMeta().getLength();
94 byte[] cellBlock = new byte[size];
95 inBuffer.readBytes(cellBlock, 0, cellBlock.length);
96 cellBlockScanner = channel.client.createCellScanner(cellBlock);
97 }
98 call.setSuccess(value, cellBlockScanner);
99 call.callStats.setResponseSizeBytes(totalSize);
100 }
101 }
102
103 @Override
104 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
105 channel.close(cause);
106 }
107
108 @Override
109 public void channelInactive(ChannelHandlerContext ctx) throws Exception {
110 channel.close(new IOException("connection closed"));
111 }
112
113
114
115
116
117 private RemoteException createRemoteException(final RPCProtos.ExceptionResponse e) {
118 String innerExceptionClassName = e.getExceptionClassName();
119 boolean doNotRetry = e.getDoNotRetry();
120 return e.hasHostname() ?
121
122 new RemoteWithExtrasException(innerExceptionClassName, e.getStackTrace(), e.getHostname(),
123 e.getPort(), doNotRetry)
124 : new RemoteWithExtrasException(innerExceptionClassName, e.getStackTrace(), doNotRetry);
125 }
126 }