View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.ipc;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.apache.hadoop.classification.InterfaceAudience;
25  import org.apache.hadoop.conf.Configuration;
26  import org.apache.hadoop.hbase.HConstants;
27  import org.apache.hadoop.hbase.IpcProtocol;
28  import org.apache.hadoop.hbase.client.RetriesExhaustedException;
29  
30  import java.io.IOException;
31  import java.io.InterruptedIOException;
32  import java.net.ConnectException;
33  import java.net.InetSocketAddress;
34  import java.net.SocketTimeoutException;
35  
36  /**
37   * An RPC implementation. This class provides the client side.
38   */
39  @InterfaceAudience.Private
40  public class HBaseClientRPC {
41    protected static final Log LOG =
42      LogFactory.getLog("org.apache.hadoop.ipc.HBaseClientRPC");
43  
44    // thread-specific RPC timeout, which may override that of RpcEngine
45    private static ThreadLocal<Integer> rpcTimeout = new ThreadLocal<Integer>() {
46      @Override
47      protected Integer initialValue() {
48        return HConstants.DEFAULT_HBASE_CLIENT_OPERATION_TIMEOUT;
49      }
50    };
51  
52    /**
53     * @param protocol      protocol interface
54     * @param addr          address of remote service
55     * @param conf          configuration
56     * @param maxAttempts   max attempts
57     * @param rpcTimeout    timeout for each RPC
58     * @param timeout       timeout in milliseconds
59     * @return proxy
60     * @throws java.io.IOException e
61     */
62    public static <T extends IpcProtocol> T waitForProxy(RpcClientEngine engine,
63                                           Class<T> protocol,
64                                           InetSocketAddress addr,
65                                           Configuration conf,
66                                           int maxAttempts,
67                                           int rpcTimeout,
68                                           long timeout)
69    throws IOException {
70      // HBase does limited number of reconnects which is different from hadoop.
71      long startTime = System.currentTimeMillis();
72      IOException ioe;
73      int reconnectAttempts = 0;
74      while (true) {
75        try {
76          return engine.getProxy(protocol, addr, conf, rpcTimeout);
77        } catch (SocketTimeoutException te) {
78         LOG.info("Problem connecting to server: " + addr);
79          ioe = te;
80        } catch (IOException ioex) {
81          // We only handle the ConnectException.
82          ConnectException ce = null;
83          if (ioex instanceof ConnectException) {
84            ce = (ConnectException) ioex;
85            ioe = ce;
86          } else if (ioex.getCause() != null
87              && ioex.getCause() instanceof ConnectException) {
88            ce = (ConnectException) ioex.getCause();
89            ioe = ce;
90          } else if (ioex.getMessage().toLowerCase()
91              .contains("connection refused")) {
92            ce = new ConnectException(ioex.getMessage());
93            ioe = ce;
94          } else {
95            // This is the exception we can't handle.
96            ioe = ioex;
97          }
98          if (ce != null) {
99            handleConnectionException(++reconnectAttempts, maxAttempts, protocol,
100               addr, ce);
101         }
102       }
103       // check if timed out
104       if (System.currentTimeMillis() - timeout >= startTime) {
105         throw ioe;
106       }
107 
108       // wait for retry
109       try {
110         Thread.sleep(1000);
111       } catch (InterruptedException ie) {
112         Thread.interrupted();
113         throw new InterruptedIOException();
114       }
115     }
116   }
117 
118   /**
119    * @param retries    current retried times.
120    * @param maxAttmpts max attempts
121    * @param protocol   protocol interface
122    * @param addr       address of remote service
123    * @param ce         ConnectException
124    * @throws org.apache.hadoop.hbase.client.RetriesExhaustedException
125    *
126    */
127   private static void handleConnectionException(int retries,
128                                                 int maxAttmpts,
129                                                 Class<?> protocol,
130                                                 InetSocketAddress addr,
131                                                 ConnectException ce)
132       throws RetriesExhaustedException {
133     if (maxAttmpts >= 0 && retries >= maxAttmpts) {
134       LOG.info("Server at " + addr + " could not be reached after "
135           + maxAttmpts + " tries, giving up.");
136       throw new RetriesExhaustedException("Failed setting up proxy " + protocol
137           + " to " + addr.toString() + " after attempts=" + maxAttmpts, ce);
138     }
139   }
140 
141   public static void setRpcTimeout(int t) {
142     rpcTimeout.set(t);
143   }
144 
145   public static int getRpcTimeout() {
146     return rpcTimeout.get();
147   }
148 
149   public static void resetRpcTimeout() {
150     rpcTimeout.remove();
151   }
152 }