@Override public void start() throws Exception { deliverManager = new DeliveryManagerImpl(); senderManager = new SenderManager(); if(deliverThread == null) { deliverThread=new DeliveryThread(this); deliverThread.setLocalAddress(localAddress.toString()); } deliverThread.start(deliverManager); statsCollector.setStatsEnabled(statsEnabled()); }
deliverManager.deliverSingleDestinationMessage(message, messageID); } else { down_prot.down(message); ToaHeader header = ToaHeader.newDataMessageHeader(messageID, deliverManager.getViewId()); message.putHeader(this.id, header); deliverManager.addLocalMessageToDeliver(messageID, message, header) : -1;
/** * Updates the current view in use and returns a {@link Collection} with the members that left the cluster. */ public final Collection<Address> handleView(View newView) { View oldView; synchronized (deliverySet) { oldView = getAndSetView(newView); deliverySet.removeIf(this::removeMessage); notifyIfNeeded(); } return View.leftMembers(oldView, newView); }
private void handleViewChange(View view) { if (log.isTraceEnabled()) { log.trace("Handle view %s", view); } final Collection<Address> leavers = deliverManager.handleView(view); //basis behavior: drop leavers message (as senders) //basis behavior: avoid waiting for the acks Collection<MessageID> pendingSentMessages = senderManager.getPendingMessageIDs(); for (MessageID messageID : pendingSentMessages) { long finalSequenceNumber = senderManager.removeLeavers(messageID, leavers); if (finalSequenceNumber != SenderManager.NOT_READY) { ToaHeader finalHeader = ToaHeader.newFinalMessageHeader(messageID, finalSequenceNumber); Message finalMessage = new Message().src(localAddress).putHeader(this.id, finalHeader) .setFlag(Message.Flag.OOB, Message.Flag.INTERNAL, Message.Flag.DONT_BUNDLE); if (log.isTraceEnabled()) { log.trace("Message %s is ready to be delivered. Final sequencer number is %d", messageID, finalSequenceNumber); } send(senderManager.getDestination(messageID), finalMessage, false); //returns true if we are in destination set if (senderManager.markSent(messageID)) { deliverManager.markReadyToDeliver(messageID, finalSequenceNumber); } } } // TODO: Future work: How to add fault tolerance? (simple and efficient) }
deliverManager.updateSequenceNumber(header.getSequencerNumber()); long finalSequenceNumber = senderManager.addPropose(messageID, from, header.getSequencerNumber()); deliverManager.markReadyToDeliver(messageID, finalSequenceNumber);
/** * @return the current view id or {@code -1} if no view is installed yet. */ public long getViewId() { synchronized (deliverySet) { return internalGetViewId(); } }
@ManagedOperation public String getMessageList() { return deliverManager.getMessageSet().toString(); }
private void handleFinalSequenceNumber(ToaHeader header) { long startTime = statsCollector.now(); long duration = -1; try { MessageID messageID = header.getMessageID(); if (log.isTraceEnabled()) { log.trace("Received the final sequence number message with %s", header); } deliverManager.markReadyToDeliver(messageID, header.getSequencerNumber()); duration = statsCollector.now() - startTime; } catch (Exception e) { logException("Exception caught while processing the final sequence number for " + header.getMessageID(), e); } finally { statsCollector.addFinalSequenceNumberDuration(duration); } }
public Object up(Message message) { ToaHeader header=message.getHeader(this.id); if (header == null) return up_prot.up(message); switch (header.getType()) { case ToaHeader.DATA_MESSAGE: handleDataMessage(message, header); break; case ToaHeader.PROPOSE_MESSAGE: handleSequenceNumberPropose(message.getSrc(), header); break; case ToaHeader.FINAL_MESSAGE: handleFinalSequenceNumber(header); break; case ToaHeader.SINGLE_DESTINATION_MESSAGE: if (log.isTraceEnabled()) { log.trace("Received message %s with SINGLE_DESTINATION header. delivering...", message); } deliverManager.deliverSingleDestinationMessage(message, header.getMessageID()); break; default: throw new IllegalStateException("Unknown header type received " + header); } return null; }
private void handleDataMessage(Message message, ToaHeader header) { final long startTime = statsCollector.now(); try { final MessageID messageID = header.getMessageID(); //create the sequence number and put it in deliver manager long myProposeSequenceNumber = deliverManager.addRemoteMessageToDeliver(messageID, message, header.getSequencerNumber(), header.getViewId()); if (log.isTraceEnabled()) { log.trace("Received the message with %s. The proposed sequence number is %d", header, myProposeSequenceNumber); } if (myProposeSequenceNumber == -1) { //message discarded. not sending ack back. return; } //create a new message and send it back ToaHeader newHeader = ToaHeader.newProposeMessageHeader(messageID, myProposeSequenceNumber); Message proposeMessage = new Message().src(localAddress).dest(messageID.getAddress()) .putHeader(this.id, newHeader).setFlag(Message.Flag.OOB, Message.Flag.INTERNAL, Message.Flag.DONT_BUNDLE); //multicastSenderThread.addUnicastMessage(proposeMessage); down_prot.down(proposeMessage); } catch (Exception e) { logException("Exception caught while processing the data message " + header.getMessageID(), e); } finally { statsCollector.addDataMessageDuration(statsCollector.now() - startTime); } }
private void handleViewChange(View view) { if (log.isTraceEnabled()) { log.trace("Handle view %s", view); } final Collection<Address> leavers = deliverManager.handleView(view); //basis behavior: drop leavers message (as senders) //basis behavior: avoid waiting for the acks Collection<MessageID> pendingSentMessages = senderManager.getPendingMessageIDs(); for (MessageID messageID : pendingSentMessages) { long finalSequenceNumber = senderManager.removeLeavers(messageID, leavers); if (finalSequenceNumber != SenderManager.NOT_READY) { ToaHeader finalHeader = ToaHeader.newFinalMessageHeader(messageID, finalSequenceNumber); Message finalMessage = new Message().src(localAddress).putHeader(this.id, finalHeader) .setFlag(Message.Flag.OOB, Message.Flag.INTERNAL, Message.Flag.DONT_BUNDLE); if (log.isTraceEnabled()) { log.trace("Message %s is ready to be delivered. Final sequencer number is %d", messageID, finalSequenceNumber); } send(senderManager.getDestination(messageID), finalMessage, false); //returns true if we are in destination set if (senderManager.markSent(messageID)) { deliverManager.markReadyToDeliver(messageID, finalSequenceNumber); } } } // TODO: Future work: How to add fault tolerance? (simple and efficient) }
deliverManager.updateSequenceNumber(header.getSequencerNumber()); long finalSequenceNumber = senderManager.addPropose(messageID, from, header.getSequencerNumber()); deliverManager.markReadyToDeliver(messageID, finalSequenceNumber);
long addRemoteMessageToDeliver(MessageID messageID, Message message, long remoteSequenceNumber, long viewId) { MessageInfo messageInfo; long sequenceNumber; synchronized (deliverySet) { long currentViewId = internalGetViewId(); if (currentViewId != -1 //we have a view, check the view id && viewId <= currentViewId //message from the current or previous view, check the members && !currentView.containsMember(message.getSrc())) { //node no longer in view. discard it return -1; } sequenceNumber = sequenceNumberManager.updateAndGet(remoteSequenceNumber); messageInfo = new MessageInfo(messageID, message, sequenceNumber); deliverySet.add(messageInfo); } messageCache.put(messageID, messageInfo); return sequenceNumber; }
@ManagedOperation public String getMessageList() { return deliverManager.getMessageSet().toString(); }
private void handleFinalSequenceNumber(ToaHeader header) { long startTime = statsCollector.now(); long duration = -1; try { MessageID messageID = header.getMessageID(); if (log.isTraceEnabled()) { log.trace("Received the final sequence number message with %s", header); } deliverManager.markReadyToDeliver(messageID, header.getSequencerNumber()); duration = statsCollector.now() - startTime; } catch (Exception e) { logException("Exception caught while processing the final sequence number for " + header.getMessageID(), e); } finally { statsCollector.addFinalSequenceNumberDuration(duration); } }
public Object up(Message message) { ToaHeader header=message.getHeader(this.id); if (header == null) return up_prot.up(message); switch (header.getType()) { case ToaHeader.DATA_MESSAGE: handleDataMessage(message, header); break; case ToaHeader.PROPOSE_MESSAGE: handleSequenceNumberPropose(message.getSrc(), header); break; case ToaHeader.FINAL_MESSAGE: handleFinalSequenceNumber(header); break; case ToaHeader.SINGLE_DESTINATION_MESSAGE: if (log.isTraceEnabled()) { log.trace("Received message %s with SINGLE_DESTINATION header. delivering...", message); } deliverManager.deliverSingleDestinationMessage(message, header.getMessageID()); break; default: throw new IllegalStateException("Unknown header type received " + header); } return null; }
private void handleDataMessage(Message message, ToaHeader header) { final long startTime = statsCollector.now(); try { final MessageID messageID = header.getMessageID(); //create the sequence number and put it in deliver manager long myProposeSequenceNumber = deliverManager.addRemoteMessageToDeliver(messageID, message, header.getSequencerNumber(), header.getViewId()); if (log.isTraceEnabled()) { log.trace("Received the message with %s. The proposed sequence number is %d", header, myProposeSequenceNumber); } if (myProposeSequenceNumber == -1) { //message discarded. not sending ack back. return; } //create a new message and send it back ToaHeader newHeader = ToaHeader.newProposeMessageHeader(messageID, myProposeSequenceNumber); Message proposeMessage = new Message().src(localAddress).dest(messageID.getAddress()) .putHeader(this.id, newHeader).setFlag(Message.Flag.OOB, Message.Flag.INTERNAL, Message.Flag.DONT_BUNDLE); //multicastSenderThread.addUnicastMessage(proposeMessage); down_prot.down(proposeMessage); } catch (Exception e) { logException("Exception caught while processing the data message " + header.getMessageID(), e); } finally { statsCollector.addDataMessageDuration(statsCollector.now() - startTime); } }
deliverManager.deliverSingleDestinationMessage(message, messageID); } else { down_prot.down(message); ToaHeader header = ToaHeader.newDataMessageHeader(messageID, deliverManager.getViewId()); message.putHeader(this.id, header); deliverManager.addLocalMessageToDeliver(messageID, message, header) : -1;
/** * Updates the current view in use and returns a {@link Collection} with the members that left the cluster. */ public final Collection<Address> handleView(View newView) { View oldView; synchronized (deliverySet) { oldView = getAndSetView(newView); deliverySet.removeIf(this::removeMessage); notifyIfNeeded(); } return View.leftMembers(oldView, newView); }
/** * @return the current view id or {@code -1} if no view is installed yet. */ public long getViewId() { synchronized (deliverySet) { return internalGetViewId(); } }