/// <summary> /// Notify the target object of a change of membership. /// </summary> /// <param name="new_view">New view of group</param> void MembershipListener.viewAccepted(View newView) { System.Collections.ArrayList joined_mbrs, left_mbrs, tmp; ArrayList joining_mbrs = new ArrayList(); lock (viewMutex) { object tmp_mbr; if (newView == null) return; NCacheLog.CriticalInfo("ClusterService.ViewAccepted", newView.ToString()); tmp = newView.Members; if (newView.Vid != null) { this._lastViewId = newView.Vid.Id; } // get new members joined_mbrs = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10)); for (int i = 0; i < tmp.Count; i++) { tmp_mbr = tmp[i]; if (!_members.Contains(tmp_mbr)) joined_mbrs.Add(tmp_mbr); } int localIndex = 0; if (joined_mbrs.Contains(LocalAddress)) localIndex = joined_mbrs.IndexOf(LocalAddress); for (int i = localIndex; i < joined_mbrs.Count; i++) { joining_mbrs.Add(joined_mbrs[i]); } // get members that left left_mbrs = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10)); for (int i = 0; i < _members.Count; i++) { tmp_mbr = _members[i]; if (!tmp.Contains(tmp_mbr)) left_mbrs.Add(tmp_mbr); } // adjust our own membership _members.Clear(); _members.AddRange(tmp); //muds: //pick the map from the view and send it to cache. //if i am the only member, i can build the map locally. if (newView.DistributionMaps == null && newView.Members.Count == 1) { if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ClusterService.viewAccepted()", "I am the only member in the view so, building map myself"); PartNodeInfo affectedNode = new PartNodeInfo(LocalAddress, _subgroupid, true); DistributionInfoData info = new DistributionInfoData(DistributionMode.OptimalWeight, ClusterActivity.NodeJoin, affectedNode); DistributionMaps maps = _distributionPolicyMbr.GetDistributionMaps(info); if (maps != null) { _distributionPolicyMbr.HashMap = maps.Hashmap; _distributionPolicyMbr.BucketsOwnershipMap = maps.BucketsOwnershipMap; } } else { if (newView.MirrorMapping != null) { _distributionPolicyMbr.InstallMirrorMap(newView.MirrorMapping); NCacheLog.Info("ClusterService.viewAccepted()", "New MirrorMap installed."); } if (newView.DistributionMaps != null) { _distributionPolicyMbr.InstallHashMap(newView.DistributionMaps, left_mbrs); if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ClusterService.viewAccepted()", "New hashmap installed"); } } lock (_servers.SyncRoot) { if (left_mbrs.Count > 0) { for (int i = left_mbrs.Count - 1; i >= 0; i--) { Address ipAddr = (Address)((Address)left_mbrs[i]); if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ClusterService.viewAccepted", ipAddr.AdditionalData.Length.ToString()); ipAddr = (Address)ipAddr.Clone(); if (_servers.Contains(ipAddr)) _servers.Remove(ipAddr); OnMemberLeft(ipAddr, CompactBinaryFormatter.FromByteBuffer(ipAddr.AdditionalData, _context.SerializationContext) as NodeIdentity); ipAddr.AdditionalData = null; } } _validMembers = (ArrayList)_members.Clone(); if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ClusterService.viewAccepted", joining_mbrs.Count.ToString()); if (joined_mbrs.Count > 0) { for (int i = 0; i < joined_mbrs.Count; i++) { Address ipAddr = (Address)joined_mbrs[i]; if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ClusterService.viewAccepted", ipAddr.AdditionalData.Length.ToString()); ipAddr = (Address)ipAddr.Clone(); if (OnMemberJoined(ipAddr, CompactBinaryFormatter.FromByteBuffer(ipAddr.AdditionalData, _context.SerializationContext) as NodeIdentity, joining_mbrs)) { if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ClusterServices.ViewAccepted", ipAddr.ToString() + " is added to _servers list."); _servers.Add(ipAddr); } ipAddr.AdditionalData = null; } } } if (String.IsNullOrEmpty(_bridgeSourceCacheId)) _bridgeSourceCacheId = newView.BridgeSourceCacheId; OnAfterMembershipChange(); } }
/// <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 { } }