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

org.apache.hadoop.hbase.client.ConnectionRegistryRpcStubHolder 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.Closeable;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.ipc.RpcClient;
import org.apache.hadoop.hbase.ipc.RpcClientFactory;
import org.apache.hadoop.hbase.ipc.RpcControllerFactory;
import org.apache.hadoop.hbase.security.User;
import org.apache.hadoop.hbase.util.FutureUtils;
import org.apache.hadoop.hbase.util.IOExceptionSupplier;
import org.apache.yetus.audience.InterfaceAudience;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;
import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableMap;

import org.apache.hadoop.hbase.shaded.protobuf.generated.RegistryProtos.ClientMetaService;

/**
 * A class for creating {@link RpcClient} and related stubs used by
 * {@link AbstractRpcBasedConnectionRegistry}. We need to connect to bootstrap nodes to get the
 * cluster id first, before creating the final {@link RpcClient} and related stubs.
 * 

* See HBASE-25051 for more details. */ @InterfaceAudience.Private class ConnectionRegistryRpcStubHolder implements Closeable { private static final Logger LOG = LoggerFactory.getLogger(ConnectionRegistryRpcStubHolder.class); private final Configuration conf; // used for getting cluster id private final Configuration noAuthConf; private final User user; private final RpcControllerFactory rpcControllerFactory; private final Set bootstrapNodes; private final int rpcTimeoutMs; private volatile ImmutableMap addr2Stub; private volatile RpcClient rpcClient; private CompletableFuture> addr2StubFuture; ConnectionRegistryRpcStubHolder(Configuration conf, User user, RpcControllerFactory rpcControllerFactory, Set bootstrapNodes) { this.conf = conf; if (User.isHBaseSecurityEnabled(conf)) { this.noAuthConf = new Configuration(conf); this.noAuthConf.set(User.HBASE_SECURITY_CONF_KEY, "simple"); } else { this.noAuthConf = conf; } this.user = user; this.rpcControllerFactory = rpcControllerFactory; this.bootstrapNodes = Collections.unmodifiableSet(bootstrapNodes); this.rpcTimeoutMs = (int) Math.min(Integer.MAX_VALUE, conf.getLong(HConstants.HBASE_RPC_TIMEOUT_KEY, HConstants.DEFAULT_HBASE_RPC_TIMEOUT)); } private ImmutableMap createStubs(RpcClient rpcClient, Collection addrs) { LOG.debug("Going to use new servers to create stubs: {}", addrs); Preconditions.checkNotNull(addrs); ImmutableMap.Builder builder = ImmutableMap.builderWithExpectedSize(addrs.size()); for (ServerName masterAddr : addrs) { builder.put(masterAddr, ClientMetaService.newStub(rpcClient.createRpcChannel(masterAddr, user, rpcTimeoutMs))); } return builder.build(); } private CompletableFuture> fetchClusterIdAndCreateStubs() { CompletableFuture> future = new CompletableFuture<>(); addr2StubFuture = future; FutureUtils.addListener( new ClusterIdFetcher(noAuthConf, user, rpcControllerFactory, bootstrapNodes).fetchClusterId(), (clusterId, error) -> { synchronized (ConnectionRegistryRpcStubHolder.this) { if (error != null) { addr2StubFuture.completeExceptionally(error); } else { RpcClient c = RpcClientFactory.createClient(conf, clusterId); ImmutableMap m = createStubs(c, bootstrapNodes); rpcClient = c; addr2Stub = m; addr2StubFuture.complete(m); } addr2StubFuture = null; } }); // here we must use the local variable future instead of addr2StubFuture, as the above listener // could be executed directly in the same thread(if the future completes quick enough), since // the synchronized lock is reentrant, it could set addr2StubFuture to null in the end, so when // arriving here the addr2StubFuture could be null. return future; } CompletableFuture> getStubs() { ImmutableMap s = this.addr2Stub; if (s != null) { return CompletableFuture.completedFuture(s); } synchronized (this) { s = this.addr2Stub; if (s != null) { return CompletableFuture.completedFuture(s); } if (addr2StubFuture != null) { return addr2StubFuture; } return fetchClusterIdAndCreateStubs(); } } void refreshStubs(IOExceptionSupplier> fetchEndpoints) throws IOException { // There is no actual call yet so we have not initialize the rpc client and related stubs yet, // give up refreshing if (addr2Stub == null) { LOG.debug("Skip refreshing stubs as we have not initialized rpc client yet"); return; } LOG.debug("Going to refresh stubs"); assert rpcClient != null; addr2Stub = createStubs(rpcClient, fetchEndpoints.get()); } @Override public void close() { if (rpcClient != null) { rpcClient.close(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy