All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.hadoop.hbase.client.RegionServerCallable Maven / Gradle / Ivy

There is a newer version: 3.0.0-beta-1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.hbase.client;

import java.io.IOException;
import java.util.Map;
import org.apache.hadoop.hbase.CellScanner;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HRegionLocation;
import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.TableNotEnabledException;
import org.apache.hadoop.hbase.ipc.HBaseRpcController;
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.yetus.audience.InterfaceAudience;

import org.apache.hbase.thirdparty.com.google.protobuf.RpcController;

/**
 * Implementations make a RPC call against a RegionService via a protobuf Service. Implement
 * rpcCall() and the parent class setClientByServiceName; this latter is where the RPC stub gets set
 * (the appropriate protobuf 'Service'/Client). Be sure to make use of the RpcController that this
 * instance is carrying via #getRpcController().
 * 

* TODO: this class is actually tied to one region, because most of the paths make use of the * regioninfo part of location when building requests. The only reason it works for multi-region * requests (e.g. batch) is that they happen to not use the region parts. This could be done cleaner * (e.g. having a generic parameter and 2 derived classes, RegionCallable and actual * RegionServerCallable with ServerName. * @param The class that the ServerCallable handles. * @param The protocol to use (Admin or Client or even an Endpoint over in MetaTableAccessor). */ // TODO: MasterCallable and this Class have a lot in common. UNIFY! // Public but should be package private only it is used by MetaTableAccessor. FIX!! @InterfaceAudience.Private public abstract class RegionServerCallable implements RetryingCallable { private final Connection connection; private final TableName tableName; private final byte[] row; /** * Some subclasses want to set their own location. Make it protected. */ protected HRegionLocation location; protected S stub; /** * This is 99% of the time a HBaseRpcController but also used doing Coprocessor Endpoints and in * this case, it is a ServerRpcControllable which is not a HBaseRpcController. Can be null! */ protected final RpcController rpcController; private int priority = HConstants.NORMAL_QOS; protected final Map requestAttributes; /** * @param connection Connection to use. * @param rpcController Controller to use; can be shaded or non-shaded. * @param tableName Table name to which row belongs. * @param row The row we want in tableName. */ public RegionServerCallable(Connection connection, TableName tableName, byte[] row, RpcController rpcController, Map requestAttributes) { this(connection, tableName, row, rpcController, HConstants.NORMAL_QOS, requestAttributes); } public RegionServerCallable(Connection connection, TableName tableName, byte[] row, RpcController rpcController, int priority, Map requestAttributes) { super(); this.connection = connection; this.tableName = tableName; this.row = row; this.rpcController = rpcController; this.priority = priority; this.requestAttributes = requestAttributes; } protected RpcController getRpcController() { return this.rpcController; } protected void setStub(S stub) { this.stub = stub; } protected S getStub() { return this.stub; } /** * Override that changes call Exception from {@link Exception} to {@link IOException}. Also does * set up of the rpcController. */ @Override public T call(int callTimeout) throws IOException { try { // Iff non-null and an instance of a SHADED rpcController, do config! Unshaded -- i.e. // com.google.protobuf.RpcController or null -- will just skip over this config. if (getRpcController() != null) { RpcController shadedRpcController = (RpcController) getRpcController(); // Do a reset to clear previous states, such as CellScanner. shadedRpcController.reset(); if (shadedRpcController instanceof HBaseRpcController) { HBaseRpcController hrc = (HBaseRpcController) getRpcController(); // If it is an instance of HBaseRpcController, we can set priority on the controller based // off the tableName. Set call timeout too. hrc.setPriority(tableName); hrc.setPriority(priority); hrc.setCallTimeout(callTimeout); hrc.setRequestAttributes(requestAttributes); if (tableName != null) { hrc.setTableName(tableName); } } } return rpcCall(); } catch (Exception e) { throw ProtobufUtil.handleRemoteException(e); } } /** * Run the RPC call. Implement this method. To get at the rpcController that has been created and * configured to make this rpc call, use getRpcController(). We are trying to contain * rpcController references so we don't pollute codebase with protobuf references; keep the * protobuf references contained and only present in a few classes rather than all about the code * base. */ protected abstract T rpcCall() throws Exception; /** * Get the RpcController CellScanner. If the RpcController is a HBaseRpcController, which it is in * all cases except when we are processing Coprocessor Endpoint, then this method returns a * reference to the CellScanner that the HBaseRpcController is carrying. Do it up here in this * Callable so we don't have to scatter ugly instanceof tests around the codebase. Will return * null if called in a Coproccessor Endpoint context. Should never happen. */ protected CellScanner getRpcControllerCellScanner() { return (getRpcController() != null && getRpcController() instanceof HBaseRpcController) ? ((HBaseRpcController) getRpcController()).cellScanner() : null; } protected void setRpcControllerCellScanner(CellScanner cellScanner) { if (getRpcController() != null && getRpcController() instanceof HBaseRpcController) { ((HBaseRpcController) this.rpcController).setCellScanner(cellScanner); } } /** Returns {@link ClusterConnection} instance used by this Callable. */ protected ClusterConnection getConnection() { return (ClusterConnection) this.connection; } protected HRegionLocation getLocation() { return this.location; } protected void setLocation(final HRegionLocation location) { this.location = location; } public TableName getTableName() { return this.tableName; } public byte[] getRow() { return this.row; } protected int getPriority() { return this.priority; } @Override public void throwable(Throwable t, boolean retrying) { if (location != null) { getConnection().updateCachedLocations(tableName, location.getRegionInfo().getRegionName(), row, t, location.getServerName()); } } @Override public String getExceptionMessageAdditionalDetail() { return "row '" + Bytes.toStringBinary(row) + "' on table '" + tableName + "' at " + location; } @Override public long sleep(long pause, int tries) { return ConnectionUtils.getPauseTime(pause, tries); } /** Returns the HRegionInfo for the current region */ public HRegionInfo getHRegionInfo() { if (this.location == null) { return null; } return this.location.getRegionInfo(); } @Override public void prepare(final boolean reload) throws IOException { // check table state if this is a retry if ( reload && tableName != null && !tableName.equals(TableName.META_TABLE_NAME) && getConnection().isTableDisabled(tableName) ) { throw new TableNotEnabledException(tableName.getNameAsString() + " is disabled."); } try (RegionLocator regionLocator = connection.getRegionLocator(tableName)) { this.location = regionLocator.getRegionLocation(row); } if (this.location == null) { throw new IOException("Failed to find location, tableName=" + tableName + ", row=" + Bytes.toString(row) + ", reload=" + reload); } setStubByServiceName(this.location.getServerName()); } /** * Set the RCP client stub * @param serviceName to get the rpc stub for * @throws IOException When client could not be created */ protected abstract void setStubByServiceName(ServerName serviceName) throws IOException; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy