Ejemplo n.º 1
0
  /** Execute when new member join or leave Group */
  public void viewAccepted(View v) {
    memberSize = v.size();
    if (mainFrame != null) setTitle();
    members.clear();
    members.addAll(v.getMembers());

    if (v instanceof MergeView) {
      System.out.println("** " + v);

      // This is a simple merge function, which fetches the state from the coordinator
      // on a merge and overwrites all of its own state
      if (useState && !members.isEmpty()) {
        Address coord = members.get(0);
        Address local_addr = channel.getAddress();
        if (local_addr != null && !local_addr.equals(coord)) {
          try {

            // make a copy of our state first
            Map<Point, Color> copy = null;
            if (send_own_state_on_merge) {
              synchronized (drawPanel.state) {
                copy = new LinkedHashMap<Point, Color>(drawPanel.state);
              }
            }
            System.out.println("fetching state from " + coord);
            channel.getState(coord, 5000);
            if (copy != null)
              sendOwnState(copy); // multicast my own state so everybody else has it too
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }
    } else System.out.println("** View=" + v);
  }
Ejemplo n.º 2
0
  private synchronized void handleViewChange(View view, boolean makeServer) {
    if (makeServer) initializeNewSymmetricKey(view instanceof MergeView);

    // if view is a bit broken set me as keyserver
    List<Address> members = view.getMembers();
    if (members == null || members.isEmpty() || members.get(0) == null) {
      becomeKeyServer(local_addr, false);
      return;
    }
    // otherwise get keyserver from view controller
    Address tmpKeyServer = view.getMembers().get(0);

    // I am  keyserver - either first member of group or old key server is no more and
    // I have been voted new controller
    if (makeServer || (tmpKeyServer.equals(local_addr))) becomeKeyServer(tmpKeyServer, makeServer);
    else handleNewKeyServer(tmpKeyServer, view instanceof MergeView);
  }
Ejemplo n.º 3
0
  protected void handleView(View view) {
    this.view = view;
    if (log.isDebugEnabled()) log.debug("view=" + view);
    List<Address> members = view.getMembers();

    _consumerLock.lock();
    try {
      // This removes the consumers that were registered that are now gone
      Iterator<Owner> iterator = _consumersAvailable.iterator();
      while (iterator.hasNext()) {
        Owner owner = iterator.next();
        if (!members.contains(owner.getAddress())) {
          iterator.remove();
          sendRemoveConsumerRequest(owner);
        }
      }

      // This removes the tasks that those requestors are gone
      iterator = _runRequests.iterator();
      while (iterator.hasNext()) {
        Owner owner = iterator.next();
        if (!members.contains(owner.getAddress())) {
          iterator.remove();
          sendRemoveRunRequest(owner);
        }
      }

      synchronized (_awaitingReturn) {
        for (Entry<Owner, Runnable> entry : _awaitingReturn.entrySet()) {
          // The person currently servicing our request has gone down
          // without completing so we have to keep our request alive by
          // sending ours back to the coordinator
          Owner owner = entry.getKey();
          if (!members.contains(owner.getAddress())) {
            Runnable runnable = entry.getValue();
            // We need to register the request id before sending the request back to the coordinator
            // in case if our task gets picked up since another was removed
            _requestId.put(runnable, owner.getRequestId());
            _awaitingConsumer.add(runnable);
            sendToCoordinator(RUN_REQUEST, owner.getRequestId(), local_addr);
          }
        }
      }
    } finally {
      _consumerLock.unlock();
    }
  }
Ejemplo n.º 4
0
 public void startFlush(List<Address> flushParticipants, boolean automatic_resume)
     throws Exception {
   if (!flushSupported())
     throw new IllegalStateException(
         "Flush is not supported, add pbcast.FLUSH protocol to your configuration");
   View v = getView();
   boolean validParticipants = v != null && v.getMembers().containsAll(flushParticipants);
   if (!validParticipants)
     throw new IllegalArgumentException(
         "Current view " + v + " does not contain all flush participants " + flushParticipants);
   try {
     down(new Event(Event.SUSPEND, flushParticipants));
   } catch (Exception e) {
     throw new Exception("Flush failed", e.getCause());
   } finally {
     if (automatic_resume) stopFlush(flushParticipants);
   }
 }
Ejemplo n.º 5
0
  protected boolean _startFlush(
      final View new_view, int maxAttempts, long randomFloor, long randomCeiling) {
    if (!flushProtocolInStack) return true;
    if (flushInvokerClass != null) {
      try {
        Callable<Boolean> invoker =
            flushInvokerClass.getDeclaredConstructor(View.class).newInstance(new_view);
        return invoker.call();
      } catch (Throwable e) {
        return false;
      }
    }

    try {
      boolean successfulFlush = false;
      boolean validView = new_view != null && new_view.size() > 0;
      if (validView && flushProtocolInStack) {
        int attemptCount = 0;
        while (attemptCount < maxAttempts) {
          try {
            up_prot.up(new Event(Event.SUSPEND, new ArrayList<Address>(new_view.getMembers())));
            successfulFlush = true;
            break;
          } catch (Exception e) {
            Util.sleepRandom(randomFloor, randomCeiling);
            attemptCount++;
          }
        }

        if (successfulFlush) {
          if (log.isTraceEnabled()) log.trace(local_addr + ": successful GMS flush by coordinator");
        } else {
          if (log.isWarnEnabled()) log.warn(local_addr + ": GMS flush by coordinator failed");
        }
      }
      return successfulFlush;
    } catch (Exception e) {
      return false;
    }
  }
Ejemplo n.º 6
0
  /**
   * Callback method <br>
   * Called by the ProtocolStack when a message is received.
   *
   * @param evt the event carrying the message from the protocol stack
   */
  public Object up(Event evt) {
    switch (evt.getType()) {
      case Event.MSG:
        Message msg = (Message) evt.getArg();
        if (stats) {
          received_msgs++;
          received_bytes += msg.getLength();
        }

        // discard local messages (sent by myself to me)
        if (discard_own_messages
            && local_addr != null
            && msg.getSrc() != null
            && local_addr.equals(msg.getSrc())) return null;
        break;

      case Event.VIEW_CHANGE:
        View tmp = (View) evt.getArg();
        if (tmp instanceof MergeView) my_view = new View(tmp.getViewId(), tmp.getMembers());
        else my_view = tmp;

        // Bela&Vladimir Oct 27th,2006 (JGroups 2.4): we need to set connected=true because a client
        // can
        // call channel.getView() in viewAccepted() callback invoked on this thread (see
        // Event.VIEW_CHANGE handling below)

        // not good: we are only connected when we returned from connect() - bela June 22 2007
        // Changed: when a channel gets a view of which it is a member then it should be
        // connected even if connect() hasn't returned yet ! (bela Noc 2010)
        if (state != State.CONNECTED) state = State.CONNECTED;
        break;

      case Event.CONFIG:
        Map<String, Object> cfg = (Map<String, Object>) evt.getArg();
        if (cfg != null) {
          if (cfg.containsKey("state_transfer")) {
            state_transfer_supported = (Boolean) cfg.get("state_transfer");
          }
          if (cfg.containsKey("flush_supported")) {
            flush_supported = (Boolean) cfg.get("flush_supported");
          }
        }
        break;

      case Event.GET_STATE_OK:
        StateTransferResult result = (StateTransferResult) evt.getArg();
        if (up_handler != null) {
          try {
            Object retval = up_handler.up(evt);
            state_promise.setResult(new StateTransferResult());
            return retval;
          } catch (Throwable t) {
            state_promise.setResult(new StateTransferResult(t));
          }
        }

        if (receiver != null) {
          try {
            if (result.hasBuffer()) {
              byte[] tmp_state = result.getBuffer();
              ByteArrayInputStream input = new ByteArrayInputStream(tmp_state);
              receiver.setState(input);
            }
            state_promise.setResult(result);
          } catch (Throwable t) {
            state_promise.setResult(new StateTransferResult(t));
          }
        }
        break;

      case Event.STATE_TRANSFER_INPUTSTREAM_CLOSED:
        state_promise.setResult((StateTransferResult) evt.getArg());
        break;

      case Event.STATE_TRANSFER_INPUTSTREAM:
        // Oct 13,2006 moved to down() when Event.STATE_TRANSFER_INPUTSTREAM_CLOSED is received
        // state_promise.setResult(is != null? Boolean.TRUE : Boolean.FALSE);

        if (up_handler != null) return up_handler.up(evt);

        InputStream is = (InputStream) evt.getArg();
        if (is != null && receiver != null) {
          try {
            receiver.setState(is);
          } catch (Throwable t) {
            throw new RuntimeException("failed calling setState() in state requester", t);
          }
        }
        break;

      case Event.STATE_TRANSFER_OUTPUTSTREAM:
        if (receiver != null && evt.getArg() != null) {
          try {
            receiver.getState((OutputStream) evt.getArg());
          } catch (Exception e) {
            throw new RuntimeException("failed calling getState() in state provider", e);
          }
        }
        break;

      case Event.GET_LOCAL_ADDRESS:
        return local_addr;

      default:
        break;
    }

    // If UpHandler is installed, pass all events to it and return (UpHandler is e.g. a building
    // block)
    if (up_handler != null) return up_handler.up(evt);

    if (receiver != null) return invokeCallback(evt.getType(), evt.getArg());
    return null;
  }
Ejemplo n.º 7
0
 Address determineCoordinator() {
   List<Address> mbrs = my_view != null ? my_view.getMembers() : null;
   if (mbrs == null) return null;
   if (!mbrs.isEmpty()) return mbrs.iterator().next();
   return null;
 }
Ejemplo n.º 8
0
  /**
   * Sets the new view and sends a VIEW_CHANGE event up and down the stack. If the view is a
   * MergeView (subclass of View), then digest will be non-null and has to be set before installing
   * the view.
   */
  public void installView(View new_view, Digest digest) {
    ViewId vid = new_view.getVid();
    List<Address> mbrs = new_view.getMembers();
    ltime =
        Math.max(
            vid.getId(),
            ltime); // compute the logical time, regardless of whether the view is accepted

    // Discards view with id lower than or equal to our own. Will be installed without check if it
    // is the first view
    if (view != null) {
      ViewId view_id = view.getViewId();
      int rc = vid.compareToIDs(view_id);
      if (rc <= 0) {
        if (log.isWarnEnabled()
            && rc < 0
            && log_view_warnings) { // only scream if view is smaller, silently discard same views
          log.warn(
              local_addr
                  + ": received view < current view;"
                  + " discarding it (current vid: "
                  + view_id
                  + ", new vid: "
                  + vid
                  + ')');
        }
        return;
      }
    }

    /* Check for self-inclusion: if I'm not part of the new membership, I just discard it.
    This ensures that messages sent in view V1 are only received by members of V1 */
    if (!mbrs.contains(local_addr)) {
      if (log.isWarnEnabled() && log_view_warnings)
        log.warn(local_addr + ": not member of view " + new_view.getViewId() + "; discarding it");
      return;
    }

    if (digest != null) {
      if (new_view instanceof MergeView) mergeDigest(digest);
      else setDigest(digest);
    }

    if (log.isDebugEnabled()) log.debug(local_addr + ": installing view " + new_view);

    Event view_event;
    synchronized (members) {
      view = new View(new_view.getVid(), new_view.getMembers());
      view_event = new Event(Event.VIEW_CHANGE, new_view);

      // Set the membership. Take into account joining members
      if (!mbrs.isEmpty()) {
        members.set(mbrs);
        tmp_members.set(members);
        joining.removeAll(mbrs); // remove all members in mbrs from joining
        // remove all elements from 'leaving' that are not in 'mbrs'
        leaving.retainAll(mbrs);

        tmp_members.add(joining); // add members that haven't yet shown up in the membership
        tmp_members.remove(
            leaving); // remove members that haven't yet been removed from the membership

        // add to prev_members
        for (Address addr : mbrs) {
          if (!prev_members.contains(addr)) prev_members.add(addr);
        }
      }

      Address coord = determineCoordinator();
      if (coord != null && coord.equals(local_addr) && !haveCoordinatorRole()) {
        becomeCoordinator();
      } else {
        if (haveCoordinatorRole() && !local_addr.equals(coord)) {
          becomeParticipant();
          merge_ack_collector.reset(null); // we don't need this one anymore
        }
      }
    }

    // - Changed order of passing view up and down (http://jira.jboss.com/jira/browse/JGRP-347)
    // - Changed it back (bela Sept 4 2007): http://jira.jboss.com/jira/browse/JGRP-564
    // - Moved sending up view_event out of the synchronized block (bela Nov 2011)
    down_prot.down(view_event); // needed e.g. by failure detector or UDP
    up_prot.up(view_event);

    List<Address> tmp_mbrs = new_view.getMembers();
    ack_collector.retainAll(tmp_mbrs);
    merge_ack_collector.retainAll(tmp_mbrs);

    if (new_view instanceof MergeView) merger.forceCancelMerge();

    if (stats) {
      num_views++;
      prev_views.add(new Tuple<View, Long>(new_view, System.currentTimeMillis()));
    }
  }
Ejemplo n.º 9
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());
        }
      }
    }
  }
Ejemplo n.º 10
0
  protected Object handleUpEvent(Event evt) throws Exception {
    switch (evt.getType()) {
      case Event.MSG:
        if (msg_listener != null) msg_listener.receive((Message) evt.getArg());
        break;

      case Event.GET_APPLSTATE: // reply with GET_APPLSTATE_OK
        byte[] tmp_state = null;
        if (msg_listener != null) {
          ByteArrayOutputStream output = new ByteArrayOutputStream(1024);
          msg_listener.getState(output);
          tmp_state = output.toByteArray();
        }
        return new StateTransferInfo(null, 0L, tmp_state);

      case Event.GET_STATE_OK:
        if (msg_listener != null) {
          StateTransferResult result = (StateTransferResult) evt.getArg();
          if (result.hasBuffer()) {
            ByteArrayInputStream input = new ByteArrayInputStream(result.getBuffer());
            msg_listener.setState(input);
          }
        }
        break;

      case Event.STATE_TRANSFER_OUTPUTSTREAM:
        OutputStream os = (OutputStream) evt.getArg();
        if (msg_listener != null && os != null) {
          msg_listener.getState(os);
        }
        break;

      case Event.STATE_TRANSFER_INPUTSTREAM:
        InputStream is = (InputStream) evt.getArg();
        if (msg_listener != null && is != null) msg_listener.setState(is);
        break;

      case Event.VIEW_CHANGE:
        View v = (View) evt.getArg();
        List<Address> new_mbrs = v.getMembers();
        setMembers(new_mbrs);
        if (membership_listener != null) membership_listener.viewAccepted(v);
        break;

      case Event.SET_LOCAL_ADDRESS:
        if (log.isTraceEnabled())
          log.trace("setting local_addr (" + local_addr + ") to " + evt.getArg());
        local_addr = (Address) evt.getArg();
        break;

      case Event.SUSPECT:
        if (membership_listener != null) membership_listener.suspect((Address) evt.getArg());
        break;

      case Event.BLOCK:
        if (membership_listener != null) membership_listener.block();
        break;
      case Event.UNBLOCK:
        if (membership_listener != null) membership_listener.unblock();
        break;
    }

    return null;
  }