예제 #1
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
            {
            }
        }