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  
19  package org.apache.hadoop.hbase.client;
20  
21  import java.io.IOException;
22  import java.io.InterruptedIOException;
23  
24  import org.apache.hadoop.hbase.DoNotRetryIOException;
25  import org.apache.hadoop.hbase.HBaseIOException;
26  import org.apache.hadoop.hbase.HRegionLocation;
27  import org.apache.hadoop.hbase.RegionLocations;
28  import org.apache.hadoop.hbase.TableName;
29  import org.apache.hadoop.hbase.classification.InterfaceAudience;
30  import org.apache.hadoop.hbase.ipc.RpcControllerFactory;
31  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.AdminService;
32  import org.apache.hadoop.hbase.util.Bytes;
33  
34  /**
35   * Similar to {@link RegionServerCallable} but for the AdminService interface. This service callable
36   * assumes a Table and row and thus does region locating similar to RegionServerCallable.
37   */
38  @InterfaceAudience.Private
39  public abstract class RegionAdminServiceCallable<T> implements RetryingCallable<T> {
40  
41    protected final ClusterConnection connection;
42  
43    protected final RpcControllerFactory rpcControllerFactory;
44  
45    protected AdminService.BlockingInterface stub;
46  
47    protected HRegionLocation location;
48  
49    protected final TableName tableName;
50    protected final byte[] row;
51    protected final int replicaId;
52  
53    protected final static int MIN_WAIT_DEAD_SERVER = 10000;
54  
55    public RegionAdminServiceCallable(ClusterConnection connection,
56        RpcControllerFactory rpcControllerFactory, TableName tableName, byte[] row) {
57      this(connection, rpcControllerFactory, null, tableName, row);
58    }
59  
60    public RegionAdminServiceCallable(ClusterConnection connection,
61        RpcControllerFactory rpcControllerFactory, HRegionLocation location,
62        TableName tableName, byte[] row) {
63      this(connection, rpcControllerFactory, location,
64        tableName, row, RegionReplicaUtil.DEFAULT_REPLICA_ID);
65    }
66  
67    public RegionAdminServiceCallable(ClusterConnection connection,
68        RpcControllerFactory rpcControllerFactory, HRegionLocation location,
69        TableName tableName, byte[] row, int replicaId) {
70      this.connection = connection;
71      this.rpcControllerFactory = rpcControllerFactory;
72      this.location = location;
73      this.tableName = tableName;
74      this.row = row;
75      this.replicaId = replicaId;
76    }
77  
78    @Override
79    public void prepare(boolean reload) throws IOException {
80      if (Thread.interrupted()) {
81        throw new InterruptedIOException();
82      }
83  
84      if (reload || location == null) {
85        location = getLocation(!reload);
86      }
87  
88      if (location == null) {
89        // With this exception, there will be a retry.
90        throw new HBaseIOException(getExceptionMessage());
91      }
92  
93      this.setStub(connection.getAdmin(location.getServerName()));
94    }
95  
96    protected void setStub(AdminService.BlockingInterface stub) {
97      this.stub = stub;
98    }
99  
100   public HRegionLocation getLocation(boolean useCache) throws IOException {
101     RegionLocations rl = getRegionLocations(connection, tableName, row, useCache, replicaId);
102     if (rl == null) {
103       throw new HBaseIOException(getExceptionMessage());
104     }
105     HRegionLocation location = rl.getRegionLocation(replicaId);
106     if (location == null) {
107       throw new HBaseIOException(getExceptionMessage());
108     }
109 
110     return location;
111   }
112 
113   @Override
114   public void throwable(Throwable t, boolean retrying) {
115     if (location != null) {
116       connection.updateCachedLocations(tableName, location.getRegionInfo().getRegionName(), row,
117           t, location.getServerName());
118     }
119   }
120 
121   /**
122    * @return {@link HConnection} instance used by this Callable.
123    */
124   HConnection getConnection() {
125     return this.connection;
126   }
127 
128   //subclasses can override this.
129   protected String getExceptionMessage() {
130     return "There is no location" + " table=" + tableName
131         + " ,replica=" + replicaId + ", row=" + Bytes.toStringBinary(row);
132   }
133 
134   @Override
135   public String getExceptionMessageAdditionalDetail() {
136     return null;
137   }
138 
139   @Override
140   public long sleep(long pause, int tries) {
141     long sleep = ConnectionUtils.getPauseTime(pause, tries);
142     if (sleep < MIN_WAIT_DEAD_SERVER
143         && (location == null || connection.isDeadServer(location.getServerName()))) {
144       sleep = ConnectionUtils.addJitter(MIN_WAIT_DEAD_SERVER, 0.10f);
145     }
146     return sleep;
147   }
148 
149   public static RegionLocations getRegionLocations(
150       ClusterConnection connection, TableName tableName, byte[] row,
151       boolean useCache, int replicaId)
152       throws RetriesExhaustedException, DoNotRetryIOException, InterruptedIOException {
153     RegionLocations rl;
154     try {
155       rl = connection.locateRegion(tableName, row, useCache, true, replicaId);
156     } catch (DoNotRetryIOException e) {
157       throw e;
158     } catch (NeedUnmanagedConnectionException e) {
159       throw new DoNotRetryIOException(e);
160     } catch (RetriesExhaustedException e) {
161       throw e;
162     } catch (InterruptedIOException e) {
163       throw e;
164     } catch (IOException e) {
165       throw new RetriesExhaustedException("Can't get the location", e);
166     }
167     if (rl == null) {
168       throw new RetriesExhaustedException("Can't get the locations");
169     }
170 
171     return rl;
172   }
173 }