private Map<Address, Object> executeOnClusterSync(
      final ReplicableCommand command,
      final int timeout,
      boolean totalOrder,
      boolean distributed,
      final ResponseFilter filter)
      throws Exception {
    // first invoke remotely

    if (totalOrder) {
      Map<Address, Response> responseMap =
          transport.invokeRemotely(
              transport.getMembers(),
              command,
              ResponseMode.SYNCHRONOUS_IGNORE_LEAVERS,
              timeout,
              filter,
              DeliverOrder.TOTAL,
              distributed);
      Map<Address, Object> responseValues =
          new HashMap<Address, Object>(transport.getMembers().size());
      for (Map.Entry<Address, Response> entry : responseMap.entrySet()) {
        Address address = entry.getKey();
        Response response = entry.getValue();
        if (!response.isSuccessful()) {
          Throwable cause =
              response instanceof ExceptionResponse
                  ? ((ExceptionResponse) response).getException()
                  : null;
          throw new CacheException(
              "Unsuccessful response received from node " + address + ": " + response, cause);
        }
        responseValues.put(address, ((SuccessfulResponse) response).getResponseValue());
      }
      return responseValues;
    }

    CompletableFuture<Map<Address, Response>> remoteFuture =
        transport.invokeRemotelyAsync(
            null, command, ResponseMode.SYNCHRONOUS, timeout, filter, DeliverOrder.NONE, false);

    // invoke the command on the local node
    gcr.wireDependencies(command);
    Response localResponse;
    try {
      if (log.isTraceEnabled()) log.tracef("Attempting to execute command on self: %s", command);
      localResponse = (Response) command.perform(null);
    } catch (Throwable throwable) {
      throw new Exception(throwable);
    }
    if (!localResponse.isSuccessful()) {
      Exception exception = null;
      if (localResponse instanceof ExceptionResponse) {
        exception = ((ExceptionResponse) localResponse).getException();
      }
      throw new CacheException("Unsuccessful local response: " + localResponse, exception);
    }

    // wait for the remote commands to finish
    Map<Address, Response> responseMap = remoteFuture.get(timeout, TimeUnit.MILLISECONDS);

    // parse the responses
    Map<Address, Object> responseValues =
        new HashMap<Address, Object>(transport.getMembers().size());
    for (Map.Entry<Address, Response> entry : responseMap.entrySet()) {
      Address address = entry.getKey();
      Response response = entry.getValue();
      if (!response.isSuccessful()) {
        Throwable cause =
            response instanceof ExceptionResponse
                ? ((ExceptionResponse) response).getException()
                : null;
        throw new CacheException(
            "Unsuccessful response received from node " + address + ": " + response, cause);
      }
      responseValues.put(address, ((SuccessfulResponse) response).getResponseValue());
    }

    responseValues.put(
        transport.getAddress(), ((SuccessfulResponse) localResponse).getResponseValue());

    return responseValues;
  }