private <DATA_TYPE> void handleBackgroundOperationException(
      OperationAndData<DATA_TYPE> operationAndData, Throwable e) {
    do {
      if ((operationAndData != null) && RetryLoop.isRetryException(e)) {
        if (!Boolean.getBoolean(DebugUtils.PROPERTY_DONT_LOG_CONNECTION_ISSUES)) {
          log.debug("Retry-able exception received", e);
        }
        if (client
            .getRetryPolicy()
            .allowRetry(
                operationAndData.getThenIncrementRetryCount(),
                operationAndData.getElapsedTimeMs(),
                operationAndData)) {
          if (!Boolean.getBoolean(DebugUtils.PROPERTY_DONT_LOG_CONNECTION_ISSUES)) {
            log.debug("Retrying operation");
          }
          backgroundOperations.offer(operationAndData);
          break;
        } else {
          if (!Boolean.getBoolean(DebugUtils.PROPERTY_DONT_LOG_CONNECTION_ISSUES)) {
            log.debug("Retry policy did not allow retry");
          }
          if (operationAndData.getErrorCallback() != null) {
            operationAndData.getErrorCallback().retriesExhausted(operationAndData);
          }
        }
      }

      logError("Background exception was not retry-able or retry gave up", e);
    } while (false);
  }
  private void backgroundOperationsLoop() {
    AuthInfo auth = authInfo.getAndSet(null);
    if (auth != null) {
      try {
        client.getZooKeeper().addAuthInfo(auth.scheme, auth.auth);
      } catch (Exception e) {
        logError("addAuthInfo for background operation threw exception", e);
        return;
      }
    }

    while (!Thread.interrupted()) {
      OperationAndData<?> operationAndData;
      try {
        operationAndData = backgroundOperations.take();
        if (debugListener != null) {
          debugListener.listen(operationAndData);
        }
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        break;
      }

      performBackgroundOperation(operationAndData);
    }
  }
  @SuppressWarnings({"ThrowableResultOfMethodCallIgnored"})
  <DATA_TYPE> void processBackgroundOperation(
      OperationAndData<DATA_TYPE> operationAndData, CuratorEvent event) {
    boolean isInitialExecution = (event == null);
    if (isInitialExecution) {
      performBackgroundOperation(operationAndData);
      return;
    }

    boolean doQueueOperation = false;
    do {
      if (RetryLoop.shouldRetry(event.getResultCode())) {
        if (client
            .getRetryPolicy()
            .allowRetry(
                operationAndData.getThenIncrementRetryCount(),
                operationAndData.getElapsedTimeMs(),
                operationAndData)) {
          doQueueOperation = true;
        } else {
          if (operationAndData.getErrorCallback() != null) {
            operationAndData.getErrorCallback().retriesExhausted(operationAndData);
          }

          KeeperException.Code code = KeeperException.Code.get(event.getResultCode());
          Exception e = null;
          try {
            e = (code != null) ? KeeperException.create(code) : null;
          } catch (Throwable ignore) {
          }
          if (e == null) {
            e = new Exception("Unknown result code: " + event.getResultCode());
          }
          logError("Background operation retry gave up", e);
        }
        break;
      }

      if (operationAndData.getCallback() != null) {
        sendToBackgroundCallback(operationAndData, event);
        break;
      }

      processEvent(event);
    } while (false);

    if (doQueueOperation) {
      queueOperation(operationAndData);
    }
  }