private ClusterDescription ProcessReplicaSetChange(ClusterDescription clusterDescription, ServerDescriptionChangedEventArgs args)
        {
            if (!args.NewServerDescription.Type.IsReplicaSetMember())
            {
                return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server is a {0}, not a replica set member.", args.NewServerDescription.Type)));
            }

            if (args.NewServerDescription.Type == ServerType.ReplicaSetGhost)
            {
                return(clusterDescription.WithServerDescription(args.NewServerDescription));
            }

            if (_replicaSetName == null)
            {
                _replicaSetName = args.NewServerDescription.ReplicaSetConfig.Name;
            }

            if (_replicaSetName != args.NewServerDescription.ReplicaSetConfig.Name)
            {
                return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server was a member of the '{0}' replica set, but should be '{1}'.", args.NewServerDescription.ReplicaSetConfig.Name, _replicaSetName)));
            }

            clusterDescription = clusterDescription.WithServerDescription(args.NewServerDescription);
            clusterDescription = EnsureServers(clusterDescription, args.NewServerDescription);

            if (args.NewServerDescription.Type == ServerType.ReplicaSetPrimary &&
                args.OldServerDescription.Type != ServerType.ReplicaSetPrimary)
            {
                var currentPrimaryEndPoints = clusterDescription.Servers
                                              .Where(x => x.Type == ServerType.ReplicaSetPrimary)
                                              .Where(x => !EndPointHelper.Equals(x.EndPoint, args.NewServerDescription.EndPoint))
                                              .Select(x => x.EndPoint)
                                              .ToList();

                if (currentPrimaryEndPoints.Count > 0)
                {
                    lock (_serversLock)
                    {
                        var currentPrimaries = _servers.Where(x => EndPointHelper.Contains(currentPrimaryEndPoints, x.EndPoint));
                        foreach (var currentPrimary in currentPrimaries)
                        {
                            // kick off the server to invalidate itself
                            currentPrimary.Invalidate();
                            // set it to disconnected in the cluster
                            clusterDescription = clusterDescription.WithServerDescription(
                                new ServerDescription(currentPrimary.ServerId, currentPrimary.EndPoint));
                        }
                    }
                }
            }

            return(clusterDescription);
        }
        private void OnClusterDescriptionChanged(object sender, EventArgs args)
        {
            var clusterDescription = _cluster.Description;
            var endPoints          = clusterDescription.Servers.Select(s => s.EndPoint).ToList();

            lock (_serverLock)
            {
                _serverInstances.RemoveAll(instance => !EndPointHelper.Contains(endPoints, instance.EndPoint));
                var newEndPoints = endPoints.Where(endPoint => !_serverInstances.Any(i => i.EndPoint.Equals(endPoint))).ToList();
                if (newEndPoints.Count > 0)
                {
                    _serverInstances.AddRange(newEndPoints.Select(endPoint => new MongoServerInstance(_settings, ToMongoServerAddress(endPoint), _cluster, endPoint)));
                    _serverInstances.Sort(ServerInstanceAddressComparer.Instance);
                }
            }
        }
Exemple #3
0
        private ClusterDescription EnsureServers(ClusterDescription clusterDescription, ServerDescription serverDescription, List <IClusterableServer> newServers)
        {
            if (serverDescription.Type == ServerType.ReplicaSetPrimary ||
                !clusterDescription.Servers.Any(x => x.Type == ServerType.ReplicaSetPrimary))
            {
                foreach (var endPoint in serverDescription.ReplicaSetConfig.Members)
                {
                    clusterDescription = EnsureServer(clusterDescription, endPoint, newServers);
                }
            }

            if (serverDescription.Type == ServerType.ReplicaSetPrimary)
            {
                var requiredEndPoints = serverDescription.ReplicaSetConfig.Members;
                var extraEndPoints    = clusterDescription.Servers.Where(x => !EndPointHelper.Contains(requiredEndPoints, x.EndPoint)).Select(x => x.EndPoint);
                foreach (var endPoint in extraEndPoints)
                {
                    clusterDescription = RemoveServer(clusterDescription, endPoint, "Server is not in the host list of the primary.");
                }
            }

            return(clusterDescription);
        }
Exemple #4
0
        private ClusterDescription ProcessReplicaSetChange(ClusterDescription clusterDescription, ServerDescriptionChangedEventArgs args, List <IClusterableServer> newServers)
        {
            if (!args.NewServerDescription.Type.IsReplicaSetMember())
            {
                return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server is a {0}, not a replica set member.", args.NewServerDescription.Type)));
            }

            if (args.NewServerDescription.Type == ServerType.ReplicaSetGhost)
            {
                return(clusterDescription.WithServerDescription(args.NewServerDescription));
            }

            if (_replicaSetName == null)
            {
                _replicaSetName = args.NewServerDescription.ReplicaSetConfig.Name;
            }

            if (_replicaSetName != args.NewServerDescription.ReplicaSetConfig.Name)
            {
                return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server was a member of the '{0}' replica set, but should be '{1}'.", args.NewServerDescription.ReplicaSetConfig.Name, _replicaSetName)));
            }

            clusterDescription = clusterDescription.WithServerDescription(args.NewServerDescription);
            clusterDescription = EnsureServers(clusterDescription, args.NewServerDescription, newServers);

            if (args.NewServerDescription.CanonicalEndPoint != null &&
                !EndPointHelper.Equals(args.NewServerDescription.CanonicalEndPoint, args.NewServerDescription.EndPoint))
            {
                return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, "CanonicalEndPoint is different than seed list EndPoint."));
            }

            if (args.NewServerDescription.Type == ServerType.ReplicaSetPrimary)
            {
                if (args.NewServerDescription.ReplicaSetConfig.Version != null)
                {
                    bool isCurrentPrimaryStale = true;
                    if (_maxElectionInfo != null)
                    {
                        isCurrentPrimaryStale = _maxElectionInfo.IsStale(args.NewServerDescription.ReplicaSetConfig.Version.Value, args.NewServerDescription.ElectionId);
                        var isReportedPrimaryStale = _maxElectionInfo.IsFresher(
                            args.NewServerDescription.ReplicaSetConfig.Version.Value,
                            args.NewServerDescription.ElectionId);


                        if (isReportedPrimaryStale && args.NewServerDescription.ElectionId != null)
                        {
                            // we only invalidate the "newly" reported stale primary if electionId was used.
                            lock (_serversLock)
                            {
                                var server = _servers.SingleOrDefault(x => EndPointHelper.Equals(args.NewServerDescription.EndPoint, x.EndPoint));
                                server.Invalidate();

                                _sdamInformationEventHandler?.Invoke(new SdamInformationEvent(() =>
                                                                                              string.Format(
                                                                                                  @"Invalidating server: Setting ServerType to ""Unknown"" for {0} because it " +
                                                                                                  @"claimed to be the replica set primary for replica set ""{1}"" but sent a " +
                                                                                                  @"(setVersion, electionId) tuple of ({2}, {3}) that was less than than the " +
                                                                                                  @"largest tuple seen, (maxSetVersion, maxElectionId), of ({4}, {5}).",
                                                                                                  args.NewServerDescription.EndPoint,
                                                                                                  args.NewServerDescription.ReplicaSetConfig.Name,
                                                                                                  args.NewServerDescription.ReplicaSetConfig.Version,
                                                                                                  args.NewServerDescription.ElectionId,
                                                                                                  _maxElectionInfo.SetVersion,
                                                                                                  _maxElectionInfo.ElectionId)));

                                return(clusterDescription.WithServerDescription(
                                           new ServerDescription(server.ServerId, server.EndPoint)));
                            }
                        }
                    }

                    if (isCurrentPrimaryStale)
                    {
                        if (_maxElectionInfo == null)
                        {
                            _sdamInformationEventHandler?.Invoke(new SdamInformationEvent(() =>
                                                                                          string.Format(
                                                                                              @"Initializing (maxSetVersion, maxElectionId): Saving tuple " +
                                                                                              @"(setVersion, electionId) of ({0}, {1}) as (maxSetVersion, maxElectionId) for " +
                                                                                              @"replica set ""{2}"" because replica set primary {3} sent ({0}, {1}), the first " +
                                                                                              @"(setVersion, electionId) tuple ever seen for replica set ""{4}"".",
                                                                                              args.NewServerDescription.ReplicaSetConfig.Version,
                                                                                              args.NewServerDescription.ElectionId,
                                                                                              args.NewServerDescription.ReplicaSetConfig.Name,
                                                                                              args.NewServerDescription.EndPoint,
                                                                                              args.NewServerDescription.ReplicaSetConfig.Name)));
                        }
                        else
                        {
                            if (_maxElectionInfo.SetVersion < args.NewServerDescription.ReplicaSetConfig.Version.Value)
                            {
                                _sdamInformationEventHandler?.Invoke(new SdamInformationEvent(() =>
                                                                                              string.Format(
                                                                                                  @"Updating stale setVersion: Updating the current " +
                                                                                                  @"(maxSetVersion, maxElectionId) tuple from ({0}, {1}) to ({2}, {3}) for " +
                                                                                                  @"replica set ""{4}"" because replica set primary {5} sent ({6}, {7})—a larger " +
                                                                                                  @"(setVersion, electionId) tuple then the saved tuple, ({0}, {1}).",
                                                                                                  _maxElectionInfo.SetVersion,
                                                                                                  _maxElectionInfo.ElectionId,
                                                                                                  args.NewServerDescription.ReplicaSetConfig.Version,
                                                                                                  args.NewServerDescription.ElectionId,
                                                                                                  args.NewServerDescription.ReplicaSetConfig.Name,
                                                                                                  args.NewServerDescription.EndPoint,
                                                                                                  args.NewServerDescription.ReplicaSetConfig.Version,
                                                                                                  args.NewServerDescription.ElectionId)));
                            }
                            else // current primary is stale & setVersion is not stale ⇒ the electionId must be stale
                            {
                                _sdamInformationEventHandler?.Invoke(new SdamInformationEvent(() =>
                                                                                              string.Format(
                                                                                                  @"Updating stale electionId: Updating the current " +
                                                                                                  @"(maxSetVersion, maxElectionId) tuple from ({0}, {1}) to ({2}, {3}) for " +
                                                                                                  @"replica set ""{4}"" because replica set primary {5} sent ({6}, {7})—" +
                                                                                                  @"a larger (setVersion, electionId) tuple than the saved tuple, ({0}, {1}).",
                                                                                                  _maxElectionInfo.SetVersion,
                                                                                                  _maxElectionInfo.ElectionId,
                                                                                                  args.NewServerDescription.ReplicaSetConfig.Version,
                                                                                                  args.NewServerDescription.ElectionId,
                                                                                                  args.NewServerDescription.ReplicaSetConfig.Name,
                                                                                                  args.NewServerDescription.EndPoint,
                                                                                                  args.NewServerDescription.ReplicaSetConfig.Version,
                                                                                                  args.NewServerDescription.ElectionId)));
                            }
                        }

                        _maxElectionInfo = new ElectionInfo(
                            args.NewServerDescription.ReplicaSetConfig.Version.Value,
                            args.NewServerDescription.ElectionId);
                    }
                }

                var currentPrimaryEndPoints = clusterDescription.Servers
                                              .Where(x => x.Type == ServerType.ReplicaSetPrimary)
                                              .Where(x => !EndPointHelper.Equals(x.EndPoint, args.NewServerDescription.EndPoint))
                                              .Select(x => x.EndPoint)
                                              .ToList();

                if (currentPrimaryEndPoints.Count > 0)
                {
                    lock (_serversLock)
                    {
                        var currentPrimaries = _servers.Where(x => EndPointHelper.Contains(currentPrimaryEndPoints, x.EndPoint));
                        foreach (var currentPrimary in currentPrimaries)
                        {
                            // kick off the server to invalidate itself
                            currentPrimary.Invalidate();
                            // set it to disconnected in the cluster
                            clusterDescription = clusterDescription.WithServerDescription(
                                new ServerDescription(currentPrimary.ServerId, currentPrimary.EndPoint));
                        }
                    }
                }
            }

            return(clusterDescription);
        }
Exemple #5
0
        private ClusterDescription ProcessReplicaSetChange(ClusterDescription clusterDescription, ServerDescriptionChangedEventArgs args, List <IClusterableServer> newServers)
        {
            if (!args.NewServerDescription.Type.IsReplicaSetMember())
            {
                return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server is a {0}, not a replica set member.", args.NewServerDescription.Type)));
            }

            if (args.NewServerDescription.Type == ServerType.ReplicaSetGhost)
            {
                return(clusterDescription.WithServerDescription(args.NewServerDescription));
            }

            if (_replicaSetName == null)
            {
                _replicaSetName = args.NewServerDescription.ReplicaSetConfig.Name;
            }

            if (_replicaSetName != args.NewServerDescription.ReplicaSetConfig.Name)
            {
                return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server was a member of the '{0}' replica set, but should be '{1}'.", args.NewServerDescription.ReplicaSetConfig.Name, _replicaSetName)));
            }

            clusterDescription = clusterDescription.WithServerDescription(args.NewServerDescription);
            clusterDescription = EnsureServers(clusterDescription, args.NewServerDescription, newServers);

            if (args.NewServerDescription.CanonicalEndPoint != null &&
                !EndPointHelper.Equals(args.NewServerDescription.CanonicalEndPoint, args.NewServerDescription.EndPoint))
            {
                return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, "CanonicalEndPoint is different than seed list EndPoint."));
            }

            if (args.NewServerDescription.Type == ServerType.ReplicaSetPrimary)
            {
                if (args.NewServerDescription.ReplicaSetConfig.Version != null)
                {
                    bool isCurrentPrimaryStale = true;
                    if (_maxElectionInfo != null)
                    {
                        isCurrentPrimaryStale = _maxElectionInfo.IsStale(args.NewServerDescription.ReplicaSetConfig.Version.Value, args.NewServerDescription.ElectionId);
                        var isReportedPrimaryStale = !isCurrentPrimaryStale;

                        if (isReportedPrimaryStale && args.NewServerDescription.ElectionId != null)
                        {
                            // we only invalidate the "newly" reported stale primary if electionId was used.
                            lock (_serversLock)
                            {
                                var server = _servers.SingleOrDefault(x => EndPointHelper.Equals(args.NewServerDescription.EndPoint, x.EndPoint));
                                server.Invalidate();
                                return(clusterDescription.WithServerDescription(
                                           new ServerDescription(server.ServerId, server.EndPoint)));
                            }
                        }
                    }

                    if (isCurrentPrimaryStale)
                    {
                        _maxElectionInfo = new ElectionInfo(
                            args.NewServerDescription.ReplicaSetConfig.Version.Value,
                            args.NewServerDescription.ElectionId);
                    }
                }

                var currentPrimaryEndPoints = clusterDescription.Servers
                                              .Where(x => x.Type == ServerType.ReplicaSetPrimary)
                                              .Where(x => !EndPointHelper.Equals(x.EndPoint, args.NewServerDescription.EndPoint))
                                              .Select(x => x.EndPoint)
                                              .ToList();

                if (currentPrimaryEndPoints.Count > 0)
                {
                    lock (_serversLock)
                    {
                        var currentPrimaries = _servers.Where(x => EndPointHelper.Contains(currentPrimaryEndPoints, x.EndPoint));
                        foreach (var currentPrimary in currentPrimaries)
                        {
                            // kick off the server to invalidate itself
                            currentPrimary.Invalidate();
                            // set it to disconnected in the cluster
                            clusterDescription = clusterDescription.WithServerDescription(
                                new ServerDescription(currentPrimary.ServerId, currentPrimary.EndPoint));
                        }
                    }
                }
            }

            return(clusterDescription);
        }
Exemple #6
0
        private ClusterDescription ProcessReplicaSetChange(ClusterDescription clusterDescription, ServerDescriptionChangedEventArgs args)
        {
            if (!args.NewServerDescription.Type.IsReplicaSetMember())
            {
                return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server is a {0}, not a replica set member.", args.NewServerDescription.Type)));
            }

            if (args.NewServerDescription.Type == ServerType.ReplicaSetGhost)
            {
                return(clusterDescription.WithServerDescription(args.NewServerDescription));
            }

            if (_replicaSetName == null)
            {
                _replicaSetName = args.NewServerDescription.ReplicaSetConfig.Name;
            }

            if (_replicaSetName != args.NewServerDescription.ReplicaSetConfig.Name)
            {
                return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server was a member of the '{0}' replica set, but should be '{1}'.", args.NewServerDescription.ReplicaSetConfig.Name, _replicaSetName)));
            }

            clusterDescription = clusterDescription.WithServerDescription(args.NewServerDescription);
            clusterDescription = EnsureServers(clusterDescription, args.NewServerDescription);

            if (args.NewServerDescription.CanonicalEndPoint != null &&
                !EndPointHelper.Equals(args.NewServerDescription.CanonicalEndPoint, args.NewServerDescription.EndPoint))
            {
                return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, "CanonicalEndPoint is different than seed list EndPoint."));
            }

            if (args.NewServerDescription.Type == ServerType.ReplicaSetPrimary)
            {
                if (args.NewServerDescription.ElectionId != null)
                {
                    if (_maxElectionId != null && _maxElectionId.CompareTo(args.NewServerDescription.ElectionId) > 0)
                    {
                        // ignore this change because we've already seen this election id
                        lock (_serversLock)
                        {
                            var server = _servers.SingleOrDefault(x => EndPointHelper.Equals(args.NewServerDescription.EndPoint, x.EndPoint));
                            server.Invalidate();
                            return(clusterDescription.WithServerDescription(
                                       new ServerDescription(server.ServerId, server.EndPoint)));
                        }
                    }

                    _maxElectionId = args.NewServerDescription.ElectionId;
                }

                var currentPrimaryEndPoints = clusterDescription.Servers
                                              .Where(x => x.Type == ServerType.ReplicaSetPrimary)
                                              .Where(x => !EndPointHelper.Equals(x.EndPoint, args.NewServerDescription.EndPoint))
                                              .Select(x => x.EndPoint)
                                              .ToList();

                if (currentPrimaryEndPoints.Count > 0)
                {
                    lock (_serversLock)
                    {
                        var currentPrimaries = _servers.Where(x => EndPointHelper.Contains(currentPrimaryEndPoints, x.EndPoint));
                        foreach (var currentPrimary in currentPrimaries)
                        {
                            // kick off the server to invalidate itself
                            currentPrimary.Invalidate();
                            // set it to disconnected in the cluster
                            clusterDescription = clusterDescription.WithServerDescription(
                                new ServerDescription(currentPrimary.ServerId, currentPrimary.EndPoint));
                        }
                    }
                }
            }

            return(clusterDescription);
        }