Represents build info about a server instance.
 public void TestVersion2_4_1_2_rc0()
 {
     var buildInfo = new MongoServerBuildInfo(64, "", "", "2.4.1.2-rc0");
     Assert.AreEqual(2, buildInfo.Version.Major);
     Assert.AreEqual(4, buildInfo.Version.Minor);
     Assert.AreEqual(1, buildInfo.Version.Build);
     Assert.AreEqual(2, buildInfo.Version.Revision);
 }
 public void TestVersion2_4_dot_beta()
 {
     var buildInfo = new MongoServerBuildInfo("2.4.beta");
     Assert.Equal(2, buildInfo.Version.Major);
     Assert.Equal(4, buildInfo.Version.Minor);
     Assert.Equal(-1, buildInfo.Version.Build);
     Assert.Equal(-1, buildInfo.Version.Revision);
 }
 public void TestVersion2_4_0()
 {
     var buildInfo = new MongoServerBuildInfo("2.4.0");
     Assert.AreEqual(2, buildInfo.Version.Major);
     Assert.AreEqual(4, buildInfo.Version.Minor);
     Assert.AreEqual(0, buildInfo.Version.Build);
     Assert.AreEqual(-1, buildInfo.Version.Revision);
 }
 public void TestVersion2_4_1_2()
 {
     var buildInfo = new MongoServerBuildInfo("2.4.1.2");
     Assert.Equal(2, buildInfo.Version.Major);
     Assert.Equal(4, buildInfo.Version.Minor);
     Assert.Equal(1, buildInfo.Version.Build);
     Assert.Equal(2, buildInfo.Version.Revision);
 }
 public void TestVersion2_4_alpha1()
 {
     var buildInfo = new MongoServerBuildInfo(64, "", "", "2.4a1");
     Assert.AreEqual(2, buildInfo.Version.Major);
     Assert.AreEqual(4, buildInfo.Version.Minor);
     Assert.AreEqual(-1, buildInfo.Version.Build);
     Assert.AreEqual(-1, buildInfo.Version.Revision);
 }
 public void TestVersionInvalid()
 {
     var buildInfo = new MongoServerBuildInfo(64, "", "", "v2.4a1");
     Assert.AreEqual(0, buildInfo.Version.Major);
     Assert.AreEqual(0, buildInfo.Version.Minor);
     Assert.AreEqual(0, buildInfo.Version.Build);
     Assert.AreEqual(0, buildInfo.Version.Revision);
 }
        internal void Connect(
            bool slaveOk
        ) {
            if (state != MongoServerState.Disconnected) {
                var message = string.Format("MongoServerInstance.Connect can only be called when state is Disconnected, not when state is {0}.", state);
                throw new InvalidOperationException(message);
            }

            State = MongoServerState.Connecting;
            connectException = null;
            try {
                endPoint = address.ToIPEndPoint(server.Settings.AddressFamily);

                var connectionPool = new MongoConnectionPool(this);
                try {
                    var connection = connectionPool.AcquireConnection(null);
                    try {
                        try {
                            var isMasterCommand = new CommandDocument("ismaster", 1);
                            isMasterResult = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, isMasterCommand);
                        } catch (MongoCommandException ex) {
                            isMasterResult = ex.CommandResult;
                            throw;
                        }

                        isPrimary = isMasterResult.Response["ismaster", false].ToBoolean();
                        isSecondary = isMasterResult.Response["secondary", false].ToBoolean();
                        isPassive = isMasterResult.Response["passive", false].ToBoolean();
                        isArbiter = isMasterResult.Response["arbiterOnly", false].ToBoolean();
                        if (!isPrimary && !slaveOk) {
                            throw new MongoConnectionException("Server is not a primary and SlaveOk is false.");
                        }

                        maxDocumentSize = isMasterResult.Response["maxBsonObjectSize", MongoDefaults.MaxDocumentSize].ToInt32();
                        maxMessageLength = Math.Max(MongoDefaults.MaxMessageLength, maxDocumentSize + 1024); // derived from maxDocumentSize

                        var buildInfoCommand = new CommandDocument("buildinfo", 1);
                        var buildInfoResult = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, buildInfoCommand);
                        buildInfo = new MongoServerBuildInfo(
                            buildInfoResult.Response["bits"].ToInt32(), // bits
                            buildInfoResult.Response["gitVersion"].AsString, // gitVersion
                            buildInfoResult.Response["sysInfo"].AsString, // sysInfo
                            buildInfoResult.Response["version"].AsString // versionString
                        );
                    } finally {
                        connectionPool.ReleaseConnection(connection);
                    }
                } catch {
                    connectionPool.Close();
                    throw;
                }

                State = MongoServerState.Connected;
                this.connectionPool = connectionPool;
            } catch (Exception ex) {
                State = MongoServerState.Disconnected;
                connectException = ex;
                throw;
            }
        }
        // private methods
        private void LookupServerInformation(MongoConnection connection)
        {
            IsMasterResult isMasterResult = null;
            bool ok = false;
            try
            {
                var isMasterCommand = new CommandDocument("ismaster", 1);
                var tempResult = connection.RunCommand("admin", QueryFlags.SlaveOk, isMasterCommand, false);
                isMasterResult = new IsMasterResult();
                isMasterResult.Initialize(isMasterCommand, tempResult.Response);
                if (!isMasterResult.Ok)
                {
                    throw new MongoCommandException(isMasterResult);
                }

                MongoServerBuildInfo buildInfo;
                var buildInfoCommand = new CommandDocument("buildinfo", 1);
                var buildInfoResult = connection.RunCommand("admin", QueryFlags.SlaveOk, buildInfoCommand, false);
                if (buildInfoResult.Ok)
                {
                    buildInfo = MongoServerBuildInfo.FromCommandResult(buildInfoResult);
                }
                else
                {
                    // short term fix: if buildInfo fails due to auth we don't know the server version; see CSHARP-324
                    if (buildInfoResult.ErrorMessage != "need to login")
                    {
                        throw new MongoCommandException(buildInfoResult);
                    }
                    buildInfo = null;
                }

                ReplicaSetInformation replicaSetInformation = null;
                MongoServerInstanceType instanceType = MongoServerInstanceType.StandAlone;
                if (isMasterResult.ReplicaSetName != null)
                {
                    var tagSet = new ReplicaSetTagSet();
                    var peers = isMasterResult.Hosts.Concat(isMasterResult.Passives).Concat(isMasterResult.Arbiters).ToList();
                    replicaSetInformation = new ReplicaSetInformation(isMasterResult.ReplicaSetName, isMasterResult.Primary, peers, tagSet);
                    instanceType = MongoServerInstanceType.ReplicaSetMember;
                }
                else if (isMasterResult.Message != null && isMasterResult.Message == "isdbgrid")
                {
                    instanceType = MongoServerInstanceType.ShardRouter;
                }

                lock (_serverInstanceLock)
                {
                    _isMasterResult = isMasterResult;
                    _maxDocumentSize = isMasterResult.MaxBsonObjectSize;
                    _maxMessageLength = isMasterResult.MaxMessageLength;
                    _buildInfo = buildInfo;
                    this.SetState(MongoServerState.Connected,
                        instanceType,
                        isMasterResult.IsPrimary,
                        isMasterResult.IsSecondary,
                        isMasterResult.IsPassive,
                        isMasterResult.IsArbiterOnly,
                        replicaSetInformation);
                }
                ok = true;
            }
            finally
            {
                if (!ok)
                {
                    lock (_serverInstanceLock)
                    {
                        _isMasterResult = isMasterResult;
                        _maxDocumentSize = MongoDefaults.MaxDocumentSize;
                        _maxMessageLength = MongoDefaults.MaxMessageLength;
                        _buildInfo = null;
                        this.SetState(MongoServerState.Disconnected, _instanceType, false, false, false, false, null);
                    }
                }
            }
        }
        internal void Connect(
            bool slaveOk
        ) {
            lock (serverInstanceLock) {
                // note: don't check that state is Disconnected here
                // when reconnecting to a replica set state can transition from Connected -> Connecting -> Connected

                State = MongoServerState.Connecting;
                connectException = null;
                try {
                    endPoint = address.ToIPEndPoint(server.Settings.AddressFamily);

                    if (connectionPool == null) {
                        connectionPool = new MongoConnectionPool(this);
                    }

                    try {
                        var connection = connectionPool.AcquireConnection(null);
                        try {
                            try {
                                var isMasterCommand = new CommandDocument("ismaster", 1);
                                isMasterResult = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, isMasterCommand);
                            } catch (MongoCommandException ex) {
                                isMasterResult = ex.CommandResult;
                                throw;
                            }

                            isPrimary = isMasterResult.Response["ismaster", false].ToBoolean();
                            isSecondary = isMasterResult.Response["secondary", false].ToBoolean();
                            isPassive = isMasterResult.Response["passive", false].ToBoolean();
                            isArbiter = isMasterResult.Response["arbiterOnly", false].ToBoolean();
                            // workaround for CSHARP-273
                            if (isPassive && isArbiter) { isPassive = false; }
                            if (!isPrimary && !slaveOk) {
                                throw new MongoConnectionException("Server is not a primary and SlaveOk is false.");
                            }

                            maxDocumentSize = isMasterResult.Response["maxBsonObjectSize", MongoDefaults.MaxDocumentSize].ToInt32();
                            maxMessageLength = Math.Max(MongoDefaults.MaxMessageLength, maxDocumentSize + 1024); // derived from maxDocumentSize

                            var buildInfoCommand = new CommandDocument("buildinfo", 1);
                            var buildInfoResult = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, buildInfoCommand);
                            buildInfo = new MongoServerBuildInfo(
                                buildInfoResult.Response["bits"].ToInt32(), // bits
                                buildInfoResult.Response["gitVersion"].AsString, // gitVersion
                                buildInfoResult.Response["sysInfo"].AsString, // sysInfo
                                buildInfoResult.Response["version"].AsString // versionString
                            );
                        } finally {
                            connection.ConnectionPool.ReleaseConnection(connection);
                        }
                    } catch {
                        if (connectionPool != null) {
                            connectionPool.Close();
                            connectionPool = null;
                        }
                        throw;
                    }

                    // for the primary only immediately start creating connections to reach MinConnectionPoolSize
                    if (isPrimary) {
                        connectionPool.CreateInitialConnections(); // will be done on a background thread
                    }

                    State = MongoServerState.Connected;
                } catch (Exception ex) {
                    State = MongoServerState.Disconnected;
                    connectException = ex;
                    throw;
                }
            }
        }
        internal void VerifyState(
            MongoConnection connection
        )
        {
            CommandResult isMasterResult = null;
            try {
                try {
                    var isMasterCommand = new CommandDocument("ismaster", 1);
                    isMasterResult = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, isMasterCommand);
                } catch (MongoCommandException ex) {
                    isMasterResult = ex.CommandResult;
                    throw;
                }

                var isPrimary = isMasterResult.Response["ismaster", false].ToBoolean();
                var isSecondary = isMasterResult.Response["secondary", false].ToBoolean();
                var isPassive = isMasterResult.Response["passive", false].ToBoolean();
                var isArbiter = isMasterResult.Response["arbiterOnly", false].ToBoolean();
                // workaround for CSHARP-273
                if (isPassive && isArbiter) { isPassive = false; }

                var maxDocumentSize = isMasterResult.Response["maxBsonObjectSize", MongoDefaults.MaxDocumentSize].ToInt32();
                var maxMessageLength = Math.Max(MongoDefaults.MaxMessageLength, maxDocumentSize + 1024); // derived from maxDocumentSize

                MongoServerBuildInfo buildInfo;
                try {
                    var buildInfoCommand = new CommandDocument("buildinfo", 1);
                    var buildInfoResult = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, buildInfoCommand);
                    buildInfo = new MongoServerBuildInfo(
                        buildInfoResult.Response["bits"].ToInt32(), // bits
                        buildInfoResult.Response["gitVersion"].AsString, // gitVersion
                        buildInfoResult.Response["sysInfo"].AsString, // sysInfo
                        buildInfoResult.Response["version"].AsString // versionString
                    );
                } catch (MongoCommandException ex) {
                    // short term fix: if buildInfo fails due to auth we don't know the server version
                    if (ex.CommandResult.ErrorMessage == "need to login") {
                        buildInfo = null;
                    } else {
                        throw;
                    }
                }

                this.isMasterResult = isMasterResult;
                this.maxDocumentSize = maxDocumentSize;
                this.maxMessageLength = maxMessageLength;
                this.buildInfo = buildInfo;
                this.SetState(MongoServerState.Connected, isPrimary, isSecondary, isPassive, isArbiter);
            } catch {
                this.isMasterResult = isMasterResult;
                this.maxDocumentSize = MongoDefaults.MaxDocumentSize;
                this.maxMessageLength = MongoDefaults.MaxMessageLength;
                this.buildInfo = null;
                this.SetState(MongoServerState.Disconnected, false, false, false, false);
                throw;
            }
        }
Example #11
0
        internal void VerifyState(MongoConnection connection)
        {
            CommandResult isMasterResult = null;
            bool          ok             = false;

            try
            {
                var isMasterCommand = new CommandDocument("ismaster", 1);
                isMasterResult = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, isMasterCommand, false);
                if (!isMasterResult.Ok)
                {
                    throw new MongoCommandException(isMasterResult);
                }

                var isPrimary   = isMasterResult.Response["ismaster", false].ToBoolean();
                var isSecondary = isMasterResult.Response["secondary", false].ToBoolean();
                var isPassive   = isMasterResult.Response["passive", false].ToBoolean();
                var isArbiter   = isMasterResult.Response["arbiterOnly", false].ToBoolean();
                // workaround for CSHARP-273
                if (isPassive && isArbiter)
                {
                    isPassive = false;
                }

                var maxDocumentSize  = isMasterResult.Response["maxBsonObjectSize", MongoDefaults.MaxDocumentSize].ToInt32();
                var maxMessageLength = Math.Max(MongoDefaults.MaxMessageLength, maxDocumentSize + 1024); // derived from maxDocumentSize

                MongoServerBuildInfo buildInfo;
                var buildInfoCommand = new CommandDocument("buildinfo", 1);
                var buildInfoResult  = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, buildInfoCommand, false);
                if (buildInfoResult.Ok)
                {
                    buildInfo = new MongoServerBuildInfo(
                        buildInfoResult.Response["bits"].ToInt32(),      // bits
                        buildInfoResult.Response["gitVersion"].AsString, // gitVersion
                        buildInfoResult.Response["sysInfo"].AsString,    // sysInfo
                        buildInfoResult.Response["version"].AsString     // versionString
                        );
                }
                else
                {
                    // short term fix: if buildInfo fails due to auth we don't know the server version; see CSHARP-324
                    if (buildInfoResult.ErrorMessage != "need to login")
                    {
                        throw new MongoCommandException(buildInfoResult);
                    }
                    buildInfo = null;
                }

                _isMasterResult   = isMasterResult;
                _maxDocumentSize  = maxDocumentSize;
                _maxMessageLength = maxMessageLength;
                _buildInfo        = buildInfo;
                this.SetState(MongoServerState.Connected, isPrimary, isSecondary, isPassive, isArbiter);

                // if this is the primary of a replica set check to see if any instances have been added or removed
                if (isPrimary && _server.Settings.ConnectionMode == ConnectionMode.ReplicaSet)
                {
                    var instanceAddresses = new List <MongoServerAddress>();
                    if (isMasterResult.Response.Contains("hosts"))
                    {
                        foreach (var hostName in isMasterResult.Response["hosts"].AsBsonArray)
                        {
                            var address = MongoServerAddress.Parse(hostName.AsString);
                            instanceAddresses.Add(address);
                        }
                    }
                    if (isMasterResult.Response.Contains("passives"))
                    {
                        foreach (var hostName in isMasterResult.Response["passives"].AsBsonArray)
                        {
                            var address = MongoServerAddress.Parse(hostName.AsString);
                            instanceAddresses.Add(address);
                        }
                    }
                    if (isMasterResult.Response.Contains("arbiters"))
                    {
                        foreach (var hostName in isMasterResult.Response["arbiters"].AsBsonArray)
                        {
                            var address = MongoServerAddress.Parse(hostName.AsString);
                            instanceAddresses.Add(address);
                        }
                    }
                    _server.VerifyInstances(instanceAddresses);
                }

                ok = true;
            }
            finally
            {
                if (!ok)
                {
                    _isMasterResult   = isMasterResult;
                    _maxDocumentSize  = MongoDefaults.MaxDocumentSize;
                    _maxMessageLength = MongoDefaults.MaxMessageLength;
                    _buildInfo        = null;
                    this.SetState(MongoServerState.Disconnected, false, false, false, false);
                }
            }
        }
        // private methods
        private void LookupServerInformation(MongoConnection connection)
        {
            IsMasterResult isMasterResult = null;
            bool           ok             = false;

            try
            {
                var isMasterCommand = new CommandDocument("ismaster", 1);
                isMasterResult = RunCommandAs <IsMasterResult>(connection, "admin", isMasterCommand);

                MongoServerBuildInfo buildInfo;
                try
                {
                    var buildInfoCommand = new CommandDocument("buildinfo", 1);
                    var buildInfoResult  = RunCommandAs <CommandResult>(connection, "admin", buildInfoCommand);
                    buildInfo = MongoServerBuildInfo.FromCommandResult(buildInfoResult);
                }
                catch (MongoCommandException ex)
                {
                    // short term fix: if buildInfo fails due to auth we don't know the server version; see CSHARP-324
                    if (ex.CommandResult.ErrorMessage != "need to login")
                    {
                        throw;
                    }
                    buildInfo = null;
                }

                ReplicaSetInformation   replicaSetInformation = null;
                MongoServerInstanceType instanceType          = MongoServerInstanceType.StandAlone;
                if (isMasterResult.IsReplicaSet)
                {
                    var peers = isMasterResult.Hosts.Concat(isMasterResult.Passives).Concat(isMasterResult.Arbiters).ToList();
                    replicaSetInformation = new ReplicaSetInformation(isMasterResult.ReplicaSetName, isMasterResult.Primary, peers, isMasterResult.Tags, isMasterResult.ReplicaSetConfigVersion);
                    instanceType          = MongoServerInstanceType.ReplicaSetMember;
                }
                else if (isMasterResult.Message != null && isMasterResult.Message == "isdbgrid")
                {
                    instanceType = MongoServerInstanceType.ShardRouter;
                }

                var featureContext = new FeatureContext
                {
                    BuildInfo          = buildInfo,
                    Connection         = connection,
                    IsMasterResult     = isMasterResult,
                    ServerInstanceType = instanceType
                };
                var featureSet = new FeatureSetDetector().DetectFeatureSet(featureContext);

                var newServerInfo = new ServerInformation
                {
                    BuildInfo             = buildInfo,
                    FeatureSet            = featureSet,
                    InstanceType          = instanceType,
                    IsArbiter             = isMasterResult.IsArbiterOnly,
                    IsMasterResult        = isMasterResult,
                    IsPassive             = isMasterResult.IsPassive,
                    IsPrimary             = isMasterResult.IsPrimary,
                    IsSecondary           = isMasterResult.IsSecondary,
                    MaxBatchCount         = isMasterResult.MaxWriteBatchSize,
                    MaxDocumentSize       = isMasterResult.MaxBsonObjectSize,
                    MaxMessageLength      = isMasterResult.MaxMessageLength,
                    ReplicaSetInformation = replicaSetInformation
                };
                MongoServerState currentState;
                lock (_serverInstanceLock)
                {
                    currentState = _state;
                }
                SetState(currentState, newServerInfo);
                ok = true;
            }
            finally
            {
                if (!ok)
                {
                    ServerInformation currentServerInfo;
                    lock (_serverInstanceLock)
                    {
                        currentServerInfo = _serverInfo;
                    }

                    // keep the current instance type, build info, and replica set info
                    // as these aren't relevent to state and are likely still correct.
                    var newServerInfo = new ServerInformation
                    {
                        BuildInfo             = currentServerInfo.BuildInfo,
                        FeatureSet            = currentServerInfo.FeatureSet,
                        InstanceType          = currentServerInfo.InstanceType,
                        IsArbiter             = false,
                        IsMasterResult        = isMasterResult,
                        IsPassive             = false,
                        IsPrimary             = false,
                        IsSecondary           = false,
                        MaxDocumentSize       = currentServerInfo.MaxDocumentSize,
                        MaxMessageLength      = currentServerInfo.MaxMessageLength,
                        MaxBatchCount         = currentServerInfo.MaxBatchCount,
                        ReplicaSetInformation = currentServerInfo.ReplicaSetInformation
                    };

                    SetState(MongoServerState.Disconnected, newServerInfo);
                }
            }
        }
        internal void VerifyState(
            MongoConnection connection
            )
        {
            CommandResult isMasterResult = null;

            try {
                try {
                    var isMasterCommand = new CommandDocument("ismaster", 1);
                    isMasterResult = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, isMasterCommand);
                } catch (MongoCommandException ex) {
                    isMasterResult = ex.CommandResult;
                    throw;
                }

                var isPrimary   = isMasterResult.Response["ismaster", false].ToBoolean();
                var isSecondary = isMasterResult.Response["secondary", false].ToBoolean();
                var isPassive   = isMasterResult.Response["passive", false].ToBoolean();
                var isArbiter   = isMasterResult.Response["arbiterOnly", false].ToBoolean();
                // workaround for CSHARP-273
                if (isPassive && isArbiter)
                {
                    isPassive = false;
                }

                var maxDocumentSize  = isMasterResult.Response["maxBsonObjectSize", MongoDefaults.MaxDocumentSize].ToInt32();
                var maxMessageLength = Math.Max(MongoDefaults.MaxMessageLength, maxDocumentSize + 1024); // derived from maxDocumentSize

                MongoServerBuildInfo buildInfo;
                try {
                    var buildInfoCommand = new CommandDocument("buildinfo", 1);
                    var buildInfoResult  = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, buildInfoCommand);
                    buildInfo = new MongoServerBuildInfo(
                        buildInfoResult.Response["bits"].ToInt32(),      // bits
                        buildInfoResult.Response["gitVersion"].AsString, // gitVersion
                        buildInfoResult.Response["sysInfo"].AsString,    // sysInfo
                        buildInfoResult.Response["version"].AsString     // versionString
                        );
                } catch (MongoCommandException ex) {
                    // short term fix: if buildInfo fails due to auth we don't know the server version
                    if (ex.CommandResult.ErrorMessage == "need to login")
                    {
                        buildInfo = null;
                    }
                    else
                    {
                        throw;
                    }
                }

                this.isMasterResult   = isMasterResult;
                this.maxDocumentSize  = maxDocumentSize;
                this.maxMessageLength = maxMessageLength;
                this.buildInfo        = buildInfo;
                this.SetState(MongoServerState.Connected, isPrimary, isSecondary, isPassive, isArbiter);
            } catch {
                this.isMasterResult   = isMasterResult;
                this.maxDocumentSize  = MongoDefaults.MaxDocumentSize;
                this.maxMessageLength = MongoDefaults.MaxMessageLength;
                this.buildInfo        = null;
                this.SetState(MongoServerState.Disconnected, false, false, false, false);
                throw;
            }
        }
        internal void Connect(
            bool slaveOk
            )
        {
            if (state != MongoServerState.Disconnected)
            {
                var message = string.Format("MongoServerInstance.Connect can only be called when state is Disconnected, not when state is {0}.", state);
                throw new InvalidOperationException(message);
            }

            State            = MongoServerState.Connecting;
            connectException = null;
            try {
                endPoint = address.ToIPEndPoint(server.Settings.AddressFamily);

                var connectionPool = new MongoConnectionPool(this);
                try {
                    var connection = connectionPool.AcquireConnection(null);
                    try {
                        try {
                            var isMasterCommand = new CommandDocument("ismaster", 1);
                            isMasterResult = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, isMasterCommand);
                        } catch (MongoCommandException ex) {
                            isMasterResult = ex.CommandResult;
                            throw;
                        }

                        isPrimary   = isMasterResult.Response["ismaster", false].ToBoolean();
                        isSecondary = isMasterResult.Response["secondary", false].ToBoolean();
                        isPassive   = isMasterResult.Response["passive", false].ToBoolean();
                        isArbiter   = isMasterResult.Response["arbiterOnly", false].ToBoolean();
                        if (!isPrimary && !slaveOk)
                        {
                            throw new MongoConnectionException("Server is not a primary and SlaveOk is false.");
                        }

                        maxDocumentSize  = isMasterResult.Response["maxBsonObjectSize", MongoDefaults.MaxDocumentSize].ToInt32();
                        maxMessageLength = Math.Max(MongoDefaults.MaxMessageLength, maxDocumentSize + 1024); // derived from maxDocumentSize

                        var buildInfoCommand = new CommandDocument("buildinfo", 1);
                        var buildInfoResult  = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, buildInfoCommand);
                        buildInfo = new MongoServerBuildInfo(
                            buildInfoResult.Response["bits"].ToInt32(),      // bits
                            buildInfoResult.Response["gitVersion"].AsString, // gitVersion
                            buildInfoResult.Response["sysInfo"].AsString,    // sysInfo
                            buildInfoResult.Response["version"].AsString     // versionString
                            );
                    } finally {
                        connectionPool.ReleaseConnection(connection);
                    }
                } catch {
                    connectionPool.Close();
                    throw;
                }

                State = MongoServerState.Connected;
                this.connectionPool = connectionPool;
            } catch (Exception ex) {
                State            = MongoServerState.Disconnected;
                connectException = ex;
                throw;
            }
        }
        // private methods
        private void LookupServerInformation(MongoConnection connection)
        {
            IsMasterResult isMasterResult = null;
            bool           ok             = false;

            try
            {
                var isMasterCommand = new CommandDocument("ismaster", 1);
                var tempResult      = connection.RunCommand("admin", QueryFlags.SlaveOk, isMasterCommand, false);
                isMasterResult = new IsMasterResult();
                isMasterResult.Initialize(isMasterCommand, tempResult.Response);
                if (!isMasterResult.Ok)
                {
                    throw new MongoCommandException(isMasterResult);
                }

                MongoServerBuildInfo buildInfo;
                var buildInfoCommand = new CommandDocument("buildinfo", 1);
                var buildInfoResult  = connection.RunCommand("admin", QueryFlags.SlaveOk, buildInfoCommand, false);
                if (buildInfoResult.Ok)
                {
                    buildInfo = MongoServerBuildInfo.FromCommandResult(buildInfoResult);
                }
                else
                {
                    // short term fix: if buildInfo fails due to auth we don't know the server version; see CSHARP-324
                    if (buildInfoResult.ErrorMessage != "need to login")
                    {
                        throw new MongoCommandException(buildInfoResult);
                    }
                    buildInfo = null;
                }

                ReplicaSetInformation   replicaSetInformation = null;
                MongoServerInstanceType instanceType          = MongoServerInstanceType.StandAlone;
                if (isMasterResult.ReplicaSetName != null)
                {
                    var peers = isMasterResult.Hosts.Concat(isMasterResult.Passives).Concat(isMasterResult.Arbiters).ToList();
                    replicaSetInformation = new ReplicaSetInformation(isMasterResult.ReplicaSetName, isMasterResult.Primary, peers, isMasterResult.Tags);
                    instanceType          = MongoServerInstanceType.ReplicaSetMember;
                }
                else if (isMasterResult.Message != null && isMasterResult.Message == "isdbgrid")
                {
                    instanceType = MongoServerInstanceType.ShardRouter;
                }

                var newServerInfo = new ServerInformation
                {
                    BuildInfo             = buildInfo,
                    InstanceType          = instanceType,
                    IsArbiter             = isMasterResult.IsArbiterOnly,
                    IsMasterResult        = isMasterResult,
                    IsPassive             = isMasterResult.IsPassive,
                    IsPrimary             = isMasterResult.IsPrimary,
                    IsSecondary           = isMasterResult.IsSecondary,
                    MaxDocumentSize       = isMasterResult.MaxBsonObjectSize,
                    MaxMessageLength      = isMasterResult.MaxMessageLength,
                    ReplicaSetInformation = replicaSetInformation
                };
                MongoServerState currentState;
                lock (_serverInstanceLock)
                {
                    currentState = _state;
                }
                SetState(currentState, newServerInfo);
                ok = true;
            }
            finally
            {
                if (!ok)
                {
                    ServerInformation currentServerInfo;
                    lock (_serverInstanceLock)
                    {
                        currentServerInfo = _serverInfo;
                    }

                    // keep the current instance type, build info, and replica set info
                    // as these aren't relevent to state and are likely still correct.
                    var newServerInfo = new ServerInformation
                    {
                        BuildInfo             = currentServerInfo.BuildInfo,
                        InstanceType          = currentServerInfo.InstanceType,
                        IsArbiter             = false,
                        IsMasterResult        = isMasterResult,
                        IsPassive             = false,
                        IsPrimary             = false,
                        IsSecondary           = false,
                        MaxDocumentSize       = currentServerInfo.MaxDocumentSize,
                        MaxMessageLength      = currentServerInfo.MaxMessageLength,
                        ReplicaSetInformation = currentServerInfo.ReplicaSetInformation
                    };

                    SetState(MongoServerState.Disconnected, newServerInfo);
                }
            }
        }
        internal void VerifyState(MongoConnection connection)
        {
            CommandResult isMasterResult = null;
            bool ok = false;
            try
            {
                var isMasterCommand = new CommandDocument("ismaster", 1);
                isMasterResult = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, isMasterCommand, false);
                if (!isMasterResult.Ok)
                {
                    throw new MongoCommandException(isMasterResult);
                }

                var isPrimary = isMasterResult.Response["ismaster", false].ToBoolean();
                var isSecondary = isMasterResult.Response["secondary", false].ToBoolean();
                var isPassive = isMasterResult.Response["passive", false].ToBoolean();
                var isArbiter = isMasterResult.Response["arbiterOnly", false].ToBoolean();
                // workaround for CSHARP-273
                if (isPassive && isArbiter) { isPassive = false; }

                var maxDocumentSize = isMasterResult.Response["maxBsonObjectSize", MongoDefaults.MaxDocumentSize].ToInt32();
                var maxMessageLength = Math.Max(MongoDefaults.MaxMessageLength, maxDocumentSize + 1024); // derived from maxDocumentSize

                MongoServerBuildInfo buildInfo;
                var buildInfoCommand = new CommandDocument("buildinfo", 1);
                var buildInfoResult = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, buildInfoCommand, false);
                if (buildInfoResult.Ok)
                {
                    buildInfo = new MongoServerBuildInfo(
                        buildInfoResult.Response["bits"].ToInt32(), // bits
                        buildInfoResult.Response["gitVersion"].AsString, // gitVersion
                        buildInfoResult.Response["sysInfo"].AsString, // sysInfo
                        buildInfoResult.Response["version"].AsString // versionString
                    );
                }
                else
                {
                    // short term fix: if buildInfo fails due to auth we don't know the server version; see CSHARP-324
                    if (buildInfoResult.ErrorMessage != "need to login")
                    {
                        throw new MongoCommandException(buildInfoResult);
                    }
                    buildInfo = null;
                }

                _isMasterResult = isMasterResult;
                _maxDocumentSize = maxDocumentSize;
                _maxMessageLength = maxMessageLength;
                _buildInfo = buildInfo;
                this.SetState(MongoServerState.Connected, isPrimary, isSecondary, isPassive, isArbiter);

                // if this is the primary of a replica set check to see if any instances have been added or removed
                if (isPrimary && _server.Settings.ConnectionMode == ConnectionMode.ReplicaSet)
                {
                    var instanceAddresses = new List<MongoServerAddress>();
                    if (isMasterResult.Response.Contains("hosts"))
                    {
                        foreach (var hostName in isMasterResult.Response["hosts"].AsBsonArray)
                        {
                            var address = MongoServerAddress.Parse(hostName.AsString);
                            instanceAddresses.Add(address);
                        }
                    }
                    if (isMasterResult.Response.Contains("passives"))
                    {
                        foreach (var hostName in isMasterResult.Response["passives"].AsBsonArray)
                        {
                            var address = MongoServerAddress.Parse(hostName.AsString);
                            instanceAddresses.Add(address);
                        }
                    }
                    if (isMasterResult.Response.Contains("arbiters"))
                    {
                        foreach (var hostName in isMasterResult.Response["arbiters"].AsBsonArray)
                        {
                            var address = MongoServerAddress.Parse(hostName.AsString);
                            instanceAddresses.Add(address);
                        }
                    }
                    _server.VerifyInstances(instanceAddresses);
                }

                ok = true;
            }
            finally
            {
                if (!ok)
                {
                    _isMasterResult = isMasterResult;
                    _maxDocumentSize = MongoDefaults.MaxDocumentSize;
                    _maxMessageLength = MongoDefaults.MaxMessageLength;
                    _buildInfo = null;
                    this.SetState(MongoServerState.Disconnected, false, false, false, false);
                }
            }
        }
        internal void VerifyState(MongoConnection connection)
        {
            CommandResult isMasterResult = null;
            bool ok = false;
            try
            {
                var isMasterCommand = new CommandDocument("ismaster", 1);
                isMasterResult = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, isMasterCommand, false);
                if (!isMasterResult.Ok)
                {
                    throw new MongoCommandException(isMasterResult);
                }

                var isPrimary = isMasterResult.Response["ismaster", false].ToBoolean();
                var isSecondary = isMasterResult.Response["secondary", false].ToBoolean();
                var isPassive = isMasterResult.Response["passive", false].ToBoolean();
                var isArbiter = isMasterResult.Response["arbiterOnly", false].ToBoolean();

                //let's suppose for now that tags are included in the isMaster command results
                var tags = isMasterResult.Response["tags", new BsonArray()].AsBsonArray.ToList();
                foreach (BsonValue tag in tags)
                    if (tag.IsString) this.tags.Add(tag.AsString);

                // workaround for CSHARP-273
                if (isPassive && isArbiter) { isPassive = false; }

                var maxDocumentSize = isMasterResult.Response["maxBsonObjectSize", MongoDefaults.MaxDocumentSize].ToInt32();
                var maxMessageLength = Math.Max(MongoDefaults.MaxMessageLength, maxDocumentSize + 1024); // derived from maxDocumentSize

                MongoServerBuildInfo buildInfo;
                var buildInfoCommand = new CommandDocument("buildinfo", 1);
                var buildInfoResult = connection.RunCommand("admin.$cmd", QueryFlags.SlaveOk, buildInfoCommand, false);
                if (buildInfoResult.Ok)
                {
                    buildInfo = new MongoServerBuildInfo(
                        buildInfoResult.Response["bits"].ToInt32(), // bits
                        buildInfoResult.Response["gitVersion"].AsString, // gitVersion
                        buildInfoResult.Response["sysInfo"].AsString, // sysInfo
                        buildInfoResult.Response["version"].AsString // versionString
                    );
                }
                else
                {
                    // short term fix: if buildInfo fails due to auth we don't know the server version; see CSHARP-324
                    if (buildInfoResult.ErrorMessage != "need to login")
                    {
                        throw new MongoCommandException(buildInfoResult);
                    }
                    buildInfo = null;
                }

                this.isMasterResult = isMasterResult;
                this.maxDocumentSize = maxDocumentSize;
                this.maxMessageLength = maxMessageLength;
                this.buildInfo = buildInfo;
                this.SetState(MongoServerState.Connected, isPrimary, isSecondary, isPassive, isArbiter);
                ok = true;
            }
            finally
            {
                if (!ok)
                {
                    this.isMasterResult = isMasterResult;
                    this.maxDocumentSize = MongoDefaults.MaxDocumentSize;
                    this.maxMessageLength = MongoDefaults.MaxMessageLength;
                    this.buildInfo = null;
                    this.SetState(MongoServerState.Disconnected, false, false, false, false);
                }
            }
        }