// internal methods
        internal void Connect(TimeSpan timeout, ConnectWaitFor waitFor)
        {
            _timeoutAt = DateTime.UtcNow + timeout;

            // connect to all server instances in parallel (they will report responses back through the responseQueue)
            // the set of Instances initially comes from the seed list, but is adjusted to the official set once connected
            foreach (var serverInstance in _server.Instances)
            {
                QueueConnect(serverInstance);
            }

            // process the responses as they come back and return as soon as we have connected to the primary
            // any remaining responses after the primary will be processed in the background

            while (_responses.Count < _connects.Count)
            {
                var timeRemaining = _timeoutAt - DateTime.UtcNow;
                var response = _responseQueue.Dequeue(timeRemaining);
                if (response == null)
                {
                    break; // we timed out
                }

                ProcessResponse(response);

                // return as soon as we can (according to the waitFor mode specified)
                bool exitEarly = false;
                switch (waitFor)
                {
                    case ConnectWaitFor.All:
                        if (_server.Instances.All(i => i.State == MongoServerState.Connected))
                        {
                            exitEarly = true;
                        }
                        break;
                    case ConnectWaitFor.AnySlaveOk:
                        if (_server.Instances.Any(i => (i.IsPrimary || i.IsSecondary || i.IsPassive) && i.State == MongoServerState.Connected))
                        {
                            exitEarly = true;
                        }
                        break;
                    case ConnectWaitFor.Primary:
                        var primary = _server.Primary;
                        if (primary != null && primary.State == MongoServerState.Connected)
                        {
                            exitEarly = true;
                        }
                        break;
                    default:
                        throw new ArgumentException("Invalid ConnectWaitFor value.");
                }

                if (exitEarly)
                {
                    if (_responses.Count < _connects.Count)
                    {
                        // process any additional responses in the background
                        ThreadPool.QueueUserWorkItem(ProcessAdditionalResponsesWorkItem);
                    }
                    return;
                }
            }

            string waitForString;
            switch (waitFor)
            {
                case ConnectWaitFor.All: waitForString = "all members"; break;
                case ConnectWaitFor.AnySlaveOk: waitForString = "any slaveOk member"; break;
                case ConnectWaitFor.Primary: waitForString = "the primary member"; break;
                default: throw new ArgumentException("Invalid ConnectWaitFor value.");
            }

            var exceptions = _responses.Select(r => r.ServerInstance.ConnectException).Where(e => e != null).ToArray();
            var firstException = exceptions.FirstOrDefault();
            string message;
            if (firstException == null)
            {
                message = string.Format("Unable to connect to {0} of the replica set.", waitForString);
            }
            else
            {
                message = string.Format("Unable to connect to {0} of the replica set: {1}.", waitForString, firstException.Message);
            }
            var connectionException = new MongoConnectionException(message, firstException);
            connectionException.Data.Add("InnerExceptions", exceptions); // useful when there is more than one
            throw connectionException;
        }
Exemple #2
0
 public void Connect(ConnectWaitFor waitFor)
 {
     _mongoServer.Connect(waitFor);
 }
Exemple #3
0
 public void Connect(TimeSpan timeout, ConnectWaitFor waitFor)
 {
     _mongoServer.Connect(timeout, waitFor);
 }
        // internal methods
        internal void Connect(TimeSpan timeout, ConnectWaitFor waitFor)
        {
            _timeoutAt = DateTime.UtcNow + timeout;

            // connect to all server instances in parallel (they will report responses back through the responseQueue)
            // the set of Instances initially comes from the seed list, but is adjusted to the official set once connected
            foreach (var serverInstance in _server.Instances)
            {
                QueueConnect(serverInstance);
            }

            // process the responses as they come back and return as soon as we have connected to the primary
            // any remaining responses after the primary will be processed in the background

            while (_responses.Count < _connects.Count)
            {
                var timeRemaining = _timeoutAt - DateTime.UtcNow;
                var response      = _responseQueue.Dequeue(timeRemaining);
                if (response == null)
                {
                    break; // we timed out
                }

                ProcessResponse(response);

                // return as soon as we can (according to the waitFor mode specified)
                bool exitEarly = false;
                switch (waitFor)
                {
                case ConnectWaitFor.All:
                    if (_server.Instances.All(i => i.State == MongoServerState.Connected))
                    {
                        exitEarly = true;
                    }
                    break;

                case ConnectWaitFor.AnySlaveOk:
                    // don't check for IsPassive because IsSecondary is also true for passives (and only true if not in recovery mode)
                    if (_server.Instances.Any(i => (i.IsPrimary || i.IsSecondary) && i.State == MongoServerState.Connected))
                    {
                        exitEarly = true;
                    }
                    break;

                case ConnectWaitFor.Primary:
                    var primary = _server.Primary;
                    if (primary != null && primary.State == MongoServerState.Connected)
                    {
                        exitEarly = true;
                    }
                    break;

                default:
                    throw new ArgumentException("Invalid ConnectWaitFor value.");
                }

                if (exitEarly)
                {
                    if (_responses.Count < _connects.Count)
                    {
                        // process any additional responses in the background
                        ThreadPool.QueueUserWorkItem(ProcessAdditionalResponsesWorkItem);
                    }
                    return;
                }
            }

            string waitForString;

            switch (waitFor)
            {
            case ConnectWaitFor.All: waitForString = "all members"; break;

            case ConnectWaitFor.AnySlaveOk: waitForString = "any slaveOk member"; break;

            case ConnectWaitFor.Primary: waitForString = "the primary member"; break;

            default: throw new ArgumentException("Invalid ConnectWaitFor value.");
            }

            var    exceptions     = _responses.Select(r => r.ServerInstance.ConnectException).Where(e => e != null).ToArray();
            var    firstException = exceptions.FirstOrDefault();
            string message;

            if (firstException == null)
            {
                message = string.Format("Unable to connect to {0} of the replica set.", waitForString);
            }
            else
            {
                message = string.Format("Unable to connect to {0} of the replica set: {1}.", waitForString, firstException.Message);
            }
            var connectionException = new MongoConnectionException(message, firstException);

            connectionException.Data.Add("InnerExceptions", exceptions); // useful when there is more than one
            throw connectionException;
        }