private <R> void coprocessorService(String serviceName, byte[] startKey, byte[] endKey,
    Batch.Callback<R> callback, StubCall<R> call) throws Throwable {
    // get regions covered by the row range
    ExecutorService pool = Context.current().wrap(this.poolSupplier.get());
    List<byte[]> keys = getStartKeysInRange(startKey, endKey);
    Map<byte[], Future<R>> futures = new TreeMap<>(Bytes.BYTES_COMPARATOR);
    try {
      for (byte[] r : keys) {
        RegionCoprocessorRpcChannel channel = coprocessorService(r);
        Future<R> future = pool.submit(() -> {
          R result = call.call(channel);
          byte[] region = channel.getLastRegion();
          if (callback != null) {
            callback.update(region, r, result);
          }
          return result;
        });
        futures.put(r, future);
      }
    } catch (RejectedExecutionException e) {
      // maybe the connection has been closed, let's check
      if (conn.isClosed()) {
        throw new DoNotRetryIOException("Connection is closed", e);
      } else {
        throw new HBaseIOException("Coprocessor operation is rejected", e);
      }
    }
    for (Map.Entry<byte[], Future<R>> e : futures.entrySet()) {
      try {
        e.getValue().get();
      } catch (ExecutionException ee) {
        LOG.warn("Error calling coprocessor service {} for row {}", serviceName,
          Bytes.toStringBinary(e.getKey()), ee);
        throw ee.getCause();
      } catch (InterruptedException ie) {
        throw new InterruptedIOException("Interrupted calling coprocessor service " + serviceName
          + " for row " + Bytes.toStringBinary(e.getKey())).initCause(ie);
      }
    }
  }
Get the corresponding start keys and regions for an arbitrary range of keys.
<p>
@param startKey      Starting row in range, inclusive
@param endKey        Ending row in range
@param includeEndKey true if endRow is inclusive, false if exclusive
@param reload        true to reload information or false to use cached information
@return A pair of list of start keys and list of HRegionLocations that contain the specified
        range
@throws IOException if a remote or network exception occurs
hbase-client/src/main/java/org/apache/hadoop/hbase/client/TableOverAsyncTable.java