public Object down(Message msg) { if(!bypass) { Address dest = msg.getDest(); if (dest == null) { // mcasts FlushHeader fh =msg.getHeader(this.id); if (fh != null && fh.type == FlushHeader.FLUSH_BYPASS) { return down_prot.down(msg); } else { blockMessageDuringFlush(); } } else { // unicasts are irrelevant in virtual synchrony, let them through return down_prot.down(msg); } } return down_prot.down(msg); }
boolean needsReconciliationPhase = false; boolean collision = false; final Tuple<Collection<? extends Address>,Digest> tuple=readParticipantsAndDigest(m.getRawBuffer(), m.getOffset(),m.getLength()); Digest digest = tuple.getVal2(); + ", flushCompleted " + flushCompletedMap.keySet()); needsReconciliationPhase = enable_reconciliation && flushCompleted && hasVirtualSynchronyGaps(); if (needsReconciliationPhase) { Digest d = findHighestSequences(currentView); msg = new Message().setFlag(Message.Flag.OOB); reconcileOks.clear(); msg.putHeader(this.id, new FlushHeader(FlushHeader.FLUSH_RECONCILE, currentViewId())) .setBuffer(marshal(flushMembers, d)); } else if (collision) { Runnable r =() -> rejectFlush(tuple.getVal1(), header.viewID); new Thread(r).start();
@ManagedOperation(description = "Request end of flush in a cluster") public void stopFlush() { down(new Event(Event.RESUME)); }
flushParticipants=new ArrayList<>(currentView.getMembers()); onSuspend(flushParticipants); try { FlushStartResult r = flush_promise.getResultWithTimeout(start_flush_timeout); rejectFlush(flushParticipants, currentViewId()); throw new RuntimeException(localAddress + " timed out waiting for flush responses from "
/** * Starts the flush protocol * @param members List of participants in the flush protocol. Guaranteed to be non-null */ private void onSuspend(final List<Address> members) { Message msg = null; Collection<Address> participantsInFlush = null; synchronized (sharedLock) { flushCoordinator = localAddress; // start FLUSH only on group members that we need to flush participantsInFlush = members; participantsInFlush.retainAll(currentView.getMembers()); flushMembers.clear(); flushMembers.addAll(participantsInFlush); flushMembers.removeAll(suspected); msg = new Message(null).src(localAddress).setBuffer(marshal(participantsInFlush, null)) .putHeader(this.id, new FlushHeader(FlushHeader.START_FLUSH, currentViewId())); } if (participantsInFlush.isEmpty()) { flush_promise.setResult(SUCCESS_START_FLUSH); } else { down_prot.down(msg); if (log.isDebugEnabled()) log.debug(localAddress + ": flush coordinator " + " is starting FLUSH with participants " + participantsInFlush); } }
case Event.MSG: Message msg = (Message) evt.getArg(); FlushHeader fh = (FlushHeader) msg.getHeader(getName()); if (fh != null) { if (fh.type == FlushHeader.FLUSH_BYPASS) { return up_prot.up(evt); } else if (fh.type == FlushHeader.START_FLUSH) { handleStartFlush(msg, fh); } else if (fh.type == FlushHeader.FLUSH_RECONCILE) { handleFlushReconcile(msg, fh); } else if (fh.type == FlushHeader.FLUSH_RECONCILE_OK) { onFlushReconcileOK(msg); } else if (fh.type == FlushHeader.STOP_FLUSH) { onStopFlush(); } else if (fh.type == FlushHeader.ABORT_FLUSH) { } else if (isCurrentFlushMessage(fh)) { if (fh.type == FlushHeader.FLUSH_OK) { onFlushOk(msg.getSrc(), fh.viewID); } else if (fh.type == FlushHeader.STOP_FLUSH_OK) { onStopFlushOk(msg.getSrc()); } else if (fh.type == FlushHeader.FLUSH_COMPLETED) { onFlushCompleted(msg.getSrc(), fh.digest); boolean firstView = onViewChange(newView); boolean singletonMember = newView.size() == 1 && newView.containsMember(localAddress); onViewChange(tmpView);
final FlushHeader fh =msg.getHeader(this.id); if (fh != null) { final Tuple<Collection<? extends Address>,Digest> tuple=readParticipantsAndDigest(msg.getRawBuffer(), msg.getOffset(), msg.getLength()); || msg.getSrc().equals(localAddress); if (amIParticipant) { handleStartFlush(msg, fh); } else { if (log.isDebugEnabled()) handleFlushReconcile(msg); break; case FlushHeader.FLUSH_RECONCILE_OK: onFlushReconcileOK(msg); break; case FlushHeader.STOP_FLUSH: onStopFlush(); break; case FlushHeader.ABORT_FLUSH: resetForNextFlush(); break; case FlushHeader.FLUSH_NOT_COMPLETED: Runnable r =() -> rejectFlush(tuple.getVal1(), fh.viewID); new Thread(r).start();
public Object down(Event evt) { switch (evt.getType()) { case Event.MSG: Message msg = (Message) evt.getArg(); FlushHeader fh = (FlushHeader) msg.getHeader(getName()); if (fh != null && fh.type == FlushHeader.FLUSH_BYPASS) { return down_prot.down(evt); } else { blockMessageDuringFlush(); } break; case Event.GET_STATE: blockMessageDuringFlush(); break; case Event.CONNECT: sendBlockUpToChannel(); break; case Event.SUSPEND: return startFlush(evt, 3, false); case Event.RESUME: onResume(); return null; } return down_prot.down(evt); }
+ flushCompletedMap.keySet()); needsReconciliationPhase = enable_reconciliation && flushCompleted && hasVirtualSynchronyGaps(); if (needsReconciliationPhase){ Digest d = findHighestSequences(); msg = new Message(); msg.setFlag(Message.OOB); FlushHeader fh = new FlushHeader(FlushHeader.FLUSH_RECONCILE, currentViewId(), flushMembers); reconcileOks.clear(); fh.addDigest(d); msg.putHeader(getName(), fh);
+ " I am the neighbor, completing the flush "); onResume(new Event(Event.RESUME, flushMembersCopy)); suspected.addAll(addresses); flushMembers.removeAll(suspected); viewID = currentViewId(); flushOkCompleted = !flushCompletedMap.isEmpty() && flushCompletedMap.keySet().containsAll(flushMembers); if (flushOkCompleted) { m.putHeader(this.id, new FlushHeader(FlushHeader.FLUSH_COMPLETED, viewID)).setBuffer(marshal(null, digest)); down_prot.down(m);
private void onResume() { long viewID = currentViewId(); Message msg = new Message(null, localAddress, null); msg.putHeader(getName(), new FlushHeader(FlushHeader.STOP_FLUSH, viewID)); down_prot.down(new Event(Event.MSG, msg)); if (log.isDebugEnabled()) log.debug("Received RESUME at " + localAddress + ", sent STOP_FLUSH to all"); }
@SuppressWarnings("unchecked") private void onResume(Event evt) { List<Address> members =evt.getArg(); long viewID = currentViewId(); boolean isParticipant = false; synchronized(sharedLock) { isParticipant = flushMembers.contains(localAddress) || (members != null && members.contains(localAddress)); } if (members == null || members.isEmpty()) { Message msg = new Message(null).src(localAddress); // Cannot be OOB since START_FLUSH is not OOB // we have to FIFO order two subsequent flushes if (log.isDebugEnabled()) log.debug(localAddress + ": received RESUME, sending STOP_FLUSH to all"); msg.putHeader(this.id, new FlushHeader(FlushHeader.STOP_FLUSH, viewID)); down_prot.down(msg); } else { for (Address address : members) { Message msg = new Message(address).src(localAddress); // Cannot be OOB since START_FLUSH is not OOB // we have to FIFO order two subsequent flushes if (log.isDebugEnabled()) log.debug(localAddress + ": received RESUME, sending STOP_FLUSH to " + address); msg.putHeader(this.id, new FlushHeader(FlushHeader.STOP_FLUSH, viewID)); down_prot.down(msg); } } if(isParticipant) waitForUnblock(); }
private boolean isCurrentFlushMessage(FlushHeader fh) { return fh.viewID == currentViewId(); }
final FlushHeader fh =msg.getHeader(this.id); if (fh != null) { final Tuple<Collection<? extends Address>,Digest> tuple=readParticipantsAndDigest(msg.getRawBuffer(), msg.getOffset(), msg.getLength()); || msg.getSrc().equals(localAddress); if (amIParticipant) { handleStartFlush(msg, fh); } else { if (log.isDebugEnabled()) handleFlushReconcile(msg); break; case FlushHeader.FLUSH_RECONCILE_OK: onFlushReconcileOK(msg); break; case FlushHeader.STOP_FLUSH: onStopFlush(); break; case FlushHeader.ABORT_FLUSH: resetForNextFlush(); break; case FlushHeader.FLUSH_NOT_COMPLETED: Runnable r =() -> rejectFlush(tuple.getVal1(), fh.viewID); new Thread(r).start();
flushParticipants=new ArrayList<>(currentView.getMembers()); onSuspend(flushParticipants); try { FlushStartResult r = flush_promise.getResultWithTimeout(start_flush_timeout); rejectFlush(flushParticipants, currentViewId()); throw new RuntimeException(localAddress + " timed out waiting for flush responses from "
+ " I am the neighbor, completing the flush "); onResume(new Event(Event.RESUME, flushMembersCopy)); suspected.addAll(addresses); flushMembers.removeAll(suspected); viewID = currentViewId(); flushOkCompleted = !flushCompletedMap.isEmpty() && flushCompletedMap.keySet().containsAll(flushMembers); if (flushOkCompleted) { m.putHeader(this.id, new FlushHeader(FlushHeader.FLUSH_COMPLETED, viewID)).setBuffer(marshal(null, digest)); down_prot.down(m);
private void onSuspect(Address address) { boolean flushOkCompleted = false; Message m = null; long viewID = 0; synchronized (sharedLock) { suspected.add(address); flushMembers.removeAll(suspected); viewID = currentViewId(); flushOkCompleted = !flushOkSet.isEmpty() && flushOkSet.containsAll(flushMembers); if (flushOkCompleted) { m = new Message(flushCoordinator, localAddress, null); } if (log.isDebugEnabled()) log.debug("Suspect is " + address + ",completed " + flushOkCompleted + ", flushOkSet " + flushOkSet + " flushMembers " + flushMembers); } if (flushOkCompleted) { Digest digest = (Digest) down_prot.down(new Event(Event.GET_DIGEST)); FlushHeader fh = new FlushHeader(FlushHeader.FLUSH_COMPLETED,viewID); fh.addDigest(digest); m.putHeader(getName(), fh); down_prot.down(new Event(Event.MSG, m)); if (log.isDebugEnabled()) log.debug(localAddress + " sent FLUSH_COMPLETED message to " + flushCoordinator); } }
/** * Starts the flush protocol * @param members List of participants in the flush protocol. Guaranteed to be non-null */ private void onSuspend(final List<Address> members) { Message msg = null; Collection<Address> participantsInFlush = null; synchronized (sharedLock) { flushCoordinator = localAddress; // start FLUSH only on group members that we need to flush participantsInFlush = members; participantsInFlush.retainAll(currentView.getMembers()); flushMembers.clear(); flushMembers.addAll(participantsInFlush); flushMembers.removeAll(suspected); msg = new Message(null).src(localAddress).setBuffer(marshal(participantsInFlush, null)) .putHeader(this.id, new FlushHeader(FlushHeader.START_FLUSH, currentViewId())); } if (participantsInFlush.isEmpty()) { flush_promise.setResult(SUCCESS_START_FLUSH); } else { down_prot.down(msg); if (log.isDebugEnabled()) log.debug(localAddress + ": flush coordinator " + " is starting FLUSH with participants " + participantsInFlush); } }
@SuppressWarnings("unchecked") private void onResume(Event evt) { List<Address> members =evt.getArg(); long viewID = currentViewId(); boolean isParticipant = false; synchronized(sharedLock) { isParticipant = flushMembers.contains(localAddress) || (members != null && members.contains(localAddress)); } if (members == null || members.isEmpty()) { Message msg = new Message(null).src(localAddress); // Cannot be OOB since START_FLUSH is not OOB // we have to FIFO order two subsequent flushes if (log.isDebugEnabled()) log.debug(localAddress + ": received RESUME, sending STOP_FLUSH to all"); msg.putHeader(this.id, new FlushHeader(FlushHeader.STOP_FLUSH, viewID)); down_prot.down(msg); } else { for (Address address : members) { Message msg = new Message(address).src(localAddress); // Cannot be OOB since START_FLUSH is not OOB // we have to FIFO order two subsequent flushes if (log.isDebugEnabled()) log.debug(localAddress + ": received RESUME, sending STOP_FLUSH to " + address); msg.putHeader(this.id, new FlushHeader(FlushHeader.STOP_FLUSH, viewID)); down_prot.down(msg); } } if(isParticipant) waitForUnblock(); }
private boolean isCurrentFlushMessage(FlushHeader fh) { return fh.viewID == currentViewId(); }