private static RspList<Object> processCalls(
      ReplicableCommand command,
      boolean broadcast,
      long timeout,
      RspFilter filter,
      List<Address> dests,
      ResponseMode mode,
      Marshaller marshaller,
      CommandAwareRpcDispatcher card,
      boolean oob,
      boolean anycasting)
      throws Exception {
    if (trace) log.tracef("Replication task sending %s to addresses %s", command, dests);

    /// HACK ALERT!  Used for ISPN-1789.  Enable RSVP if the command is a cache view control
    // command.
    boolean rsvp = command instanceof CacheViewControlCommand;

    RspList<Object> retval = null;
    Buffer buf;
    if (broadcast || FORCE_MCAST) {
      buf = marshallCall(marshaller, command);
      retval =
          card.castMessage(
              dests,
              constructMessage(buf, null, oob, mode, rsvp),
              new RequestOptions(mode, timeout, false, filter));
    } else {
      RequestOptions opts = new RequestOptions(mode, timeout);

      if (dests.isEmpty()) return new RspList<Object>();
      buf = marshallCall(marshaller, command);

      // if at all possible, try not to use JGroups' ANYCAST for now.  Multiple (parallel) UNICASTs
      // are much faster.
      if (filter != null) {
        // This is possibly a remote GET.
        // These UNICASTs happen in parallel using sendMessageWithFuture.  Each future has a
        // listener attached
        // (see FutureCollator) and the first successful response is used.
        FutureCollator futureCollator = new FutureCollator(filter, dests.size(), timeout);
        for (Address a : dests) {
          NotifyingFuture<Object> f =
              card.sendMessageWithFuture(constructMessage(buf, a, oob, mode, rsvp), opts);
          futureCollator.watchFuture(f, a);
        }
        retval = futureCollator.getResponseList();
      } else if (mode == ResponseMode.GET_ALL) {
        // A SYNC call that needs to go everywhere
        Map<Address, Future<Object>> futures = new HashMap<Address, Future<Object>>(dests.size());

        for (Address dest : dests)
          futures.put(
              dest, card.sendMessageWithFuture(constructMessage(buf, dest, oob, mode, rsvp), opts));

        retval = new RspList<Object>();

        // a get() on each future will block till that call completes.
        for (Map.Entry<Address, Future<Object>> entry : futures.entrySet()) {
          try {
            retval.addRsp(entry.getKey(), entry.getValue().get(timeout, MILLISECONDS));
          } catch (java.util.concurrent.TimeoutException te) {
            throw new TimeoutException(
                formatString(
                    "Timed out after %s waiting for a response from %s",
                    prettyPrintTime(timeout), entry.getKey()));
          }
        }
      } else if (mode == ResponseMode.GET_NONE) {
        // An ASYNC call.  We don't care about responses.
        for (Address dest : dests)
          card.sendMessage(constructMessage(buf, dest, oob, mode, rsvp), opts);
      }
    }

    // we only bother parsing responses if we are not in ASYNC mode.
    if (mode != ResponseMode.GET_NONE) {

      if (trace) log.tracef("Responses: %s", retval);

      // a null response is 99% likely to be due to a marshalling problem - we throw a NSE, this
      // needs to be changed when
      // JGroups supports http://jira.jboss.com/jira/browse/JGRP-193
      // the serialization problem could be on the remote end and this is why we cannot catch this
      // above, when marshalling.
      if (retval == null)
        throw new NotSerializableException(
            "RpcDispatcher returned a null.  This is most often caused by args for "
                + command.getClass().getSimpleName()
                + " not being serializable.");
    }

    return retval;
  }
  private static RspList<Object> processCalls(
      ReplicableCommand command,
      boolean broadcast,
      long timeout,
      RspFilter filter,
      List<Address> dests,
      ResponseMode mode,
      DeliverOrder deliverOrder,
      Marshaller marshaller,
      CommandAwareRpcDispatcher card,
      boolean ignoreLeavers)
      throws Exception {
    if (trace)
      log.tracef(
          "Replication task sending %s to addresses %s with response mode %s",
          command, dests, mode);
    boolean rsvp = isRsvpCommand(command);

    RspList<Object> retval = null;
    Buffer buf;
    if (deliverOrder == DeliverOrder.TOTAL) {
      buf = marshallCall(marshaller, command);
      Message message = constructMessage(buf, new AnycastAddress(dests), mode, rsvp, deliverOrder);

      retval = card.castMessage(dests, message, new RequestOptions(mode, timeout, false, filter));
    } else if (broadcast || FORCE_MCAST) {
      buf = marshallCall(marshaller, command);
      RequestOptions opts = new RequestOptions(mode, timeout, false, filter);

      // Only the commands in total order must be received...
      // For correctness, ispn doesn't need their own message, so add own address to exclusion list
      opts.setExclusionList(card.getChannel().getAddress());

      retval = card.castMessage(dests, constructMessage(buf, null, mode, rsvp, deliverOrder), opts);
    } else {
      RequestOptions opts = new RequestOptions(mode, timeout);

      // Only the commands in total order must be received...
      opts.setExclusionList(card.getChannel().getAddress());

      if (dests.isEmpty()) return new RspList<>();
      buf = marshallCall(marshaller, command);

      // if at all possible, try not to use JGroups' ANYCAST for now.  Multiple (parallel) UNICASTs
      // are much faster.
      if (filter != null) {
        // This is possibly a remote GET.
        // These UNICASTs happen in parallel using sendMessageWithFuture.  Each future has a
        // listener attached
        // (see FutureCollator) and the first successful response is used.
        FutureCollator futureCollator =
            new FutureCollator(filter, dests.size(), timeout, card.timeService);
        for (Address a : dests) {
          NotifyingFuture<Object> f =
              card.sendMessageWithFuture(constructMessage(buf, a, mode, rsvp, deliverOrder), opts);
          futureCollator.watchFuture(f, a);
        }
        retval = futureCollator.getResponseList();
      } else if (mode == ResponseMode.GET_ALL) {
        // A SYNC call that needs to go everywhere
        Map<Address, Future<Object>> futures = new HashMap<>(dests.size());

        for (Address dest : dests)
          futures.put(
              dest,
              card.sendMessageWithFuture(
                  constructMessage(buf, dest, mode, rsvp, deliverOrder), opts));

        retval = new RspList<>();

        // a get() on each future will block till that call completes.
        for (Map.Entry<Address, Future<Object>> entry : futures.entrySet()) {
          Address target = entry.getKey();
          try {
            retval.addRsp(target, entry.getValue().get(timeout, MILLISECONDS));
          } catch (java.util.concurrent.TimeoutException te) {
            throw new TimeoutException(
                formatString(
                    "Timed out after %s waiting for a response from %s",
                    prettyPrintTime(timeout), target));
          } catch (ExecutionException e) {
            if (ignoreLeavers && e.getCause() instanceof SuspectedException) {
              log.tracef(formatString("Ignoring node %s that left during the remote call", target));
            } else {
              throw wrapThrowableInException(e.getCause());
            }
          }
        }
      } else if (mode == ResponseMode.GET_NONE) {
        // An ASYNC call.  We don't care about responses.
        for (Address dest : dests)
          card.sendMessage(constructMessage(buf, dest, mode, rsvp, deliverOrder), opts);
      }
    }

    // we only bother parsing responses if we are not in ASYNC mode.
    if (mode != ResponseMode.GET_NONE) {

      if (trace) log.tracef("Responses: %s", retval);

      // a null response is 99% likely to be due to a marshalling problem - we throw a NSE, this
      // needs to be changed when
      // JGroups supports http://jira.jboss.com/jira/browse/JGRP-193
      // the serialization problem could be on the remote end and this is why we cannot catch this
      // above, when marshalling.
      if (retval == null)
        throw new NotSerializableException(
            "RpcDispatcher returned a null.  This is most often caused by args for "
                + command.getClass().getSimpleName()
                + " not being serializable.");
    }

    return retval;
  }