/// <summary>
        /// Authoritative phase:
        /// 1. the requesting node acquires an election lock up at the config server.
        /// 2. It then proceeds with the election conduction where it asks for votes.
        /// 3. Each node checks their world view once more before voting with a yes or no.
        /// 4. Its mandatory for a consensus amongst all the nodes for an election term to be successful.
        /// 5. One negative vote nullifies the current election term. If such is the case, the entire procedure
        /// needs to be repeated.
        /// </summary>
        /// <param name="reportTable"></param>
        /// <returns></returns>
        private ElectionResult HoldElection(LocalShardHeartbeatReporting reportTable, Activity activity)
        {
            ElectionId electionId = null;

            ServerNode requestingNode = new ServerNode();

            requestingNode.Name     = _context.LocalAddress.IpAddress.ToString();
            requestingNode.Priority = (int)_manager.LocalServerPriority;
            ElectionType type = ElectionType.None;

            if (activity == Activity.GeneralElectionsTriggered)
            {
                type = ElectionType.GeneralElections;
            }
            else if (activity == Activity.TakeoverElectionsTriggered)
            {
                type = ElectionType.TakeoverElections;
            }

            Object response = _context.ConfigurationSession.BeginElection(_context.ClusterName.ToLower(), _context.LocalShardName.ToLower(), requestingNode, type);

            if (response != null)
            {
                electionId = response as ElectionId;
                if (electionId != null)
                {
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsInfoEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Info("ElectionBasedMembershipStrategy", type + " started for node " + _context.LocalAddress);
                    }
                    Address[] activeNodes = reportTable.GetReportTable.Keys.ToArray();

                    return(_manager.ConductElection(electionId, activeNodes, activity));
                }
                else
                {
                    //if we get a database exception from the CS, we wait for a configurable amount of time
                    //before trying to elect a new primary again.
                    if (response is DatabaseException && ((DatabaseException)response).ErrorCode == ErrorCodes.Cluster.PRIMARY_ALREADY_EXISTS)
                    {
                        lock (_mutexOnWait)
                        {
                            Monitor.Wait(_mutexOnWait, _waitTimeout);
                        }
                    }
                }
            }
            if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
            {
                LoggerManager.Instance.ShardLogger.Debug("ElectionBasedMembershipStrategy.HoldElection() ", "Node " + _context.LocalAddress.ToString() + " failed to acquire an election lock on the CS.");
            }
            return(null);
        }
Example #2
0
        public object Clone()
        {
            ElectionId electionId = new ElectionId();

            electionId.Id              = Id;
            electionId.UID             = UID;
            electionId.RequestingNode  = RequestingNode;
            electionId.ElectionTime    = ElectionTime;
            electionId.AllowedDuration = AllowedDuration;
            electionId.TimeTaken       = TimeTaken;

            return(electionId);
        }
Example #3
0
 public Election(ElectionId id, ElectionType electionType)
 {
     ElectionId   = id;
     ElectionType = electionType;
 }