private <T> T executeRemoteCallWithRetry(final Operation<T> call, final Predicate<T> check)
      throws TException {
    int detectedNodeNum = 0;
    for (int i = 0; i < RETRY_NUM; i++) {
      try {
        final T result = call.execute();
        if (check.test(result)) {
          return result;
        }
        detectedNodeNum++;
      } catch (TException e) {
        final String message =
            String.format(
                MSG_RECONNECTION_DATANODE_FAIL,
                configNode,
                config.getAddressAndPort(),
                Thread.currentThread().getStackTrace()[2].getMethodName());
        logger.warn(message, e);
        configLeader = null;
      }

      // If we have detected all configNodes and still not return
      if (detectedNodeNum >= configNodes.size()) {
        // Clear count
        detectedNodeNum = 0;
        // Wait to start the next try
        try {
          Thread.sleep(WAIT_CN_LEADER_ELECTION_INTERVAL_MS);
        } catch (InterruptedException ignore) {
          Thread.currentThread().interrupt();
          logger.warn(
              "Unexpected interruption when waiting to try to connect to ConfigNode, may because current node has been down. Will break current execution process to avoid meaningless wait.");
          break;
        }
      }

      connectAndSync();
    }
    throw new TException(MSG_RECONNECTION_FAIL);
  }
The frame of execute RPC, include logic of retry and exception handling.

@param call which rpc should call
@param check check the rpc's result
@return rpc's result
@param <T> the type of rpc result
@throws TException if fails more than RETRY_NUM times, throw TException(MSG_RECONNECTION_FAIL)
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/ConfigNodeClient.java