public object OnMessageReceived(object message, Server source, LocalShardHeartbeatReporting heartbeatReport, Membership existingMembership)
        {
            Election election = message as Election;

            if (election != null)
            {
                HeartbeatInfo localHeartbeat = heartbeatReport.GetHeartbeatInfo(_context.LocalAddress);
                if (localHeartbeat != null)
                {
                    return(_manager.CastVote(election, existingMembership, localHeartbeat));
                }
            }
            return(null);
        }
        /// <summary>
        /// Speculative Phase:
        /// 1. We search for the node with the latest op-log entry. This detail bears the highest value.
        /// 2. Next, if multiple nodes have the same op-log entry, we move onto the next step.
        /// 3. All those nodes which have the same op-log entry AND are connected to the CS are considered.
        /// 4. Highest priority from amongst these active nodes are taken into consideration.
        /// 5. If this node fulfills all of the above, it successfully passes the speculative phase.
        /// </summary>
        /// <param name="heartbeatReport"></param>
        /// <returns></returns>

        private bool ShouldIInitiateElection(LocalShardHeartbeatReporting heartbeatReport, Activity activity)
        {
            IList <Address> activeNodes = null;

            if (heartbeatReport != null)
            {
                activeNodes = heartbeatReport.GetReportTable.Keys.ToList();
                OperationId    maxOplog = null;
                IList <string> matchingOplogServerIPs = new List <string>();

                HeartbeatInfo localHeartbeat = heartbeatReport.GetHeartbeatInfo(_context.LocalAddress);
                if (localHeartbeat == null)
                {
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsWarnEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Warn(
                            "ElectionBasedMembershipStrategy.ShouldIInititateElections()",
                            "local node heartbeat is null");
                    }
                    return(false);
                }

                OperationId lastRepId = null;


                if (activity.Equals(Activity.TakeoverElectionsTriggered))
                {
                    HeartbeatInfo info = null;
                    if (_shard != null && _shard.Primary != null)
                    {
                        info = heartbeatReport.GetHeartbeatInfo(_shard.Primary.Address);
                    }
                }

                else
                {
                    ShardConfiguration sConfig       = _clusterConfigMgr.GetShardConfiguration(_context.LocalShardName);
                    int         configuredNodesCount = 0;
                    OperationId OpIdAtCS             = null;
                    if (sConfig != null && sConfig.Servers != null && sConfig.Servers.Nodes != null)
                    {
                        configuredNodesCount = sConfig.Servers.Nodes.Count;
                    }
                    if (configuredNodesCount > 0 && activeNodes != null && activeNodes.Count < configuredNodesCount)
                    {
                        ShardInfo   sInfo = null;
                        ClusterInfo cInfo = _context.ConfigurationSession.GetDatabaseClusterInfo(_context.ClusterName);
                        if (cInfo != null)
                        {
                            sInfo = cInfo.GetShardInfo(_context.LocalShardName);
                        }
                        if (sInfo != null)
                        {
                            OpIdAtCS = sInfo.LastOperationId;
                        }
                        if (OpIdAtCS > lastRepId)
                        {
                            if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsInfoEnabled)
                            {
                                LoggerManager.Instance.ShardLogger.Info(
                                    "electBasedMemSt.ShouldIInitElections()",
                                    "CS has an operation newer than my operation. Hence, waiting.");
                            }

                            if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsInfoEnabled)
                            {
                                if (OpIdAtCS != null)
                                {
                                    LoggerManager.Instance.ShardLogger.Info(
                                        "electBasedMemSt.ShouldIInitElections()",
                                        "Operation ID on the CS:- " + OpIdAtCS.ElectionId + ":"
                                        + OpIdAtCS.ElectionBasedSequenceId);
                                }
                                else
                                {
                                    LoggerManager.Instance.ShardLogger.Info(
                                        "electBasedMemSt.ShouldIInitElections()", "The operation ID at the CS is set to null.");
                                }
                                if (lastRepId != null)
                                {
                                    LoggerManager.Instance.ShardLogger.Info(
                                        "electBasedMemSt.ShouldIInitElections()", "Local node Operation ID:- " + lastRepId.ElectionId +
                                        ":" + lastRepId.ElectionBasedSequenceId);
                                }
                                else
                                {
                                    LoggerManager.Instance.ShardLogger.Info(
                                        "electBasedMemSt.ShouldIInitElections()", "The local node operation ID is set to null.");
                                }
                            }
                            //We maintain the last replicated operation log entry with the CS.
                            //If a node in a shard with older data (usually the previous secondary) is up before the node with the
                            //latest data(usually the previous primary), it waits for a configurable amount of time (2 minutes for
                            //now) before proceeding with the election procedure if it is still unable to detect a primary node.
                            //This way we give the node with the latest data a chance to become primary and therefore avoid data loss.
                            lock (_mutexOnWait)
                            {
                                Monitor.Wait(_mutexOnWait, _waitTimeout);
                            }
                        }
                    }

                    for (int i = 0; i < activeNodes.Count; i++)
                    {
                        HeartbeatInfo info           = heartbeatReport.GetHeartbeatInfo(activeNodes[i]);
                        OperationId   currIndexOplog = info.LastOplogOperationId;
                        if (currIndexOplog > maxOplog)
                        {
                            maxOplog = currIndexOplog;
                        }

                        if (((localHeartbeat.LastOplogOperationId == null && info.LastOplogOperationId == null) || localHeartbeat.LastOplogOperationId != null && localHeartbeat.LastOplogOperationId.Equals(info.LastOplogOperationId)) &&
                            info.CSStatus == ConnectivityStatus.Connected)
                        {
                            matchingOplogServerIPs.Add(activeNodes[i].IpAddress.ToString());
                        }
                    }
                }

                if (localHeartbeat.LastOplogOperationId != null && maxOplog != null && maxOplog > localHeartbeat.LastOplogOperationId && (lastRepId == null || maxOplog > lastRepId))
                {
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "Local operation log is behind max op log wrt " + _context.LocalShardName + " shard.");
                    }
                    if (maxOplog != null && LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "maxOplog: " + maxOplog.ElectionId + ":" + maxOplog.ElectionBasedSequenceId);
                    }
                    if (localHeartbeat.LastOplogOperationId != null && LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "local opLog (from the heartbeat): " + localHeartbeat.LastOplogOperationId.ElectionId + ":" + localHeartbeat.LastOplogOperationId.ElectionBasedSequenceId);
                    }
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled && lastRepId != null)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "LastOpFromOpLog (from the replication module): " + lastRepId.ElectionId + ":" + lastRepId.ElectionBasedSequenceId);
                    }

                    return(false);
                }
                else if (maxOplog == localHeartbeat.LastOplogOperationId || (lastRepId != null && lastRepId.Equals(maxOplog)))
                {
                    //if: there are multiple nodes that have the same oplog entry,
                    //decision will be made on the basis of the priorities.
                    //else: the node with the highest oplog entry will be considered eligible.
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "Local operation log is equal to the max op log wrt " + _context.LocalShardName + " shard.");
                    }
                    if (maxOplog != null && (localHeartbeat != null && localHeartbeat.LastOplogOperationId != null))
                    {
                        if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                        {
                            LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "maxOplog: " + maxOplog.ElectionId + ":" + maxOplog.ElectionBasedSequenceId);
                        }
                        if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                        {
                            LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "local opLog (from the heartbeat): " + localHeartbeat.LastOplogOperationId.ElectionId + ":" + localHeartbeat.LastOplogOperationId.ElectionBasedSequenceId);
                        }
                        if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled && lastRepId != null)
                        {
                            LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "LastOpFromOpLog (from the replication module): " + lastRepId.ElectionId + ":" + lastRepId.ElectionBasedSequenceId);
                        }
                    }
                    if (matchingOplogServerIPs.Count > 0)
                    {
                        int highestRunningNodePriority = _manager.GetHighestNodePriority(activeNodes,
                                                                                         matchingOplogServerIPs);

                        if (highestRunningNodePriority.Equals(_manager.LocalServerPriority))
                        {
                            if (LoggerManager.Instance.ShardLogger != null &&
                                LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                            {
                                LoggerManager.Instance.ShardLogger.Debug(
                                    "ElectionBasedMembershipStrategy.ShouldIInitiateElection()",
                                    "Node : " + _context.LocalAddress.IpAddress.ToString() + " in shard: " +
                                    _context.LocalShardName + " is eligible having priority: " +
                                    highestRunningNodePriority + " .");
                            }
                            return(true);
                        }
                        else
                        {
                            return(false);
                        }
                    }
                }
            }
            return(false);
        }