View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.ipc;
19  
20  import com.google.protobuf.Descriptors;
21  import com.google.protobuf.Message;
22  import com.google.protobuf.RpcCallback;
23  
24  import io.netty.util.Timeout;
25  
26  import java.io.IOException;
27  
28  import org.apache.hadoop.hbase.CellScanner;
29  import org.apache.hadoop.hbase.classification.InterfaceAudience;
30  import org.apache.hadoop.hbase.client.MetricsConnection;
31  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
32  import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
33  import org.apache.htrace.Span;
34  import org.apache.htrace.Trace;
35  
36  /** A call waiting for a value. */
37  @InterfaceAudience.Private
38  class Call {
39    final int id; // call id
40    final Message param; // rpc request method param object
41    /**
42     * Optionally has cells when making call. Optionally has cells set on response. Used passing cells
43     * to the rpc and receiving the response.
44     */
45    CellScanner cells;
46    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "IS2_INCONSISTENT_SYNC",
47        justification = "Direct access is only allowed after done")
48    Message response; // value, null if error
49    // The return type. Used to create shell into which we deserialize the response if any.
50    Message responseDefaultType;
51    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "IS2_INCONSISTENT_SYNC",
52      justification = "Direct access is only allowed after done")
53    IOException error; // exception, null if value
54    private boolean done; // true when call is done
55    final Descriptors.MethodDescriptor md;
56    final int timeout; // timeout in millisecond for this call; 0 means infinite.
57    final int priority;
58    final MetricsConnection.CallStats callStats;
59    final RpcCallback<Call> callback;
60    final Span span;
61    Timeout timeoutTask;
62  
63    protected Call(int id, final Descriptors.MethodDescriptor md, Message param,
64        final CellScanner cells, final Message responseDefaultType, int timeout, int priority,
65        RpcCallback<Call> callback, MetricsConnection.CallStats callStats) {
66      this.param = param;
67      this.md = md;
68      this.cells = cells;
69      this.callStats = callStats;
70      this.callStats.setStartTime(EnvironmentEdgeManager.currentTime());
71      this.responseDefaultType = responseDefaultType;
72      this.id = id;
73      this.timeout = timeout;
74      this.priority = priority;
75      this.callback = callback;
76      this.span = Trace.currentSpan();
77    }
78  
79    @Override
80    public String toString() {
81      return "callId: " + this.id + " methodName: " + this.md.getName() + " param {"
82          + (this.param != null ? ProtobufUtil.getShortTextFormat(this.param) : "") + "}";
83    }
84  
85    /**
86     * called from timeoutTask, prevent self cancel
87     */
88    public void setTimeout(IOException error) {
89      synchronized (this) {
90        if (done) {
91          return;
92        }
93        this.done = true;
94        this.error = error;
95      }
96      callback.run(this);
97    }
98  
99    private void callComplete() {
100     if (timeoutTask != null) {
101       timeoutTask.cancel();
102     }
103     callback.run(this);
104   }
105 
106   /**
107    * Set the exception when there is an error. Notify the caller the call is done.
108    * @param error exception thrown by the call; either local or remote
109    */
110   public void setException(IOException error) {
111     synchronized (this) {
112       if (done) {
113         return;
114       }
115       this.done = true;
116       this.error = error;
117     }
118     callComplete();
119   }
120 
121   /**
122    * Set the return value when there is no error. Notify the caller the call is done.
123    * @param response return value of the call.
124    * @param cells Can be null
125    */
126   public void setResponse(Message response, final CellScanner cells) {
127     synchronized (this) {
128       if (done) {
129         return;
130       }
131       this.done = true;
132       this.response = response;
133       this.cells = cells;
134     }
135     callComplete();
136   }
137 
138   public synchronized boolean isDone() {
139     return done;
140   }
141 
142   public long getStartTime() {
143     return this.callStats.getStartTime();
144   }
145 }