private <T> Predicate<T> getMutationRetryableFunction(Predicate<T> isRetryableMutation) {
   if (retryOptions.allowRetriesWithoutTimestamp()) {
     return Predicates.<T>alwaysTrue();
   } else {
     return isRetryableMutation;
   }
 }
  private ResultScanner<Row> streamRows(ReadRowsRequest request) {
    final Timer.Context timerContext = readRowsAsync.getRpcMetrics().timeRpc();
    final AtomicBoolean wasCanceled = new AtomicBoolean(false);

    expandPoolIfNecessary(this.bigtableOptions.getChannelCount());

    CallOptions callOptions = getCallOptions(readRowsAsync.getMethodDescriptor(), request);
    final ClientCall<ReadRowsRequest, ReadRowsResponse> readRowsCall =
        readRowsAsync.newCall(callOptions);

    ResponseQueueReader reader =
        new ResponseQueueReader(
            retryOptions.getReadPartialRowTimeoutMillis(), retryOptions.getStreamingBufferSize());

    final StreamObserverAdapter<ReadRowsResponse> listener =
        new StreamObserverAdapter<>(readRowsCall, new RowMerger(reader));

    readRowsAsync.start(readRowsCall, request, listener, createMetadata(request.getTableName()));
    // If the scanner is closed before we're done streaming, we want to cancel the RPC.
    CancellationToken cancellationToken = new CancellationToken();
    cancellationToken.addListener(
        new Runnable() {
          @Override
          public synchronized void run() {
            if (!wasCanceled.get()) {
              timerContext.close();
              wasCanceled.set(true);
            }
            if (!listener.hasStatusBeenRecieved()) {
              readRowsCall.cancel("User requested cancelation.", null);
            }
          }
        },
        MoreExecutors.directExecutor());

    return new StreamingBigtableResultScanner(reader, cancellationToken);
  }
 /**
  * Calls {@link OAuth2Credentials#refreshAccessToken()}. In case of an IOException, retry the call
  * as per the {@link BackOff} policy defined by {@link RetryOptions#createBackoff()}.
  *
  * <p>This method retries until one of the following conditions occurs:
  *
  * <ol>
  *   <li>An OAuth request was completed. If the value is null, return an exception.
  *   <li>A non-IOException Exception is thrown - return an error status
  *   <li>All retries have been exhausted, i.e. when the Backoff.nextBackOffMillis() returns
  *       BackOff.STOP
  *   <li>An interrupt occurs.
  * </ol>
  *
  * @return HeaderCacheElement containing either a valid {@link AccessToken} or an exception.
  */
 protected HeaderCacheElement refreshCredentialsWithRetry() {
   BackOff backoff = null;
   while (true) {
     try {
       logger.info("Refreshing the OAuth token");
       AccessToken newToken = credentials.refreshAccessToken();
       if (newToken == null) {
         // The current implementations of refreshAccessToken() throws an IOException or return
         // a valid token. This handling is future proofing just in case credentials returns null
         // for
         // some reason. This case was caught by a poorly coded unit test.
         logger.info("Refreshed the OAuth token");
         return new HeaderCacheElement(
             new IOException("Could not load the token for credentials: " + credentials));
       } else {
         // Success!
         return new HeaderCacheElement(newToken);
       }
     } catch (IOException exception) {
       logger.warn("Got an unexpected IOException when refreshing google credentials.", exception);
       // An IOException occurred. Retry with backoff.
       if (backoff == null) {
         // initialize backoff.
         backoff = retryOptions.createBackoff();
       }
       // Given the backoff, either sleep for a short duration, or terminate if the backoff has
       // reached its configured timeout limit.
       try {
         RetryState retryState = getRetryState(backoff);
         if (retryState != RetryState.PerformRetry) {
           return new HeaderCacheElement(exception);
         } // else Retry.
       } catch (IOException e) {
         logger.warn("Got an exception while trying to run backoff.nextBackOffMillis()", e);
         return new HeaderCacheElement(exception);
       }
     } catch (Exception e) {
       logger.warn("Got an unexpected exception while trying to refresh google credentials.", e);
       return new HeaderCacheElement(new IOException("Could not read headers", e));
     }
   }
 }