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 org.apache.hadoop.hbase.CellScanner;
23  import org.apache.hadoop.hbase.classification.InterfaceAudience;
24  import org.apache.hadoop.hbase.client.MetricsConnection;
25  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
26  import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
27  
28  import java.io.IOException;
29  
30  /** A call waiting for a value. */
31  @InterfaceAudience.Private
32  public class Call {
33    final int id;                                 // call id
34    final Message param;                          // rpc request method param object
35    /**
36     * Optionally has cells when making call.  Optionally has cells set on response.  Used
37     * passing cells to the rpc and receiving the response.
38     */
39    CellScanner cells;
40    Message response;                             // value, null if error
41    // The return type.  Used to create shell into which we deserialize the response if any.
42    Message responseDefaultType;
43    IOException error;                            // exception, null if value
44    volatile boolean done;                                 // true when call is done
45    final Descriptors.MethodDescriptor md;
46    final int timeout; // timeout in millisecond for this call; 0 means infinite.
47    final MetricsConnection.CallStats callStats;
48  
49    protected Call(int id, final Descriptors.MethodDescriptor md, Message param,
50        final CellScanner cells, final Message responseDefaultType, int timeout,
51        MetricsConnection.CallStats callStats) {
52      this.param = param;
53      this.md = md;
54      this.cells = cells;
55      this.callStats = callStats;
56      this.callStats.setStartTime(EnvironmentEdgeManager.currentTime());
57      this.responseDefaultType = responseDefaultType;
58      this.id = id;
59      this.timeout = timeout;
60    }
61  
62    /**
63     * Check if the call did timeout. Set an exception (includes a notify) if it's the case.
64     * @return true if the call is on timeout, false otherwise.
65     */
66    public boolean checkAndSetTimeout() {
67      if (timeout == 0){
68        return false;
69      }
70  
71      long waitTime = EnvironmentEdgeManager.currentTime() - getStartTime();
72      if (waitTime >= timeout) {
73        IOException ie = new CallTimeoutException("Call id=" + id +
74            ", waitTime=" + waitTime + ", operationTimeout=" + timeout + " expired.");
75        setException(ie); // includes a notify
76        return true;
77      } else {
78        return false;
79      }
80    }
81  
82    public int remainingTime() {
83      if (timeout == 0) {
84        return Integer.MAX_VALUE;
85      }
86  
87      int remaining = timeout - (int) (EnvironmentEdgeManager.currentTime() - getStartTime());
88      return remaining > 0 ? remaining : 0;
89    }
90  
91    @Override
92    public String toString() {
93      return "callId: " + this.id + " methodName: " + this.md.getName() + " param {" +
94        (this.param != null? ProtobufUtil.getShortTextFormat(this.param): "") + "}";
95    }
96  
97    /** Indicate when the call is complete and the
98     * value or error are available.  Notifies by default.  */
99    protected synchronized void callComplete() {
100     this.done = true;
101     notify();                                 // notify caller
102   }
103 
104   /** Set the exception when there is an error.
105    * Notify the caller the call is done.
106    *
107    * @param error exception thrown by the call; either local or remote
108    */
109   public void setException(IOException error) {
110     this.error = error;
111     callComplete();
112   }
113 
114   /**
115    * Set the return value when there is no error.
116    * Notify the caller the call is done.
117    *
118    * @param response return value of the call.
119    * @param cells Can be null
120    */
121   public void setResponse(Message response, final CellScanner cells) {
122     this.response = response;
123     this.cells = cells;
124     callComplete();
125   }
126 
127   public long getStartTime() {
128     return this.callStats.getStartTime();
129   }
130 }