1 package org.apache.hadoop.hbase.ipc;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.nio.channels.ClosedChannelException;
20
21 import org.apache.hadoop.classification.InterfaceAudience;
22 import org.apache.hadoop.hbase.CellScanner;
23 import org.apache.hadoop.hbase.ipc.RpcServer.Call;
24 import org.apache.hadoop.hbase.monitoring.MonitoredRPCHandler;
25 import org.apache.hadoop.hbase.monitoring.TaskMonitor;
26 import org.apache.hadoop.hbase.security.UserProvider;
27 import org.apache.hadoop.hbase.util.Pair;
28 import org.apache.hadoop.security.UserGroupInformation;
29 import org.apache.hadoop.util.StringUtils;
30 import org.cloudera.htrace.Trace;
31 import org.cloudera.htrace.TraceScope;
32
33 import com.google.protobuf.Message;
34
35
36
37
38
39
40 @InterfaceAudience.Private
41 public class CallRunner {
42 private Call call;
43 private RpcServerInterface rpcServer;
44 private MonitoredRPCHandler status;
45 private UserProvider userProvider;
46
47
48
49
50
51
52
53
54
55 CallRunner(final RpcServerInterface rpcServer, final Call call, UserProvider userProvider) {
56 this.call = call;
57 this.rpcServer = rpcServer;
58
59 this.rpcServer.addCallSize(call.getSize());
60 this.status = getStatus();
61 this.userProvider = userProvider;
62 }
63
64 public Call getCall() {
65 return call;
66 }
67
68
69
70
71 private void cleanup() {
72 this.call = null;
73 this.rpcServer = null;
74 this.status = null;
75 this.userProvider = null;
76 }
77
78 public void run() {
79 try {
80 if (!call.connection.channel.isOpen()) {
81 if (RpcServer.LOG.isDebugEnabled()) {
82 RpcServer.LOG.debug(Thread.currentThread().getName() + ": skipped " + call);
83 }
84 return;
85 }
86 this.status.setStatus("Setting up call");
87 this.status.setConnection(call.connection.getHostAddress(), call.connection.getRemotePort());
88 if (RpcServer.LOG.isDebugEnabled()) {
89 UserGroupInformation remoteUser = call.connection.user;
90 RpcServer.LOG.debug(call.toShortString() + " executing as " +
91 ((remoteUser == null) ? "NULL principal" : remoteUser.getUserName()));
92 }
93 Throwable errorThrowable = null;
94 String error = null;
95 Pair<Message, CellScanner> resultPair = null;
96 RpcServer.CurCall.set(call);
97 TraceScope traceScope = null;
98 try {
99 if (!this.rpcServer.isStarted()) {
100 throw new ServerNotRunningYetException("Server is not running yet");
101 }
102 if (call.tinfo != null) {
103 traceScope = Trace.startSpan(call.toTraceString(), call.tinfo);
104 }
105 RequestContext.set(userProvider.create(call.connection.user), RpcServer.getRemoteIp(),
106 call.connection.service);
107
108 resultPair = this.rpcServer.call(call.service, call.md, call.param, call.cellScanner,
109 call.timestamp, this.status);
110 } catch (Throwable e) {
111 RpcServer.LOG.debug(Thread.currentThread().getName() + ": " + call.toShortString(), e);
112 errorThrowable = e;
113 error = StringUtils.stringifyException(e);
114 } finally {
115 if (traceScope != null) {
116 traceScope.close();
117 }
118
119
120 RequestContext.clear();
121 }
122 RpcServer.CurCall.set(null);
123
124
125 if (!call.isDelayed() || !call.isReturnValueDelayed()) {
126 Message param = resultPair != null ? resultPair.getFirst() : null;
127 CellScanner cells = resultPair != null ? resultPair.getSecond() : null;
128 call.setResponse(param, cells, errorThrowable, error);
129 }
130 call.sendResponseIfReady();
131 this.status.markComplete("Sent response");
132 this.status.pause("Waiting for a call");
133 } catch (OutOfMemoryError e) {
134 if (this.rpcServer.getErrorHandler() != null) {
135 if (this.rpcServer.getErrorHandler().checkOOME(e)) {
136 RpcServer.LOG.info(Thread.currentThread().getName() + ": exiting on OutOfMemoryError");
137 return;
138 }
139 } else {
140
141 throw e;
142 }
143 } catch (ClosedChannelException cce) {
144 RpcServer.LOG.warn(Thread.currentThread().getName() + ": caught a ClosedChannelException, " +
145 "this means that the server was processing a " +
146 "request but the client went away. The error message was: " +
147 cce.getMessage());
148 } catch (Exception e) {
149 RpcServer.LOG.warn(Thread.currentThread().getName()
150 + ": caught: " + StringUtils.stringifyException(e));
151 } finally {
152
153 this.rpcServer.addCallSize(call.getSize() * -1);
154 cleanup();
155 }
156 }
157
158 MonitoredRPCHandler getStatus() {
159
160 MonitoredRPCHandler status = RpcServer.MONITORED_RPC.get();
161 if (status != null) {
162 return status;
163 }
164 status = TaskMonitor.get().createRPCStatus(Thread.currentThread().getName());
165 status.pause("Waiting for a call");
166 RpcServer.MONITORED_RPC.set(status);
167 return status;
168 }
169 }