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