static <T> CompletableFuture<T> getOrFetch(AtomicReference<T> cacheRef,
    AtomicReference<CompletableFuture<T>> futureRef, boolean reload,
    Supplier<CompletableFuture<T>> fetch, Predicate<T> validator, String type) {
    for (;;) {
      if (!reload) {
        T value = cacheRef.get();
        if (value != null && validator.test(value)) {
          return CompletableFuture.completedFuture(value);
        }
      }
      LOG.trace("{} cache is null, try fetching from registry", type);
      if (futureRef.compareAndSet(null, new CompletableFuture<>())) {
        LOG.debug("Start fetching {} from registry", type);
        CompletableFuture<T> future = futureRef.get();
        addListener(fetch.get(), (value, error) -> {
          if (error != null) {
            LOG.debug("Failed to fetch {} from registry", type, error);
            futureRef.getAndSet(null).completeExceptionally(error);
            return;
          }
          LOG.debug("The fetched {} is {}", type, value);
          // Here we update cache before reset future, so it is possible that someone can get a
          // stale value. Consider this:
          // 1. update cacheRef
          // 2. someone clears the cache and relocates again
          // 3. the futureRef is not null so the old future is used.
          // 4. we clear futureRef 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.
          cacheRef.set(value);
          futureRef.set(null);
          future.complete(value);
        });
        return future;
      } else {
        CompletableFuture<T> future = futureRef.get();
        if (future != null) {
          return future;
        }
      }
    }
  }
Select the priority for the rpc call.
<p/>
The rules are:
<ol>
<li>If user set a priority explicitly, then just use it.</li>
<li>For system table, use {@link HConstants#SYSTEMTABLE_QOS}.</li>
<li>For other tables, use {@link HConstants#NORMAL_QOS}.</li>
</ol>
@param priority  the priority set by user, can be {@link HConstants#PRIORITY_UNSET}.
@param tableName the table we operate on
hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java