Exemplo n.º 1
0
  /**
   * Broadcasts the new view and digest, and waits for acks from all members in the list given as
   * argument. If the list is null, we take the members who are part of new_view
   */
  public void castViewChange(
      View new_view, Digest digest, JoinRsp jr, Collection<Address> newMembers) {
    if (log.isTraceEnabled())
      log.trace(local_addr + ": mcasting view " + new_view + " (" + new_view.size() + " mbrs)\n");

    // Send down a local TMP_VIEW event. This is needed by certain layers (e.g. NAKACK) to compute
    // correct digest
    // in case client's next request (e.g. getState()) reaches us *before* our own view change
    // multicast.
    // Check NAKACK's TMP_VIEW handling for details
    down_prot.up(new Event(Event.TMP_VIEW, new_view));
    down_prot.down(new Event(Event.TMP_VIEW, new_view));

    List<Address> ackMembers = new ArrayList<Address>(new_view.getMembers());
    if (newMembers != null && !newMembers.isEmpty()) ackMembers.removeAll(newMembers);

    Message view_change_msg = new Message(); // bcast to all members
    GmsHeader hdr = new GmsHeader(GmsHeader.VIEW, new_view);
    hdr.my_digest = digest;
    view_change_msg.putHeader(this.id, hdr);

    // If we're the only member the VIEW is broadcast to, let's simply install the view directly,
    // without
    // sending the VIEW multicast ! Or else N-1 members drop the multicast anyway...
    if (local_addr != null && ackMembers.size() == 1 && ackMembers.get(0).equals(local_addr)) {
      // we need to add the message to the retransmit window (e.g. in NAKACK), so (1) it can be
      // retransmitted and
      // (2) we increment the seqno (otherwise, we'd return an incorrect digest)
      down_prot.down(new Event(Event.ADD_TO_XMIT_TABLE, view_change_msg));
      impl.handleViewChange(new_view, digest);
    } else {
      if (!ackMembers.isEmpty()) ack_collector.reset(ackMembers);

      down_prot.down(new Event(Event.MSG, view_change_msg));
      try {
        if (!ackMembers.isEmpty()) {
          ack_collector.waitForAllAcks(view_ack_collection_timeout);
          if (log.isTraceEnabled())
            log.trace(
                local_addr
                    + ": received all "
                    + ack_collector.expectedAcks()
                    + " ACKs from members for view "
                    + new_view.getVid());
        }
      } catch (TimeoutException e) {
        if (log_collect_msgs && log.isWarnEnabled()) {
          log.warn(
              local_addr
                  + ": failed to collect all ACKs (expected="
                  + ack_collector.expectedAcks()
                  + ") for view "
                  + new_view.getViewId()
                  + " after "
                  + view_ack_collection_timeout
                  + "ms, missing ACKs from "
                  + ack_collector.printMissing());
        }
      }
    }

    if (jr != null && (newMembers != null && !newMembers.isEmpty())) {
      ack_collector.reset(new ArrayList<Address>(newMembers));
      for (Address joiner : newMembers) {
        sendJoinResponse(jr, joiner);
      }
      try {
        ack_collector.waitForAllAcks(view_ack_collection_timeout);
        if (log.isTraceEnabled())
          log.trace(
              local_addr
                  + ": received all ACKs ("
                  + ack_collector.expectedAcks()
                  + ") from joiners for view "
                  + new_view.getVid());
      } catch (TimeoutException e) {
        if (log_collect_msgs && log.isWarnEnabled()) {
          log.warn(
              local_addr
                  + ": failed to collect all ACKs (expected="
                  + ack_collector.expectedAcks()
                  + ") for unicast view "
                  + new_view
                  + " after "
                  + view_ack_collection_timeout
                  + "ms, missing ACKs from "
                  + ack_collector.printMissing());
        }
      }
    }
  }