public static AdminResponse sendAndWait(AdminRequest msg, ClusterDistributionManager dm) {

    // Prior to GemFire 4.0 admin messages were only sent to other
    // VMs; it was impossible for an admin message to be destined for
    // the VM that sent it. However, now that the admin API can be
    // used in an application VM, the admin API may request
    // information about its own VM. Unfortunately, a distribution
    // manager cannot send a message to itself (see bug 31734). So,
    // we have to handle admin messages sent to ourselves specially.
    if (dm.getId().equals(msg.getRecipient())) {
      msg.setSender(dm.getId()); // Sent from myself
      return msg.createResponse(dm);
    }

    AdminResponse result = null;
    try {
      synchronized (msg) {
        Set failures = dm.putOutgoing(msg);
        if (failures != null && failures.size() > 0) { // didn't go out
          if (dm.getDistributionManagerIds().contains(msg.getRecipient())) {
            // it's still in the view
            String s = " (" + msg + ")";
            throw new RuntimeAdminException(
                String.format("Could not send request.%s", s));
          }
          throw new OperationCancelledException(
              String.format("Request sent to %s failed since member departed.%s",
                  msg.getRecipient(), ""));
        }
        // sent it

        long timeout = getWaitTimeout();
        boolean gotResponse = msg.waitForResponse(timeout);
        if (!gotResponse) {
          if (dm.isCurrentMember(msg.getRecipient())) { // still here?
            // no one ever replied
            final String sb = "Administration request " + msg
                + " sent to "
                + msg.getRecipient()
                + " timed out after "
                + (timeout / 1000)
                + " seconds.";

            throw new RuntimeAdminException(sb);
          } // still here?
          // recipient vanished
          String s = " (" + msg + ")";
          throw new OperationCancelledException(
              String.format("Request sent to %s failed since member departed.%s",
                  msg.getRecipient(), s));
        } // !gotResponse

        result = msg.getResponse();
      } // synchronized
    } catch (InterruptedException ex) {
      Thread.currentThread().interrupt();
      dm.getCancelCriterion().checkCancelInProgress(ex);
      String s = "Request wait was interrupted.";
      s += " (" + msg + ")";
      throw new RuntimeAdminException(s, ex);
    }

    if (result == null) {
      String s = " (" + msg + ")";
      throw new OperationCancelledException(
          String.format("Request sent to %s was cancelled. %s",
              msg.getRecipient(), s));

    } else if (result instanceof AdminFailureResponse) {
      throw new RuntimeAdminException(
          "Request failed.",
          ((AdminFailureResponse) result).getCause());
    }
    return result;
  }
Sends <code>msg</code> using <code>dm</code> and waits for the response.

@return the response.
@throws RuntimeAdminException if this method is interrupted, times out, cancelled
        ({@link #cancelWaiters}), or failed with an exception on the server side.
geode-core/src/main/java/org/apache/geode/internal/admin/remote/AdminWaiters.java