/// <summary> Merge all MergeData. All MergeData elements should be disjunct (both views and digests). However, /// this method is prepared to resolve duplicate entries (for the same member). Resolution strategy for /// views is to merge only 1 of the duplicate members. Resolution strategy for digests is to take the higher /// seqnos for duplicate digests.<p> /// After merging all members into a Membership and subsequent sorting, the first member of the sorted membership /// will be the new coordinator. /// </summary> /// <param name="v">A list of MergeData items. Elements with merge_rejected=true were removed before. Is guaranteed /// not to be null and to contain at least 1 member. /// </param> internal virtual MergeData consolidateMergeData(System.Collections.ArrayList v) { MergeData ret = null; MergeData tmp_data; long logical_time = 0; // for new_vid ViewId new_vid, tmp_vid; MergeView new_view; View tmp_view; Membership new_mbrs = new Membership(); int num_mbrs = 0; Digest new_digest = null; Address new_coord; System.Collections.ArrayList subgroups = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(11)); // contains a list of Views, each View is a subgroup for (int i = 0; i < v.Count; i++) { tmp_data = (MergeData)v[i]; gms.Stack.NCacheLog.Debug("merge data is " + tmp_data); tmp_view = tmp_data.View; if (tmp_view != null) { tmp_vid = tmp_view.Vid; if (tmp_vid != null) { // compute the new view id (max of all vids +1) logical_time = System.Math.Max(logical_time, tmp_vid.Id); } } // merge all membership lists into one (prevent duplicates) new_mbrs.add(tmp_view.Members); subgroups.Add(tmp_view.Clone()); } // the new coordinator is the first member of the consolidated & sorted membership list new_mbrs.sort(); num_mbrs = new_mbrs.size(); new_coord = num_mbrs > 0 ? (Address)new_mbrs.elementAt(0) : null; if (new_coord == null) { gms.Stack.NCacheLog.Error("CoordGmsImpl.consolodateMergeData", "new_coord is null."); return null; } // should be the highest view ID seen up to now plus 1 new_vid = new ViewId(new_coord, logical_time + 1); // determine the new view new_view = new MergeView(new_vid, new_mbrs.Members, subgroups); gms.Stack.NCacheLog.Debug("new merged view will be " + new_view); // determine the new digest new_digest = consolidateDigests(v, num_mbrs); if (new_digest == null) { gms.Stack.NCacheLog.Error("CoordGmsImpl.consolidateMergeData", "digest could not be consolidated."); return null; } gms.Stack.NCacheLog.Debug("consolidated digest=" + new_digest); ret = new MergeData(gms.local_addr, new_view, new_digest); return ret; }
/// <summary> Invoked upon receiving a MERGE event from the MERGE layer. Starts the merge protocol. /// See description of protocol in DESIGN. /// </summary> /// <param name="other_coords">A list of coordinators (including myself) found by MERGE protocol /// </param> public override void merge(System.Collections.ArrayList other_coords) { Membership tmp; Address leader = null; if (merging) { gms.Stack.NCacheLog.Warn("CoordGmsImpl.merge", "merge already in progress, discarded MERGE event"); return; } if (other_coords == null) { gms.Stack.NCacheLog.Warn("CoordGmsImpl.merge", "list of other coordinators is null. Will not start merge."); return; } if (other_coords.Count <= 1) { gms.Stack.NCacheLog.Error("CoordGmsImpl.merge", "number of coordinators found is " + other_coords.Count + "; will not perform merge"); return; } /* Establish deterministic order, so that coords can elect leader */ tmp = new Membership(other_coords); tmp.sort(); leader = (Address)tmp.elementAt(0); gms.Stack.NCacheLog.Debug("coordinators in merge protocol are: " + tmp); if (leader.Equals(gms.local_addr)) { gms.Stack.NCacheLog.Debug("I (" + leader + ") will be the leader. Starting the merge task"); startMergeTask(other_coords); } }
/// <summary> /// Sets the membership to the specified membership /// </summary> /// <param name="m">New membership</param> public void set(Membership m) { clear(); if (m != null) { add(m.Members); } }
/// <summary> /// Clones the membership /// </summary> /// <returns>A clone of the membership</returns> public Object Clone() { Membership m; m = new Membership(); m.setMembers((ArrayList)members.Clone()); return(m); }
/// <summary> Sets the new view and sends a VIEW_CHANGE event up and down the stack.</summary> public virtual void installView(View new_view) { Stack.NCacheLog.CriticalInfo("GMS.InstallView", "Installing new View " + local_addr.ToString() + " --> " + new_view); Address coord = null; try { //Lest inform coordinator about view receiption SendViewAcknowledgment(new_view.Coordinator); int rc; ViewId vid = new_view.Vid; System.Collections.ArrayList mbrs = new_view.Members; impl.UniqueId = new_view.BridgeSourceCacheId; _uniqueID = new_view.BridgeSourceCacheId; if (Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("[local_addr=" + local_addr + "] view is " + new_view); // 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) { Stack.NCacheLog.Error("[" + local_addr + "] received view <= current view;" + " discarding it (current vid: " + view_id + ", new vid: " + vid + ')'); Event viewEvt = new Event(Event.VIEW_CHANGE_OK, null, Priority.Critical); passDown(viewEvt); return; } Address currentCoodinator = determineCoordinator(); Address newCoordinator = new_view.Coordinator; Address sender = vid.CoordAddress; // creater of the view if (!currentCoodinator.Equals(newCoordinator) && !newCoordinator.Equals(local_addr) && !sender.Equals(currentCoodinator)) { Stack.NCacheLog.CriticalInfo("GMS.InstallView", "Force Join Cluster"); if (!new_view.ForceInstall) { if (!VerifySuspect(currentCoodinator)) { Stack.NCacheLog.Error("GMS.installView", "rejecting the view from " + newCoordinator + " as my own coordinator[" + currentCoodinator + "] is not down"); Event viewEvt = new Event(Event.VIEW_CHANGE_OK, null, Priority.Critical); passDown(viewEvt); //we should inform the coordinator of this view that i can't be the member //of your view as my own coordinator is alive. Message msg = new Message(new_view.Coordinator, null, new byte[0]); msg.putHeader(HeaderType.GMS, new GMS.HDR(GMS.HDR.VIEW_REJECTED, local_addr)); passDown(new Event(Event.MSG, msg, Priority.Critical)); return; } } } } ltime = System.Math.Max(vid.Id, 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 (checkSelfInclusion(mbrs) == false) { Stack.NCacheLog.Error("GMS.InstallView", "CheckSelfInclusion() failed, " + local_addr + " is not a member of view " + new_view + "; discarding view"); // only shun if this member was previously part of the group. avoids problem where multiple // members (e.g. X,Y,Z) join {A,B} concurrently, X is joined first, and Y and Z get view // {A,B,X}, which would cause Y and Z to be shunned as they are not part of the membership // bela Nov 20 2003 if (shun && local_addr != null && prev_members.contains(local_addr)) { Stack.NCacheLog.CriticalInfo("I (" + local_addr + ") am being shunned, will leave and " + "rejoin group (prev_members are " + prev_members + ')'); passUp(new Event(Event.EXIT)); } return; } lock (members) { //@UH Members are same as in the previous view. No need to apply view if (view_id != null) { Membership newMembers = new Membership(mbrs); if (members.Equals(newMembers) && vid.CoordAddress.Equals(view_id.CoordAddress)) { Stack.NCacheLog.Error("GMS.InstallView", "[" + local_addr + "] received view has the same members as current view;" + " discarding it (current vid: " + view_id + ", new vid: " + vid + ')'); Event viewEvt = new Event(Event.VIEW_CHANGE_OK, null, Priority.Critical); //#usama@15-4-2013 joining, leaving and tmp_members are needed to be synchronized even if view is same Global.ICollectionSupport.RemoveAll(joining, mbrs); // remove all members in mbrs from joining // remove all elements from 'leaving' that are not in 'mbrs' Global.ICollectionSupport.RetainAll(leaving, mbrs); tmp_members.add(joining); // add members that haven't yet shown up in the membership tmp_members.remove(leaving); // remove members that haven't yet been removed from the membership passDown(viewEvt); return; } } //========================================= // Stack.NCacheLog.CriticalInfo("GMS.InstallView", "Installing view in gms"); if (Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("GMS.InstallView " + new_view.ToString() + "\\n" + "seq tble : " + new_view.SequencerTbl.Count); this._subGroupMbrsMap = new_view.SequencerTbl.Clone() as System.Collections.Hashtable; this._mbrSubGroupMap = new_view.MbrsSubgroupMap.Clone() as System.Collections.Hashtable; //========================================= // serialize access to views // assign new_view to view_id view_id = vid.Copy(); Stack.NCacheLog.CriticalInfo("GMS.InstallView", "=== View ID = " + view_id.ToString()); // Set the membership. Take into account joining members if (mbrs != null && mbrs.Count > 0) { for (int i = 0; i < members.size(); i++) { Address mbr = members.elementAt(i); if (!mbrs.Contains(mbr)) RemoveGmsId(mbr); } Hashtable gmsIds = new_view.GmsIds; if (gmsIds != null) { IDictionaryEnumerator ide = gmsIds.GetEnumerator(); while (ide.MoveNext()) { if(Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("GMS.InstallView", "mbr = " + ide.Key + " ; gms_id = " + ide.Value); AddGmsId((Address)ide.Key, (string)ide.Value); } } for (int i = 0; i < mbrs.Count; i++) { Stack.NCacheLog.CriticalInfo("GMS.InstallView", "Members.set = " + mbrs[i] != null ? mbrs[i].ToString() : null); } members.set(mbrs); tmp_members.set(members); Global.ICollectionSupport.RemoveAll(joining, mbrs); // remove all members in mbrs from joining // remove all elements from 'leaving' that are not in 'mbrs' Global.ICollectionSupport.RetainAll(leaving, mbrs); tmp_members.add(joining); // add members that haven't yet shown up in the membership tmp_members.remove(leaving); // remove members that haven't yet been removed from the membership // add to prev_members for (System.Collections.IEnumerator it = mbrs.GetEnumerator(); it.MoveNext(); ) { Address addr = (Address)it.Current; if (!prev_members.contains(addr)) prev_members.add(addr); } } // Send VIEW_CHANGE event up and down the stack: if (Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("GMS.installView", "broadcasting view change within stack"); coord = determineCoordinator(); // changed on suggestion by yaronr and Nicolas Piedeloupe if (coord != null && coord.Equals(local_addr) && !haveCoordinatorRole()) { becomeCoordinator(); } else { if (haveCoordinatorRole() && !local_addr.Equals(coord)) becomeParticipant(); } if (string.IsNullOrEmpty(new_view.BridgeSourceCacheId)) new_view.BridgeSourceCacheId = impl.UniqueId; MarkStateTransferInProcess(); Event view_event = new Event(Event.VIEW_CHANGE, new_view.Clone(), Priority.Critical); passDown(view_event); // needed e.g. by failure detector or UDP } } finally { } }