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.IOException; 021 022import org.apache.hadoop.hbase.HConstants; 023import org.apache.hadoop.hbase.TableName; 024import org.apache.yetus.audience.InterfaceAudience; 025import org.slf4j.Logger; 026import org.slf4j.LoggerFactory; 027import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils; 028import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.CoprocessorServiceRequest; 029import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.CoprocessorServiceResponse; 030 031import com.google.protobuf.Descriptors; 032import com.google.protobuf.Message; 033import com.google.protobuf.RpcController; 034 035/** 036 * Provides clients with an RPC connection to call Coprocessor Endpoint 037 * {@link com.google.protobuf.Service}s 038 * against a given table region. An instance of this class may be obtained 039 * by calling {@link org.apache.hadoop.hbase.client.Table#coprocessorService(byte[])}, 040 * but should normally only be used in creating a new {@link com.google.protobuf.Service} stub to 041 * call the endpoint methods. 042 * @see org.apache.hadoop.hbase.client.Table#coprocessorService(byte[]) 043 */ 044@InterfaceAudience.Private 045class RegionCoprocessorRpcChannel extends SyncCoprocessorRpcChannel { 046 private static final Logger LOG = LoggerFactory.getLogger(RegionCoprocessorRpcChannel.class); 047 private final TableName table; 048 private final byte [] row; 049 private final ClusterConnection conn; 050 private byte[] lastRegion; 051 private final int operationTimeout; 052 private final RpcRetryingCallerFactory rpcCallerFactory; 053 054 /** 055 * Constructor 056 * @param conn connection to use 057 * @param table to connect to 058 * @param row to locate region with 059 */ 060 RegionCoprocessorRpcChannel(ClusterConnection conn, TableName table, byte[] row) { 061 this.table = table; 062 this.row = row; 063 this.conn = conn; 064 this.operationTimeout = conn.getConnectionConfiguration().getOperationTimeout(); 065 this.rpcCallerFactory = conn.getRpcRetryingCallerFactory(); 066 } 067 068 @Override 069 protected Message callExecService(final RpcController controller, 070 final Descriptors.MethodDescriptor method, final Message request, 071 final Message responsePrototype) 072 throws IOException { 073 if (LOG.isTraceEnabled()) { 074 LOG.trace("Call: " + method.getName() + ", " + request.toString()); 075 } 076 if (row == null) { 077 throw new NullPointerException("Can't be null!"); 078 } 079 ClientServiceCallable<CoprocessorServiceResponse> callable = 080 new ClientServiceCallable<CoprocessorServiceResponse>(this.conn, 081 this.table, this.row, this.conn.getRpcControllerFactory().newController(), HConstants.PRIORITY_UNSET) { 082 @Override 083 protected CoprocessorServiceResponse rpcCall() throws Exception { 084 byte [] regionName = getLocation().getRegionInfo().getRegionName(); 085 CoprocessorServiceRequest csr = 086 CoprocessorRpcUtils.getCoprocessorServiceRequest(method, request, row, regionName); 087 return getStub().execService(getRpcController(), csr); 088 } 089 }; 090 CoprocessorServiceResponse result = 091 this.rpcCallerFactory.<CoprocessorServiceResponse> newCaller().callWithRetries(callable, 092 operationTimeout); 093 this.lastRegion = result.getRegion().getValue().toByteArray(); 094 return CoprocessorRpcUtils.getResponse(result, responsePrototype); 095 } 096 097 /** 098 * Get last region this RpcChannel communicated with 099 * @return region name as byte array 100 */ 101 public byte[] getLastRegion() { 102 return lastRegion; 103 } 104}