/// <summary> /// Computes the next view, removes old and suspected members, adds new members. /// </summary> /// <param name="new_mbrs">New members to be added to the view</param> /// <param name="old_mbrs">Old members to be removed from the view</param> /// <param name="suspected_mbrs">Suspected members to be removed from the view</param> /// <returns>The new View</returns> public View getNextView(ArrayList new_mbrs, ArrayList old_mbrs, ArrayList suspected_mbrs) { ArrayList mbrs; long vid = 0; View v; Membership tmp_mbrs = null; Address tmp_mbr; lock (members) { if (view_id == null) { return(null); // this should *never* happen ! } vid = Math.Max(view_id.getId(), ltime) + 1; ltime = vid; if (Trace.trace) { Trace.info("GMS.getNextView()", "VID=" + vid + ", current members=" + printMembers(members.getMembers()) + ", new_mbrs=" + printMembers(new_mbrs) + ", old_mbrs=" + printMembers(old_mbrs) + ", suspected_mbrs=" + printMembers(suspected_mbrs)); } tmp_mbrs = tmp_members.copy(); // always operate on the temporary membership tmp_mbrs.remove(suspected_mbrs); tmp_mbrs.remove(old_mbrs); tmp_mbrs.add(new_mbrs); mbrs = (ArrayList)tmp_mbrs.getMembers(); v = new View(local_addr, vid, mbrs); // Update membership tmp_members.set(mbrs); // Update joining list if (new_mbrs != null) { for (int i = 0; i < new_mbrs.Count; i++) { tmp_mbr = (Address)new_mbrs[i]; if (!joining.Contains(tmp_mbr)) { joining.Add(tmp_mbr); } } } if (Trace.trace) { Trace.info("GMS.getNextView()", "new view is " + v); } return(v); } }
/// <summary> /// Sets the new view and sends a VIEW_CHANGE event up and down the stack. /// </summary> /// <param name="new_view">New View to install</param> public void installView(View new_view) { Address coord; int rc; ViewId vid = new_view.getVid(); ArrayList mbrs = new_view.getMembers(); lock (members) { // serialize access to views ltime = Math.Max(vid.getId(), ltime); // compute Lamport logical time /* Check for self-inclusion: if I'm not part of the new membership, I just discard it. * This ensures that messages sent in view V1 are only received by members of V1 */ if (Trace.trace) { Trace.info("GMS.installView()", "View to install contains: " + new_view.ToString()); } if (checkSelfInclusion(mbrs) == false) { if (Trace.trace) { Trace.warn("GMS.installView()", "checkSelfInclusion() failed, not a member of view " + mbrs + "; discarding view"); } if (shun) { if (Trace.trace) { Trace.warn("GMS.installView()", "I'm being shunned, will leave and rejoin group"); } passUp(new Event(Event.EXIT)); } return; } // Discards view with id lower than our own. Will be installed without check if first view if (view_id != null) { rc = vid.CompareTo(view_id); if (rc <= 0) { if (Trace.trace) { Trace.error("GMS.installView()", "received view <= current view;" + " discarding it ! (current vid: " + view_id + ", new vid: " + vid + ")"); } return; } } if (Trace.trace) { Trace.info("GMS.installView()", "view is " + new_view); } // assign new_view to view_id view_id = vid.Copy(); // Set the membership. Take into account joining members if (mbrs != null && mbrs.Count > 0) { members.set(mbrs); tmp_members.set(members); foreach (Object obj in mbrs) { joining.Remove(obj); // remove all members in mbrs from joining } tmp_members.add(joining); // adjust temporary membership } // Send VIEW_CHANGE event up and down the stack: Event view_event = new Event(Event.VIEW_CHANGE, (View)new_view.copy()); passDown(view_event); // needed e.g. by failure detector or UDP passUp(view_event); coord = determineCoordinator(); if (coord != null && coord.Equals(local_addr) && !(coord.Equals(vid.getCoordAddress()))) { becomeCoordinator(); } else { if (haveCoordinatorRole() && !local_addr.Equals(coord)) { becomeParticipant(); } } } }