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

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

There is a newer version: 2.1.4
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 static org.apache.hadoop.hbase.client.AsyncRegionLocator.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.hadoop.hbase.HRegionLocation;
import org.apache.yetus.audience.InterfaceAudience;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The asynchronous locator for meta region.
 */
@InterfaceAudience.Private
class AsyncMetaRegionLocator {

  private static final Logger LOG = LoggerFactory.getLogger(AsyncMetaRegionLocator.class);

  private final AsyncRegistry registry;

  private final AtomicReference metaRegionLocation = new AtomicReference<>();

  private final AtomicReference> metaRelocateFuture =
      new AtomicReference<>();

  AsyncMetaRegionLocator(AsyncRegistry registry) {
    this.registry = registry;
  }

  CompletableFuture getRegionLocation(boolean reload) {
    for (;;) {
      if (!reload) {
        HRegionLocation metaRegionLocation = this.metaRegionLocation.get();
        if (metaRegionLocation != null) {
          return CompletableFuture.completedFuture(metaRegionLocation);
        }
      }
      if (LOG.isTraceEnabled()) {
        LOG.trace("Meta region location cache is null, try fetching from registry.");
      }
      if (metaRelocateFuture.compareAndSet(null, new CompletableFuture<>())) {
        if (LOG.isDebugEnabled()) {
          LOG.debug("Start fetching meta region location from registry.");
        }
        CompletableFuture future = metaRelocateFuture.get();
        registry.getMetaRegionLocation().whenComplete((locs, error) -> {
          if (error != null) {
            if (LOG.isDebugEnabled()) {
              LOG.debug("Failed to fetch meta region location from registry", error);
            }
            metaRelocateFuture.getAndSet(null).completeExceptionally(error);
            return;
          }
          HRegionLocation loc = locs.getDefaultRegionLocation();
          if (LOG.isDebugEnabled()) {
            LOG.debug("The fetched meta region location is " + loc);
          }
          // Here we update cache before reset future, so it is possible that someone can get a
          // stale value. Consider this:
          // 1. update cache
          // 2. someone clear the cache and relocate again
          // 3. the metaRelocateFuture is not null so the old future is used.
          // 4. we clear metaRelocateFuture and complete the future in it with the value being
          // cleared in step 2.
          // But we do not think it is a big deal as it rarely happens, and even if it happens, the
          // caller will retry again later, no correctness problems.
          this.metaRegionLocation.set(loc);
          metaRelocateFuture.set(null);
          future.complete(loc);
        });
      } else {
        CompletableFuture future = metaRelocateFuture.get();
        if (future != null) {
          return future;
        }
      }
    }
  }

  void updateCachedLocation(HRegionLocation loc, Throwable exception) {
    AsyncRegionLocator.updateCachedLocation(loc, exception, l -> metaRegionLocation.get(),
      newLoc -> {
        for (;;) {
          HRegionLocation oldLoc = metaRegionLocation.get();
          if (oldLoc != null && (oldLoc.getSeqNum() > newLoc.getSeqNum() ||
              oldLoc.getServerName().equals(newLoc.getServerName()))) {
            return;
          }
          if (metaRegionLocation.compareAndSet(oldLoc, newLoc)) {
            return;
          }
        }
      }, l -> {
        for (;;) {
          HRegionLocation oldLoc = metaRegionLocation.get();
          if (!canUpdate(l, oldLoc) || metaRegionLocation.compareAndSet(oldLoc, null)) {
            return;
          }
        }
      });
  }

  void clearCache() {
    metaRegionLocation.set(null);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy