001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.hadoop.hbase.client; 020 021import java.io.Closeable; 022import java.io.IOException; 023import org.apache.hadoop.hbase.TableName; 024import org.apache.hadoop.hbase.ipc.HBaseRpcController; 025import org.apache.hadoop.hbase.ipc.RpcControllerFactory; 026import org.apache.hadoop.hbase.util.Bytes; 027import org.apache.yetus.audience.InterfaceAudience; 028 029import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 030 031/** 032 * A RetryingCallable for Master RPC operations. 033 * Implement the #rpcCall method. It will be retried on error. See its javadoc and the javadoc of 034 * #call(int). See {@link HBaseAdmin} for examples of how this is used. To get at the 035 * rpcController that has been created and configured to make this rpc call, use getRpcController(). 036 * We are trying to contain all protobuf references including references to rpcController so we 037 * don't pollute codebase with protobuf references; keep the protobuf references contained and only 038 * present in a few classes rather than all about the code base. 039 * <p>Like {@link RegionServerCallable} only in here, we can safely be PayloadCarryingRpcController 040 * all the time. This is not possible in the similar {@link RegionServerCallable} Callable because 041 * it has to deal with Coprocessor Endpoints. 042 * @param <V> return type 043 */ 044@InterfaceAudience.Private 045abstract class MasterCallable<V> implements RetryingCallable<V>, Closeable { 046 protected final ClusterConnection connection; 047 protected MasterKeepAliveConnection master; 048 private final HBaseRpcController rpcController; 049 050 MasterCallable(final Connection connection, final RpcControllerFactory rpcConnectionFactory) { 051 this.connection = (ClusterConnection) connection; 052 this.rpcController = rpcConnectionFactory.newController(); 053 } 054 055 @Override 056 public void prepare(boolean reload) throws IOException { 057 this.master = this.connection.getMaster(); 058 } 059 060 @Override 061 public void close() throws IOException { 062 // The above prepare could fail but this would still be called though masterAdmin is null 063 if (this.master != null) { 064 this.master.close(); 065 this.master = null; 066 } 067 } 068 069 @Override 070 public void throwable(Throwable t, boolean retrying) { 071 } 072 073 @Override 074 public String getExceptionMessageAdditionalDetail() { 075 return ""; 076 } 077 078 @Override 079 public long sleep(long pause, int tries) { 080 return ConnectionUtils.getPauseTime(pause, tries); 081 } 082 083 /** 084 * Override that changes the {@link java.util.concurrent.Callable#call()} Exception from {@link Exception} to 085 * {@link IOException}. It also does setup of an rpcController and calls through to the rpcCall() 086 * method which callers are expected to implement. If rpcController is an instance of 087 * PayloadCarryingRpcController, we will set a timeout on it. 088 */ 089 @Override 090 // Same trick as in RegionServerCallable so users don't have to copy/paste so much boilerplate 091 // and so we contain references to protobuf. We can't set priority on the rpcController as 092 // we do in RegionServerCallable because we don't always have a Table when we call. 093 public V call(int callTimeout) throws IOException { 094 try { 095 if (this.rpcController != null) { 096 this.rpcController.reset(); 097 this.rpcController.setCallTimeout(callTimeout); 098 } 099 return rpcCall(); 100 } catch (Exception e) { 101 throw ProtobufUtil.handleRemoteException(e); 102 } 103 } 104 105 /** 106 * Run the RPC call. Implement this method. To get at the rpcController that has been created 107 * and configured to make this rpc call, use getRpcController(). We are trying to contain 108 * rpcController references so we don't pollute codebase with protobuf references; keep the 109 * protobuf references contained and only present in a few classes rather than all about the 110 * code base. 111 * @throws Exception 112 */ 113 protected abstract V rpcCall() throws Exception; 114 115 HBaseRpcController getRpcController() { 116 return this.rpcController; 117 } 118 119 void setPriority(final int priority) { 120 if (this.rpcController != null) { 121 this.rpcController.setPriority(priority); 122 } 123 } 124 125 void setPriority(final TableName tableName) { 126 if (this.rpcController != null) { 127 this.rpcController.setPriority(tableName); 128 } 129 } 130 131 /** 132 * @param regionName RegionName. If hbase:meta, we'll set high priority. 133 */ 134 void setPriority(final byte[] regionName) { 135 if (isMetaRegion(regionName)) { 136 setPriority(TableName.META_TABLE_NAME); 137 } 138 } 139 140 private static boolean isMetaRegion(final byte[] regionName) { 141 return Bytes.equals(regionName, RegionInfoBuilder.FIRST_META_REGIONINFO.getRegionName()) || 142 Bytes.equals(regionName, RegionInfoBuilder.FIRST_META_REGIONINFO.getEncodedNameAsBytes()); 143 } 144}