View Javadoc

1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase.client;
22  
23  import java.io.IOException;
24  import java.net.SocketTimeoutException;
25  import java.util.concurrent.Callable;
26  
27  import org.apache.hadoop.hbase.HConstants;
28  import org.apache.hadoop.hbase.HRegionLocation;
29  import org.apache.hadoop.hbase.ipc.HBaseRPC;
30  import org.apache.hadoop.hbase.ipc.HRegionInterface;
31  import org.apache.hadoop.hbase.util.Bytes;
32  
33  /**
34   * Abstract class that implements {@link Callable}.  Implementation stipulates
35   * return type and method we actually invoke on remote Server.  Usually
36   * used inside a try/catch that fields usual connection failures all wrapped
37   * up in a retry loop.
38   * <p>Call {@link #connect(boolean)} to connect to server hosting region
39   * that contains the passed row in the passed table before invoking
40   * {@link #call()}.
41   * @see HConnection#getRegionServerWithoutRetries(ServerCallable)
42   * @param <T> the class that the ServerCallable handles
43   */
44  public abstract class ServerCallable<T> implements Callable<T> {
45    protected final HConnection connection;
46    protected final byte [] tableName;
47    protected final byte [] row;
48    protected HRegionLocation location;
49    protected HRegionInterface server;
50    protected int callTimeout;
51    protected long startTime, endTime;
52  
53    /**
54     * @param connection Connection to use.
55     * @param tableName Table name to which <code>row</code> belongs.
56     * @param row The row we want in <code>tableName</code>.
57     */
58    public ServerCallable(HConnection connection, byte [] tableName, byte [] row) {
59      this(connection, tableName, row, HConstants.DEFAULT_HBASE_CLIENT_OPERATION_TIMEOUT);
60    }
61  
62    public ServerCallable(HConnection connection, byte [] tableName, byte [] row, int callTimeout) {
63      this.connection = connection;
64      this.tableName = tableName;
65      this.row = row;
66      this.callTimeout = callTimeout;
67    }
68  
69    /**
70     * Connect to the server hosting region with row from tablename.
71     * @param reload Set this to true if connection should re-find the region
72     * @throws IOException e
73     */
74    public void connect(final boolean reload) throws IOException {
75      this.location = connection.getRegionLocation(tableName, row, reload);
76      this.server = connection.getHRegionConnection(location.getHostname(),
77        location.getPort());
78    }
79  
80    /** @return the server name
81     * @deprecated Just use {@link #toString()} instead.
82     */
83    public String getServerName() {
84      if (location == null) return null;
85      return location.getHostnamePort();
86    }
87  
88    /** @return the region name
89     * @deprecated Just use {@link #toString()} instead.
90     */
91    public byte[] getRegionName() {
92      if (location == null) return null;
93      return location.getRegionInfo().getRegionName();
94    }
95  
96    /** @return the row
97     * @deprecated Just use {@link #toString()} instead.
98     */
99    public byte [] getRow() {
100     return row;
101   }
102 
103   public void beforeCall() {
104     HBaseRPC.setRpcTimeout(this.callTimeout);
105     this.startTime = System.currentTimeMillis();
106   }
107 
108   public void afterCall() {
109     HBaseRPC.resetRpcTimeout();
110     this.endTime = System.currentTimeMillis();
111   }
112 
113   public void shouldRetry(Throwable throwable) throws IOException {
114     if (this.callTimeout != HConstants.DEFAULT_HBASE_CLIENT_OPERATION_TIMEOUT)
115       if (throwable instanceof SocketTimeoutException
116           || (this.endTime - this.startTime > this.callTimeout)) {
117         throw (SocketTimeoutException) (SocketTimeoutException) new SocketTimeoutException(
118             "Call to access row '" + Bytes.toString(row) + "' on table '"
119                 + Bytes.toString(tableName)
120                 + "' failed on socket timeout exception: " + throwable)
121             .initCause(throwable);
122       } else {
123         this.callTimeout = ((int) (this.endTime - this.startTime));
124       }
125   }
126 }