Beispiel #1
0
  /**
   * Convenience utility: creates a retry loop calling the given proc and retrying if needed
   *
   * @param client Zookeeper
   * @param proc procedure to call with retry
   * @param <T> return type
   * @return procedure result
   * @throws Exception any non-retriable errors
   */
  public static <T> T callWithRetry(CuratorZookeeperClient client, Callable<T> proc)
      throws Exception {
    T result = null;
    RetryLoop retryLoop = client.newRetryLoop();
    while (retryLoop.shouldContinue()) {
      try {
        client.internalBlockUntilConnectedOrTimedOut();

        result = proc.call();
        retryLoop.markComplete();
      } catch (Exception e) {
        retryLoop.takeException(e);
      }
    }
    return result;
  }
  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);
    }
  }
  @Override
  public void start() {
    log.info("Starting");
    if (!state.compareAndSet(CuratorFrameworkState.LATENT, CuratorFrameworkState.STARTED)) {
      IllegalStateException error = new IllegalStateException();
      log.error("Cannot be started more than once", error);
      throw error;
    }

    try {
      connectionStateManager.start(); // ordering dependency - must be called before client.start()
      client.start();
      executorService =
          Executors.newFixedThreadPool(2, threadFactory); // 1 for listeners, 1 for background ops

      executorService.submit(
          new Callable<Object>() {
            @Override
            public Object call() throws Exception {
              backgroundOperationsLoop();
              return null;
            }
          });
    } catch (Exception e) {
      handleBackgroundOperationException(null, e);
    }
  }
  @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);
    }
  }
  @Override
  public void close() {
    log.debug("Closing");
    if (state.compareAndSet(CuratorFrameworkState.STARTED, CuratorFrameworkState.STOPPED)) {
      listeners.forEach(
          new Function<CuratorListener, Void>() {
            @Override
            public Void apply(CuratorListener listener) {
              CuratorEvent event =
                  new CuratorEventImpl(
                      CuratorFrameworkImpl.this,
                      CuratorEventType.CLOSING,
                      0,
                      null,
                      null,
                      null,
                      null,
                      null,
                      null,
                      null,
                      null);
              try {
                listener.eventReceived(CuratorFrameworkImpl.this, event);
              } catch (Exception e) {
                log.error("Exception while sending Closing event", e);
              }
              return null;
            }
          });

      listeners.clear();
      unhandledErrorListeners.clear();
      connectionStateManager.close();
      client.close();
      namespaceWatcherMap.close();
      executorService.shutdownNow();
    }
  }
 ZooKeeper getZooKeeper() throws Exception {
   return client.getZooKeeper();
 }
 RetryLoop newRetryLoop() {
   return client.newRetryLoop();
 }