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 */ 018package org.apache.hadoop.hbase.client; 019 020import java.io.Closeable; 021import java.io.IOException; 022import org.apache.hadoop.hbase.TableName; 023import org.apache.hadoop.hbase.ipc.HBaseRpcController; 024import org.apache.hadoop.hbase.ipc.RpcControllerFactory; 025import org.apache.hadoop.hbase.util.Bytes; 026import org.apache.yetus.audience.InterfaceAudience; 027 028import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 029 030/** 031 * A RetryingCallable for Master RPC operations. Implement the #rpcCall method. It will be retried 032 * on error. See its javadoc and the javadoc of #call(int). See {@link HBaseAdmin} for examples of 033 * how this is used. To get at the rpcController that has been created and configured to make this 034 * rpc call, use getRpcController(). We are trying to contain all protobuf references including 035 * references to rpcController so we don't pollute codebase with protobuf references; keep the 036 * protobuf references contained and only present in a few classes rather than all about the code 037 * base. 038 * <p> 039 * Like {@link RegionServerCallable} only in here, we can safely be PayloadCarryingRpcController all 040 * the time. This is not possible in the similar {@link RegionServerCallable} Callable because it 041 * 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 085 * {@link Exception} to {@link IOException}. It also does setup of an rpcController and calls 086 * through to the rpcCall() method which callers are expected to implement. If rpcController is an 087 * instance of 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 and 107 * 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 code 110 * base. 111 */ 112 protected abstract V rpcCall() throws Exception; 113 114 HBaseRpcController getRpcController() { 115 return this.rpcController; 116 } 117 118 void setPriority(final int priority) { 119 if (this.rpcController != null) { 120 this.rpcController.setPriority(priority); 121 } 122 } 123 124 void setPriority(final TableName tableName) { 125 if (this.rpcController != null) { 126 this.rpcController.setPriority(tableName); 127 } 128 } 129 130 /** 131 * @param regionName RegionName. If hbase:meta, we'll set high priority. 132 */ 133 void setPriority(final byte[] regionName) { 134 if (isMetaRegion(regionName)) { 135 setPriority(TableName.META_TABLE_NAME); 136 } 137 } 138 139 private static boolean isMetaRegion(final byte[] regionName) { 140 return Bytes.equals(regionName, RegionInfoBuilder.FIRST_META_REGIONINFO.getRegionName()) 141 || Bytes.equals(regionName, RegionInfoBuilder.FIRST_META_REGIONINFO.getEncodedNameAsBytes()); 142 } 143}