/// <summary> /// Adds members to the Membership and multicast the new view. /// </summary> /// <param name="mbr">New Member requesting join</param> /// <returns><c>JoinRsp</c> containing new view and digest</returns> public override JoinRsp handleJoin(Address mbr) { lock (this) { ArrayList new_mbrs = new ArrayList(); View v = null; Digest d, tmp; if (Trace.trace) { Trace.info("CoordGmsImpl.handleJoin()", "mbr=" + mbr); } if (gms.local_addr.Equals(mbr)) { if (Trace.trace) { Trace.error("CoordGmsImpl.handleJoin()", "cannot join myself !"); } return(null); } if (gms.members.contains(mbr)) { if (Trace.trace) { Trace.error("CoordGmsImpl.handleJoin()", "member " + mbr + " already present; returning existing view " + gms.members.getMembers()); } return(new JoinRsp(new View(gms.view_id, gms.members.getMembers()), gms.getDigest())); // already joined: return current digest and membership } new_mbrs.Add(mbr); tmp = gms.getDigest(); // get existing digest if (Trace.trace) { Trace.info("CoordGmsImpl.handleJoin()", "got digest=" + tmp); } d = new Digest(tmp.size() + 1); // create a new digest, which contains 1 more member d.add(tmp); // add the existing digest to the new one d.add(mbr, 0, 0); // ... and add the new member. it's first seqno will be 1 v = gms.getNextView(new_mbrs, null, null); if (Trace.trace) { Trace.info("CoordGmsImpl.handleJoin()", "joined member " + mbr + ", view is " + v.getMembers()); } return(new JoinRsp(v, d)); } }
/// <remarks> /// Returns a message digest: for each member P the highest seqno received from P <em>without a gap</em> /// is added to the digest. E.g. if the seqnos received from P are [+3 +4 +5 -6 +7 +8], then 5 will be returned. /// Also, the highest seqno <em>seen</em> is added. The max of all highest seqnos seen will be used (in STABLE) /// to determine whether the last seqno from a sender was received). /// </remarks> /// <summary> /// Returns a message digest. /// </summary> Digest getDigestHighestDeliveredMsgs() { Digest digest; Address sender; Range range; long high_seqno_seen = 0; digest = new Digest(members.Count); for (int i = 0; i < members.Count; i++) { sender = (Address)members[i]; range = getLowestAndHighestSeqno(sender, true); // get the highest deliverable seqno if (range == null) { if (Trace.trace) { Trace.error("NAKACK.getDigest()", "range is null"); } continue; } high_seqno_seen = getHighSeqnoSeen(sender); digest.add(sender, range.low, range.high, high_seqno_seen); // add another entry to the digest } return(digest); }
/// <remarks> /// Called by <c>Join()</c> when no initial members can be detected /// </remarks> /// <summary> /// Changes the GMS to a Coord implementation /// </summary> /// <param name="mbr">Local Address representing this Channel</param> private void becomeSingletonMember(Address mbr) { Digest initial_digest; ViewId view_id = null; ArrayList mbrs = new ArrayList(); // set the initial digest (since I'm the first member) initial_digest = new Digest(1); // 1 member (it's only me) initial_digest.add(gms.local_addr, 0, 0); // initial seqno mcast by me will be 1 (highest seen +1) gms.setDigest(initial_digest); view_id = new ViewId(mbr); // create singleton view with mbr as only member mbrs.Add(mbr); gms.installView(new View(view_id, mbrs)); gms.becomeCoordinator(); gms.passUp(new Event(Event.BECOME_SERVER)); gms.passDown(new Event(Event.BECOME_SERVER)); if (Trace.trace) { Trace.info("ClientGmsImpl.becomeSingletonMember()", "created group (first member). My view is " + gms.view_id + ", impl is " + gms.getImpl().getName()); } }
/// <summary> /// Adds members to the Membership and multicast the new view. /// </summary> /// <param name="mbr">New Member requesting join</param> /// <returns><c>JoinRsp</c> containing new view and digest</returns> public override JoinRsp handleJoin(Address mbr) { lock(this) { ArrayList new_mbrs = new ArrayList(); View v = null; Digest d, tmp; if (Trace.trace) Trace.info("CoordGmsImpl.handleJoin()", "mbr=" + mbr); if (gms.local_addr.Equals(mbr)) { if(Trace.trace) Trace.error("CoordGmsImpl.handleJoin()", "cannot join myself !"); return null; } if (gms.members.contains(mbr)) { if (Trace.trace) Trace.error("CoordGmsImpl.handleJoin()","member "+ mbr+ " already present; returning existing view "+ gms.members.getMembers()); return new JoinRsp(new View(gms.view_id, gms.members.getMembers()),gms.getDigest()); // already joined: return current digest and membership } new_mbrs.Add(mbr); tmp = gms.getDigest(); // get existing digest if (Trace.trace) Trace.info("CoordGmsImpl.handleJoin()", "got digest=" + tmp); d = new Digest(tmp.size() + 1); // create a new digest, which contains 1 more member d.add(tmp); // add the existing digest to the new one d.add(mbr, 0, 0); // ... and add the new member. it's first seqno will be 1 v = gms.getNextView(new_mbrs, null, null); if (Trace.trace) Trace.info("CoordGmsImpl.handleJoin()","joined member " + mbr + ", view is " + v.getMembers()); return new JoinRsp(v, d); } }
public override void up(Event evt) { Console.WriteLine(name.PadRight(5) + " [UP] : " + Event.type2String(evt.Type)); switch (evt.Type) { case (Event.GET_DIGEST): { Thread.Sleep(10000); Digest d = new Digest(1); d.add(localAddr, 0, 0, 0); evt = new Event(Event.GET_DIGEST_OK, d); passDown(evt); break; } case (Event.SET_LOCAL_ADDRESS): { localAddr = (Address)evt.Arg; return; } } }
/// <summary> /// Returns a message digest /// </summary> Digest getDigest() { Digest digest; Address sender; Range range; digest = new Digest(members.Count); for (int i = 0; i < members.Count; i++) { sender = (Address)members[i]; range = getLowestAndHighestSeqno(sender, false); // get the highest received seqno if (range == null) { if (Trace.trace) { Trace.error("NAKACK.getDigest()", "range is null"); } continue; } digest.add(sender, range.low, range.high); // add another entry to the digest } return(digest); }
static void Main(string[] args) { Tester.SetupDebug(); NAKACK nak = new NAKACK(); Protocol bottom = null; Protocol top = Tester.createStack(nak, out bottom); Address remote1 = new Address("1.1.1.1", 8005); Address remote2 = new Address("1.1.1.2", 8005); Address remote3 = new Address("1.1.1.3", 8005); ArrayList members = new ArrayList(); members.Add(Tester.localAddr); members.Add(remote1); members.Add(remote2); members.Add(remote3); View newView = new View(new ViewId(Tester.localAddr, 0), members); evt = new Event(Event.VIEW_CHANGE, newView); top.down(evt); evt = new Event(Event.MSG, new Message(null, null, "Message 1")); top.down(evt); evt = new Event(Event.MSG, new Message(null, null, "Message 2")); top.down(evt); evt = new Event(Event.MSG, new Message(null, null, "Message 3")); top.down(evt); Console.WriteLine("-=-=-=-=- Received Msg 0 from Remote 1 -=-=-=-=-=-"); Message msg = new Message(null, remote1, "Incoming Message 0"); msg.Headers.Add("NAKACK", new NakAckHeader(NakAckHeader.MSG, 0)); evt = new Event(Event.MSG, msg); bottom.up(evt); Console.WriteLine("-=-=-=-=- Received Msg 0 from Remote 2 -=-=-=-=-=-"); msg = new Message(null, remote2, "Incoming Message 0"); msg.Headers.Add("NAKACK", new NakAckHeader(NakAckHeader.MSG, 0)); evt = new Event(Event.MSG, msg); bottom.up(evt); Console.WriteLine("-=-=-=-=- Received Msg 1 from Remote 1 -=-=-=-=-=-"); msg = new Message(null, remote1, "Incoming Message 1"); msg.Headers.Add("NAKACK", new NakAckHeader(NakAckHeader.MSG, 1)); evt = new Event(Event.MSG, msg); bottom.up(evt); Console.WriteLine("-=-=-=-=- Received Msg 2 from Remote 2 -=-=-=-=-=-"); msg = new Message(null, remote2, "Incoming Message 2"); msg.Headers.Add("NAKACK", new NakAckHeader(NakAckHeader.MSG, 2)); evt = new Event(Event.MSG, msg); bottom.up(evt); Thread.Sleep(20000); Console.WriteLine("-=-=-=-=- Received Msg 1 from Remote 2 -=-=-=-=-=-"); msg = new Message(null, remote2, "Incoming Message 1"); msg.Headers.Add("NAKACK", new NakAckHeader(NakAckHeader.MSG, 1)); evt = new Event(Event.MSG, msg); bottom.up(evt); Thread.Sleep(3000); Console.WriteLine("-=-=-=-=- Receiving STABLE event -=-=-=-=-=-"); Digest digest = new Digest(4); // 4 members digest.add(Tester.localAddr, 0, 2, 2); digest.add(remote1, 0, 1, 1); digest.add(remote2, 0, 2, 2); digest.add(remote3, 0, 0, 0); evt = new Event(Event.STABLE, digest); bottom.up(evt); Console.ReadLine(); Tester.stopProtocols(top); Console.ReadLine(); }
/// <remarks> /// Called by <c>Join()</c> when no initial members can be detected /// </remarks> /// <summary> /// Changes the GMS to a Coord implementation /// </summary> /// <param name="mbr">Local Address representing this Channel</param> private void becomeSingletonMember(Address mbr) { Digest initial_digest; ViewId view_id=null; ArrayList mbrs=new ArrayList(); // set the initial digest (since I'm the first member) initial_digest = new Digest(1); // 1 member (it's only me) initial_digest.add(gms.local_addr, 0, 0); // initial seqno mcast by me will be 1 (highest seen +1) gms.setDigest(initial_digest); view_id=new ViewId(mbr); // create singleton view with mbr as only member mbrs.Add(mbr); gms.installView(new View(view_id, mbrs)); gms.becomeCoordinator(); gms.passUp(new Event(Event.BECOME_SERVER)); gms.passDown(new Event(Event.BECOME_SERVER)); if(Trace.trace) Trace.info("ClientGmsImpl.becomeSingletonMember()", "created group (first member). My view is " + gms.view_id + ", impl is " + gms.getImpl().getName()); }
/// <remarks> /// Returns a message digest: for each member P the highest seqno received from P <em>without a gap</em> /// is added to the digest. E.g. if the seqnos received from P are [+3 +4 +5 -6 +7 +8], then 5 will be returned. /// Also, the highest seqno <em>seen</em> is added. The max of all highest seqnos seen will be used (in STABLE) /// to determine whether the last seqno from a sender was received). /// </remarks> /// <summary> /// Returns a message digest. /// </summary> Digest getDigestHighestDeliveredMsgs() { Digest digest; Address sender; Range range; long high_seqno_seen=0; digest=new Digest(members.Count); for(int i=0; i < members.Count; i++) { sender=(Address)members[i]; range=getLowestAndHighestSeqno(sender, true); // get the highest deliverable seqno if(range == null) { if(Trace.trace) Trace.error("NAKACK.getDigest()", "range is null"); continue; } high_seqno_seen=getHighSeqnoSeen(sender); digest.add(sender, range.low, range.high, high_seqno_seen); // add another entry to the digest } return digest; }
/// <summary> /// Returns a message digest /// </summary> Digest getDigest() { Digest digest; Address sender; Range range; digest=new Digest(members.Count); for(int i=0; i < members.Count; i++) { sender=(Address)members[i]; range=getLowestAndHighestSeqno(sender, false); // get the highest received seqno if(range == null) { if(Trace.trace) Trace.error("NAKACK.getDigest()", "range is null"); continue; } digest.add(sender, range.low, range.high); // add another entry to the digest } return digest; }