/// <summary> /// Sends a Heartbeat to the <i>next</i> member in the group /// </summary> public void run() { Message suspect_msg, hb_req; FdHeader hdr; long not_heard_from = 0; // time in msecs we haven't heard from ping_dest if (fd.ping_dest == null) { if (Trace.trace) { Trace.error("FD.Monitor.run()", "ping_dest is null"); } return; } // 1. send heartbeat request hb_req = new Message(fd.ping_dest, null, null); hb_req.putHeader(fd.Name, new FdHeader(FdHeader.HEARTBEAT)); // send heartbeat request if (Trace.trace) { Trace.info("FD.Monitor.run()", "sending are-you-alive msg to " + fd.ping_dest); } fd.passDown(new Event(Event.MSG, hb_req)); // 2. If the time of the last heartbeat is > timeout and max_tries heartbeat messages have not been // received, then broadcast a SUSPECT message. Will be handled by coordinator, which may install // a new view not_heard_from = System.Environment.TickCount - fd.last_ack; if (not_heard_from >= fd.timeout) { // no heartbeat ack for more than timeout msecs if (fd.num_tries >= fd.max_tries) { if (Trace.trace) { Trace.info("FD.Monitor.run()", "[" + fd.local_addr + "]: received no heartbeat ack from " + fd.ping_dest + ", suspecting it"); } hdr = new FdHeader(FdHeader.SUSPECT); hdr.suspected_mbr = fd.ping_dest; hdr.from = fd.local_addr; suspect_msg = new Message(null, null, null); // mcast SUSPECT to all members suspect_msg.putHeader(fd.Name, hdr); fd.passDown(new Event(Event.MSG, suspect_msg)); } else { if (Trace.trace) { Trace.info("FD.Monitor.run()", "heartbeat missing from " + fd.ping_dest + " (number=" + fd.num_tries + ")"); } fd.num_tries++; } } }
/// <summary> /// Sends a Heartbeat to the <i>next</i> member in the group /// </summary> public void run() { Message suspect_msg, hb_req; FdHeader hdr; long not_heard_from=0; // time in msecs we haven't heard from ping_dest if(fd.ping_dest == null) { if(Trace.trace) Trace.error("FD.Monitor.run()", "ping_dest is null"); return; } // 1. send heartbeat request hb_req=new Message(fd.ping_dest, null, null); hb_req.putHeader(fd.Name, new FdHeader(FdHeader.HEARTBEAT)); // send heartbeat request if(Trace.trace) Trace.info("FD.Monitor.run()", "sending are-you-alive msg to " + fd.ping_dest); fd.passDown(new Event(Event.MSG, hb_req)); // 2. If the time of the last heartbeat is > timeout and max_tries heartbeat messages have not been // received, then broadcast a SUSPECT message. Will be handled by coordinator, which may install // a new view not_heard_from=System.Environment.TickCount - fd.last_ack; if(not_heard_from >= fd.timeout) { // no heartbeat ack for more than timeout msecs if(fd.num_tries >= fd.max_tries) { if(Trace.trace) Trace.info("FD.Monitor.run()", "[" + fd.local_addr + "]: received no heartbeat ack from " + fd.ping_dest + ", suspecting it"); hdr=new FdHeader(FdHeader.SUSPECT); hdr.suspected_mbr=fd.ping_dest; hdr.from=fd.local_addr; suspect_msg=new Message(null,null,null); // mcast SUSPECT to all members suspect_msg.putHeader(fd.Name, hdr); fd.passDown(new Event(Event.MSG, suspect_msg)); } else { if(Trace.trace) Trace.info("FD.Monitor.run()", "heartbeat missing from " + fd.ping_dest + " (number=" + fd.num_tries + ")"); fd.num_tries++; } } }
/// <summary> /// Processes <c>Events</c> traveling up the stack /// </summary> /// <param name="evt">The Event to be processed</param> public override void up(Event evt) { Message msg; FdHeader hdr = null; Object sender, tmphdr; switch (evt.Type) { case Event.SET_LOCAL_ADDRESS: local_addr = (Address)evt.Arg; break; case Event.MSG: msg = (Message)evt.Arg; tmphdr = msg.getHeader(getName()); if (tmphdr == null || !(tmphdr is FdHeader)) { if (ping_dest != null && (sender = msg.Source) != null) { if (ping_dest.Equals(sender)) { last_ack = System.Environment.TickCount; if (Trace.trace) { Trace.info("FD.up()", "received msg from " + sender + " (counts as ack)"); } num_tries = 0; } } break; // message did not originate from FD layer, just pass up } hdr = (FdHeader)msg.removeHeader(getName()); switch (hdr.type) { case FdHeader.HEARTBEAT: // heartbeat request; send heartbeat ack Address hb_sender = msg.Source; Message hb_ack = new Message(msg.Source, null, null); FdHeader tmp_hdr = new FdHeader(FdHeader.HEARTBEAT_ACK); // 1. Send an ack tmp_hdr.from = local_addr; hb_ack.putHeader(getName(), tmp_hdr); passDown(new Event(Event.MSG, hb_ack)); // 2. Shun the sender of a HEARTBEAT message if that sender is not a member. This will cause // the sender to leave the group (and possibly rejoin it later) if (shun) { shunInvalidHeartbeatSender(hb_sender); } if (ping_dest == null) // we're being pinged but not pinging anyone { stop(); ping_dest = (Address)getPingDest(members); if (ping_dest != null) { startMonitor(); } } break; // don't pass up ! case FdHeader.HEARTBEAT_ACK: // heartbeat ack if (ping_dest != null && ping_dest.Equals(hdr.from)) { last_ack = System.Environment.TickCount; num_tries = 0; if (Trace.trace) { Trace.info("FD.up()", "received ack from " + hdr.from); } } else { stop(); ping_dest = (Address)getPingDest(members); if (ping_dest != null) { startMonitor(); } } break; case FdHeader.SUSPECT: if (hdr.suspected_mbr != null) { if (Trace.trace) { Trace.info("FD.up()", "[SUSPECT] suspect hdr is " + hdr); } if (local_addr != null && hdr.suspected_mbr != null && hdr.suspected_mbr.Equals(local_addr)) { if (Trace.trace) { Trace.warn("FD.up()", "I was suspected, but will not remove myself from membership " + "(waiting for EXIT message)"); } else { members.Remove(hdr.suspected_mbr); } } ping_dest = (Address)getPingDest(members); passUp(new Event(Event.SUSPECT, hdr.suspected_mbr)); passDown(new Event(Event.SUSPECT, hdr.suspected_mbr)); } break; case FdHeader.NOT_MEMBER: if (shun) { if (Trace.trace) { Trace.info("FD.up()", "[NOT_MEMBER] I'm being shunned; exiting"); } passUp(new Event(Event.EXIT)); } break; } return; } passUp(evt); // pass up to the layer above us }
/// <summary> /// Processes <c>Events</c> traveling up the stack /// </summary> /// <param name="evt">The Event to be processed</param> public override void up(Event evt) { Message msg; FdHeader hdr=null; Object sender, tmphdr; switch(evt.Type) { case Event.SET_LOCAL_ADDRESS: local_addr=(Address)evt.Arg; break; case Event.MSG: msg=(Message)evt.Arg; tmphdr=msg.getHeader(getName()); if(tmphdr == null || !(tmphdr is FdHeader)) { if(ping_dest != null && (sender=msg.Source) != null) { if(ping_dest.Equals(sender)) { last_ack=System.Environment.TickCount; if(Trace.trace) Trace.info("FD.up()", "received msg from " + sender + " (counts as ack)"); num_tries=0; } } break; // message did not originate from FD layer, just pass up } hdr=(FdHeader)msg.removeHeader(getName()); switch(hdr.type) { case FdHeader.HEARTBEAT: // heartbeat request; send heartbeat ack Address hb_sender=msg.Source; Message hb_ack=new Message(msg.Source, null, null); FdHeader tmp_hdr=new FdHeader(FdHeader.HEARTBEAT_ACK); // 1. Send an ack tmp_hdr.from=local_addr; hb_ack.putHeader(getName(), tmp_hdr); passDown(new Event(Event.MSG, hb_ack)); // 2. Shun the sender of a HEARTBEAT message if that sender is not a member. This will cause // the sender to leave the group (and possibly rejoin it later) if(shun) shunInvalidHeartbeatSender(hb_sender); if(ping_dest == null) // we're being pinged but not pinging anyone { stop(); ping_dest=(Address)getPingDest(members); if(ping_dest != null) startMonitor(); } break; // don't pass up ! case FdHeader.HEARTBEAT_ACK: // heartbeat ack if(ping_dest != null && ping_dest.Equals(hdr.from)) { last_ack=System.Environment.TickCount; num_tries=0; if(Trace.trace) Trace.info("FD.up()", "received ack from " + hdr.from); } else { stop(); ping_dest=(Address)getPingDest(members); if(ping_dest != null) startMonitor(); } break; case FdHeader.SUSPECT: if(hdr.suspected_mbr != null) { if(Trace.trace) Trace.info("FD.up()", "[SUSPECT] suspect hdr is " + hdr); if(local_addr != null && hdr.suspected_mbr != null && hdr.suspected_mbr.Equals(local_addr)) if(Trace.trace) Trace.warn("FD.up()", "I was suspected, but will not remove myself from membership " + "(waiting for EXIT message)"); else members.Remove(hdr.suspected_mbr); ping_dest = (Address)getPingDest(members); passUp(new Event(Event.SUSPECT, hdr.suspected_mbr)); passDown(new Event(Event.SUSPECT, hdr.suspected_mbr)); } break; case FdHeader.NOT_MEMBER: if(shun) { if(Trace.trace) Trace.info("FD.up()", "[NOT_MEMBER] I'm being shunned; exiting"); passUp(new Event(Event.EXIT)); } break; } return; } passUp(evt); // pass up to the layer above us }