예제 #1
0
        /// <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;
        }
예제 #2
0
        /// <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);
            }
        }
예제 #3
0
		/// <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);
			}
		}
예제 #4
0
		/// <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);
		}
예제 #5
0
파일: GMS.cs 프로젝트: javithalion/NCache
        /// <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
            {
            }
        }