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    public RegionAdminServiceCallable(ClusterConnection connection,
54        RpcControllerFactory rpcControllerFactory, TableName tableName, byte[] row) {
55      this(connection, rpcControllerFactory, null, tableName, row);
56    }
57  
58    public RegionAdminServiceCallable(ClusterConnection connection,
59        RpcControllerFactory rpcControllerFactory, HRegionLocation location,
60        TableName tableName, byte[] row) {
61      this(connection, rpcControllerFactory, location,
62        tableName, row, RegionReplicaUtil.DEFAULT_REPLICA_ID);
63    }
64  
65    public RegionAdminServiceCallable(ClusterConnection connection,
66        RpcControllerFactory rpcControllerFactory, HRegionLocation location,
67        TableName tableName, byte[] row, int replicaId) {
68      this.connection = connection;
69      this.rpcControllerFactory = rpcControllerFactory;
70      this.location = location;
71      this.tableName = tableName;
72      this.row = row;
73      this.replicaId = replicaId;
74    }
75  
76    @Override
77    public void prepare(boolean reload) throws IOException {
78      if (Thread.interrupted()) {
79        throw new InterruptedIOException();
80      }
81  
82      if (reload || location == null) {
83        location = getLocation(!reload);
84      }
85  
86      if (location == null) {
87        // With this exception, there will be a retry.
88        throw new HBaseIOException(getExceptionMessage());
89      }
90  
91      this.setStub(connection.getAdmin(location.getServerName()));
92    }
93  
94    protected void setStub(AdminService.BlockingInterface stub) {
95      this.stub = stub;
96    }
97  
98    public HRegionLocation getLocation(boolean useCache) throws IOException {
99      RegionLocations rl = getRegionLocations(connection, tableName, row, useCache, replicaId);
100     if (rl == null) {
101       throw new HBaseIOException(getExceptionMessage());
102     }
103     HRegionLocation location = rl.getRegionLocation(replicaId);
104     if (location == null) {
105       throw new HBaseIOException(getExceptionMessage());
106     }
107 
108     return location;
109   }
110 
111   @Override
112   public void throwable(Throwable t, boolean retrying) {
113     if (location != null) {
114       connection.updateCachedLocations(tableName, location.getRegionInfo().getRegionName(), row,
115           t, location.getServerName());
116     }
117   }
118 
119   /**
120    * @return {@link HConnection} instance used by this Callable.
121    */
122   HConnection getConnection() {
123     return this.connection;
124   }
125 
126   //subclasses can override this.
127   protected String getExceptionMessage() {
128     return "There is no location" + " table=" + tableName
129         + " ,replica=" + replicaId + ", row=" + Bytes.toStringBinary(row);
130   }
131 
132   @Override
133   public String getExceptionMessageAdditionalDetail() {
134     return null;
135   }
136 
137   @Override
138   public long sleep(long pause, int tries) {
139     return ConnectionUtils.getPauseTime(pause, tries);
140   }
141 
142   public static RegionLocations getRegionLocations(
143       ClusterConnection connection, TableName tableName, byte[] row,
144       boolean useCache, int replicaId)
145       throws RetriesExhaustedException, DoNotRetryIOException, InterruptedIOException {
146     RegionLocations rl;
147     try {
148       rl = connection.locateRegion(tableName, row, useCache, true, replicaId);
149     } catch (DoNotRetryIOException e) {
150       throw e;
151     } catch (NeedUnmanagedConnectionException e) {
152       throw new DoNotRetryIOException(e);
153     } catch (RetriesExhaustedException e) {
154       throw e;
155     } catch (InterruptedIOException e) {
156       throw e;
157     } catch (IOException e) {
158       throw new RetriesExhaustedException("Can't get the location", e);
159     }
160     if (rl == null) {
161       throw new RetriesExhaustedException("Can't get the locations");
162     }
163 
164     return rl;
165   }
166 }