/// <summary> /// Stops any awaiting stability multicasts, passes STABLE Event up the stack. /// </summary> /// <param name="d">Stable Digest</param> private void handleStabilityMessage(Digest d) { if (d == null) { if (Trace.trace) { Trace.error("STABLE.handleStabilityMessage()", "stability vector is null"); } return; } if (Trace.trace) { Trace.info("STABLE.handleStabilityMessage()", "stability vector is " + d.printHighSeqnos()); } lock (stability_mutex) { if (stability_task != null) { if (Trace.trace) { Trace.info("STABLE.handleStabilityMessage()", "cancelling stability task (running=" + !stability_task.cancelled() + ")"); } stability_task.stop(); stability_task = null; } } // pass STABLE event up the stack, so NAKACK can garbage collect old messages passUp(new Event(Event.STABLE, d)); }
/// <remarks> /// The reason for waiting a random amount of time is that, in the worst case, all members receive a /// STABLE_GOSSIP message from the last outstanding member at the same time and would therefore mcast the /// STABILITY message at the same time too. To avoid this, each member waits random N msecs. If, before N /// elapses, some other member sent the STABILITY message, we just cancel our own message. If, during /// waiting for N msecs to send STABILITY message S1, another STABILITY message S2 is to be sent, we just /// discard S2. /// </remarks> /// <summary> /// Schedules a stability message to be mcast after a random number of milliseconds. /// </summary> /// <param name="tmp">Stable Digest</param> private void sendStabilityMessage(Digest tmp) { long delay; if (timer == null) { if (Trace.trace) { Trace.error("STABLE.sendStabilityMessage()", "timer is null, cannot schedule " + "stability message to be sent"); } timer = stack != null ? stack.timer : null; return; } // give other members a chance to mcast STABILITY message. if we receive STABILITY by the end of // our random sleep, we will not send the STABILITY msg. this prevents that all mbrs mcast a // STABILITY msg at the same time delay = random.Next((int)stability_delay); if (Trace.trace) { Trace.info("STABLE.sendStabilityMessage()", "stability_task=" + stability_task + ", delay is " + delay); } lock (stability_mutex) { if (stability_task != null && !stability_task.cancelled()) // schedule only if not yet running { return; } stability_task = new StabilitySendTask(this, tmp, delay); timer.add(stability_task, true); // run it 1x after delay msecs. use fixed-rate scheduling } }
/// <remarks> /// The reason for waiting a random amount of time is that, in the worst case, all members receive a /// STABLE_GOSSIP message from the last outstanding member at the same time and would therefore mcast the /// STABILITY message at the same time too. To avoid this, each member waits random N msecs. If, before N /// elapses, some other member sent the STABILITY message, we just cancel our own message. If, during /// waiting for N msecs to send STABILITY message S1, another STABILITY message S2 is to be sent, we just /// discard S2. /// </remarks> /// <summary> /// Schedules a stability message to be mcast after a random number of milliseconds. /// </summary> /// <param name="tmp">Stable Digest</param> private void sendStabilityMessage(Digest tmp) { long delay; if(timer == null) { if(Trace.trace) Trace.error("STABLE.sendStabilityMessage()", "timer is null, cannot schedule " + "stability message to be sent"); timer=stack != null ? stack.timer : null; return; } // give other members a chance to mcast STABILITY message. if we receive STABILITY by the end of // our random sleep, we will not send the STABILITY msg. this prevents that all mbrs mcast a // STABILITY msg at the same time delay=random.Next((int)stability_delay); if(Trace.trace) Trace.info("STABLE.sendStabilityMessage()", "stability_task=" + stability_task + ", delay is " + delay); lock(stability_mutex) { if(stability_task != null && !stability_task.cancelled()) // schedule only if not yet running return; stability_task =new StabilitySendTask(this, tmp, delay); timer.add(stability_task, true); // run it 1x after delay msecs. use fixed-rate scheduling } }
/// <summary> /// Stops any awaiting stability multicasts, passes STABLE Event up the stack. /// </summary> /// <param name="d">Stable Digest</param> private void handleStabilityMessage(Digest d) { if(d == null) { if(Trace.trace) Trace.error("STABLE.handleStabilityMessage()", "stability vector is null"); return; } if(Trace.trace) Trace.info("STABLE.handleStabilityMessage()", "stability vector is " + d.printHighSeqnos()); lock(stability_mutex) { if(stability_task != null) { if(Trace.trace) Trace.info("STABLE.handleStabilityMessage()", "cancelling stability task (running=" + !stability_task.cancelled() + ")"); stability_task.stop(); stability_task=null; } } // pass STABLE event up the stack, so NAKACK can garbage collect old messages passUp(new Event(Event.STABLE, d)); }