/// <summary>
 /// Initializes a new instance of the <see cref="ClusterSelectedServerEvent" /> struct.
 /// </summary>
 /// <param name="clusterDescription">The cluster description.</param>
 /// <param name="serverSelector">The server selector.</param>
 /// <param name="selectedServer">The selected server.</param>
 /// <param name="duration">The duration of time it took to select the server.</param>
 public ClusterSelectedServerEvent(ClusterDescription clusterDescription, IServerSelector serverSelector, ServerDescription selectedServer, TimeSpan duration)
 {
     _clusterDescription = clusterDescription;
     _serverSelector = serverSelector;
     _selectedServer = selectedServer;
     _duration = duration;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ClusterSelectedServerEvent" /> struct.
 /// </summary>
 /// <param name="clusterDescription">The cluster description.</param>
 /// <param name="serverSelector">The server selector.</param>
 /// <param name="selectedServer">The selected server.</param>
 /// <param name="duration">The duration of time it took to select the server.</param>
 public ClusterSelectedServerEvent(ClusterDescription clusterDescription, IServerSelector serverSelector, ServerDescription selectedServer, TimeSpan duration)
 {
     _clusterDescription = clusterDescription;
     _serverSelector     = serverSelector;
     _selectedServer     = selectedServer;
     _duration           = duration;
 }
예제 #3
0
        public async Task <IServer> SelectServerAsync(IServerSelector selector, CancellationToken cancellationToken)
        {
            ThrowIfDisposedOrNotOpen();
            Ensure.IsNotNull(selector, nameof(selector));

            using (var helper = new SelectServerHelper(this, selector))
            {
                try
                {
                    while (true)
                    {
                        var server = helper.SelectServer();
                        if (server != null)
                        {
                            return(server);
                        }

                        helper.WaitingForDescriptionToChange();
                        await WaitForDescriptionChangedAsync(helper.Selector, helper.Description, helper.DescriptionChangedTask, helper.TimeoutRemaining, cancellationToken).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    helper.HandleException(ex);
                    throw;
                }
            }
        }
예제 #4
0
 // constructors
 /// <summary>
 /// Initializes a new instance of the <see cref="ClusterSettings"/> class.
 /// </summary>
 /// <param name="connectionMode">The connection mode.</param>
 /// <param name="endPoints">The end points.</param>
 /// <param name="kmsProviders">The kms providers.</param>
 /// <param name="localThreshold">The local threshold.</param>
 /// <param name="maxServerSelectionWaitQueueSize">Maximum size of the server selection wait queue.</param>
 /// <param name="replicaSetName">Name of the replica set.</param>
 /// <param name="serverSelectionTimeout">The server selection timeout.</param>
 /// <param name="preServerSelector">The pre server selector.</param>
 /// <param name="postServerSelector">The post server selector.</param>
 /// <param name="schemaMap">The schema map.</param>
 /// <param name="scheme">The connection string scheme.</param>
 public ClusterSettings(
     Optional <ClusterConnectionMode> connectionMode = default(Optional <ClusterConnectionMode>),
     Optional <IEnumerable <EndPoint> > endPoints    = default(Optional <IEnumerable <EndPoint> >),
     Optional <IReadOnlyDictionary <string, IReadOnlyDictionary <string, object> > > kmsProviders = default(Optional <IReadOnlyDictionary <string, IReadOnlyDictionary <string, object> > >),
     Optional <TimeSpan> localThreshold             = default,
     Optional <int> maxServerSelectionWaitQueueSize = default(Optional <int>),
     Optional <string> replicaSetName              = default(Optional <string>),
     Optional <TimeSpan> serverSelectionTimeout    = default(Optional <TimeSpan>),
     Optional <IServerSelector> preServerSelector  = default(Optional <IServerSelector>),
     Optional <IServerSelector> postServerSelector = default(Optional <IServerSelector>),
     Optional <IReadOnlyDictionary <string, BsonDocument> > schemaMap = default(Optional <IReadOnlyDictionary <string, BsonDocument> >),
     Optional <ConnectionStringScheme> scheme = default(Optional <ConnectionStringScheme>))
 {
     _connectionMode = connectionMode.WithDefault(ClusterConnectionMode.Automatic);
     _endPoints      = Ensure.IsNotNull(endPoints.WithDefault(__defaultEndPoints), "endPoints").ToList();
     _kmsProviders   = kmsProviders.WithDefault(null);
     _localThreshold = Ensure.IsGreaterThanOrEqualToZero(localThreshold.WithDefault(TimeSpan.FromMilliseconds(15)), "localThreshold");
     _maxServerSelectionWaitQueueSize = Ensure.IsGreaterThanOrEqualToZero(maxServerSelectionWaitQueueSize.WithDefault(500), "maxServerSelectionWaitQueueSize");
     _replicaSetName         = replicaSetName.WithDefault(null);
     _serverSelectionTimeout = Ensure.IsGreaterThanOrEqualToZero(serverSelectionTimeout.WithDefault(TimeSpan.FromSeconds(30)), "serverSelectionTimeout");
     _preServerSelector      = preServerSelector.WithDefault(null);
     _postServerSelector     = postServerSelector.WithDefault(null);
     _scheme    = scheme.WithDefault(ConnectionStringScheme.MongoDB);
     _schemaMap = schemaMap.WithDefault(null);
 }
예제 #5
0
 // constructors
 /// <summary>
 /// Initializes a new instance of the <see cref="ReadPreferenceBinding" /> class.
 /// </summary>
 /// <param name="cluster">The cluster.</param>
 /// <param name="readPreference">The read preference.</param>
 /// <param name="session">The session.</param>
 public ReadPreferenceBinding(ICluster cluster, ReadPreference readPreference, ICoreSessionHandle session)
 {
     _cluster        = Ensure.IsNotNull(cluster, nameof(cluster));
     _readPreference = Ensure.IsNotNull(readPreference, nameof(readPreference));
     _session        = Ensure.IsNotNull(session, nameof(session));
     _serverSelector = new ReadPreferenceServerSelector(readPreference);
 }
예제 #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ClusterSelectingServerFailedEvent" /> struct.
 /// </summary>
 /// <param name="clusterDescription">The cluster description.</param>
 /// <param name="serverSelector">The server selector.</param>
 /// <param name="exception">The exception.</param>
 /// <param name="operationId">The operation identifier.</param>
 public ClusterSelectingServerFailedEvent(ClusterDescription clusterDescription, IServerSelector serverSelector, Exception exception, long?operationId)
 {
     _clusterDescription = clusterDescription;
     _serverSelector     = serverSelector;
     _exception          = exception;
     _operationId        = operationId;
 }
예제 #7
0
 public SelectServerHelper(Cluster cluster, IServerSelector selector)
 {
     _cluster   = cluster;
     _selector  = DecorateSelector(selector);
     _stopwatch = Stopwatch.StartNew();
     _timeoutAt = DateTime.UtcNow + _cluster.Settings.ServerSelectionTimeout;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ClusterSelectingServerEvent" /> struct.
 /// </summary>
 /// <param name="clusterDescription">The cluster description.</param>
 /// <param name="serverSelector">The server selector.</param>
 /// <param name="operationId">The operation identifier.</param>
 public ClusterSelectingServerEvent(ClusterDescription clusterDescription, IServerSelector serverSelector, long?operationId)
 {
     _clusterDescription = clusterDescription;
     _serverSelector     = serverSelector;
     _operationId        = operationId;
     _timestamp          = DateTime.UtcNow;
 }
예제 #9
0
        // constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="ClusterSettings"/> class.
        /// </summary>
        /// <param name="connectionMode">The connection mode.</param>
        /// <param name="connectionModeSwitch">The connection mode switch.</param>
        /// <param name="directConnection">The directConnection.</param>
        /// <param name="endPoints">The end points.</param>
        /// <param name="kmsProviders">The kms providers.</param>
        /// <param name="localThreshold">The local threshold.</param>
        /// <param name="maxServerSelectionWaitQueueSize">Maximum size of the server selection wait queue.</param>
        /// <param name="replicaSetName">Name of the replica set.</param>
        /// <param name="serverSelectionTimeout">The server selection timeout.</param>
        /// <param name="preServerSelector">The pre server selector.</param>
        /// <param name="postServerSelector">The post server selector.</param>
        /// <param name="schemaMap">The schema map.</param>
        /// <param name="scheme">The connection string scheme.</param>
        public ClusterSettings(
#pragma warning disable CS0618 // Type or member is obsolete
            Optional <ClusterConnectionMode> connectionMode      = default(Optional <ClusterConnectionMode>),
            Optional <ConnectionModeSwitch> connectionModeSwitch = default,
#pragma warning restore CS0618 // Type or member is obsolete
            Optional <bool?> directConnection            = default,
            Optional <IEnumerable <EndPoint> > endPoints = default(Optional <IEnumerable <EndPoint> >),
            Optional <IReadOnlyDictionary <string, IReadOnlyDictionary <string, object> > > kmsProviders = default(Optional <IReadOnlyDictionary <string, IReadOnlyDictionary <string, object> > >),
            Optional <TimeSpan> localThreshold             = default,
            Optional <int> maxServerSelectionWaitQueueSize = default(Optional <int>),
            Optional <string> replicaSetName              = default(Optional <string>),
            Optional <TimeSpan> serverSelectionTimeout    = default(Optional <TimeSpan>),
            Optional <IServerSelector> preServerSelector  = default(Optional <IServerSelector>),
            Optional <IServerSelector> postServerSelector = default(Optional <IServerSelector>),
            Optional <IReadOnlyDictionary <string, BsonDocument> > schemaMap = default(Optional <IReadOnlyDictionary <string, BsonDocument> >),
            Optional <ConnectionStringScheme> scheme = default(Optional <ConnectionStringScheme>))
        {
#pragma warning disable CS0618 // Type or member is obsolete
            _connectionMode       = connectionMode.WithDefault(ClusterConnectionMode.Automatic);
            _connectionModeSwitch = connectionModeSwitch.WithDefault(ConnectionModeSwitch.NotSet);
#pragma warning restore CS0618 // Type or member is obsolete
            _directConnection = directConnection.WithDefault(null);
            _endPoints        = Ensure.IsNotNull(endPoints.WithDefault(__defaultEndPoints), "endPoints").ToList();
            _kmsProviders     = kmsProviders.WithDefault(null);
            _localThreshold   = Ensure.IsGreaterThanOrEqualToZero(localThreshold.WithDefault(TimeSpan.FromMilliseconds(15)), "localThreshold");
            _maxServerSelectionWaitQueueSize = Ensure.IsGreaterThanOrEqualToZero(maxServerSelectionWaitQueueSize.WithDefault(500), "maxServerSelectionWaitQueueSize");
            _replicaSetName         = replicaSetName.WithDefault(null);
            _serverSelectionTimeout = Ensure.IsGreaterThanOrEqualToZero(serverSelectionTimeout.WithDefault(TimeSpan.FromSeconds(30)), "serverSelectionTimeout");
            _preServerSelector      = preServerSelector.WithDefault(null);
            _postServerSelector     = postServerSelector.WithDefault(null);
            _scheme    = scheme.WithDefault(ConnectionStringScheme.MongoDB);
            _schemaMap = schemaMap.WithDefault(null);

            ClusterConnectionModeHelper.EnsureConnectionModeValuesAreValid(_connectionMode, _connectionModeSwitch, _directConnection);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ClusterSelectingServerFailedEvent" /> struct.
 /// </summary>
 /// <param name="clusterDescription">The cluster description.</param>
 /// <param name="serverSelector">The server selector.</param>
 /// <param name="exception">The exception.</param>
 /// <param name="operationId">The operation identifier.</param>
 public ClusterSelectingServerFailedEvent(ClusterDescription clusterDescription, IServerSelector serverSelector, Exception exception, long? operationId)
 {
     _clusterDescription = clusterDescription;
     _serverSelector = serverSelector;
     _exception = exception;
     _operationId = operationId;
 }
예제 #11
0
 internal static void SetStrategy(string name)
 {
     Sp = ServerSelectorManager.GetSelector(name);
     if (Sp is FixedServerSelector)
     {
         (Sp as FixedServerSelector).SetIndex(MyShadowsocksController.Config.Index);
     }
 }
예제 #12
0
 private void WaitForDescriptionChanged(IServerSelector selector, ClusterDescription description, Task descriptionChangedTask, TimeSpan timeout, CancellationToken cancellationToken)
 {
     using (var helper = new WaitForDescriptionChangedHelper(this, selector, description, descriptionChangedTask, timeout, cancellationToken))
     {
         var index = Task.WaitAny(helper.Tasks);
         helper.HandleCompletedTask(helper.Tasks[index]);
     }
 }
예제 #13
0
        private async Task WaitForDescriptionChangedAsync(IServerSelector selector, ClusterDescription description, Task descriptionChangedTask, TimeSpan timeout, CancellationToken cancellationToken)
        {
            using (var helper = new WaitForDescriptionChangedHelper(this, selector, description, descriptionChangedTask, timeout, cancellationToken))
            {
                var completedTask = await Task.WhenAny(helper.Tasks).ConfigureAwait(false);

                helper.HandleCompletedTask(completedTask);
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ClusterSelectedServerEvent" /> struct.
 /// </summary>
 /// <param name="clusterDescription">The cluster description.</param>
 /// <param name="serverSelector">The server selector.</param>
 /// <param name="selectedServer">The selected server.</param>
 /// <param name="duration">The duration of time it took to select the server.</param>
 /// <param name="operationId">The operation identifier.</param>
 public ClusterSelectedServerEvent(ClusterDescription clusterDescription, IServerSelector serverSelector, ServerDescription selectedServer, TimeSpan duration, long?operationId)
 {
     _clusterDescription = clusterDescription;
     _serverSelector     = serverSelector;
     _selectedServer     = selectedServer;
     _duration           = duration;
     _operationId        = operationId;
     _timestamp          = DateTime.UtcNow;
 }
예제 #15
0
        private string BuildTimeoutExceptionMessage(TimeSpan timeout, IServerSelector selector, ClusterDescription clusterDescription)
        {
            var ms = (int)Math.Round(timeout.TotalMilliseconds);

            return(string.Format(
                       "A timeout occured after {0}ms selecting a server using {1}. Client view of cluster state is {2}.",
                       ms.ToString(),
                       selector.ToString(),
                       clusterDescription.ToString()));
        }
예제 #16
0
 public WaitForDescriptionChangedHelper(Cluster cluster, IServerSelector selector, ClusterDescription description, Task descriptionChangedTask, TimeSpan timeout, CancellationToken cancellationToken)
 {
     _cluster                          = cluster;
     _description                      = description;
     _selector                         = selector;
     _descriptionChangedTask           = descriptionChangedTask;
     _cancellationToken                = cancellationToken;
     _cancellationTaskCompletionSource = new TaskCompletionSource <bool>();
     _cancellationTokenRegistration    = cancellationToken.Register(() => _cancellationTaskCompletionSource.TrySetCanceled());
     _timeoutCancellationTokenSource   = new CancellationTokenSource();
     _timeoutTask                      = Task.Delay(timeout, _timeoutCancellationTokenSource.Token);
 }
예제 #17
0
            public SelectServerHelper(Cluster cluster, IServerSelector selector)
            {
                _cluster = cluster;

                _connectedServers             = new List <IClusterableServer>(_cluster._description?.Servers?.Count ?? 1);
                _connectedServerDescriptions  = new List <ServerDescription>(_connectedServers.Count);
                _operationCountServerSelector = new OperationsCountServerSelector(_connectedServers);

                _selector  = DecorateSelector(selector);
                _stopwatch = Stopwatch.StartNew();
                _timeoutAt = DateTime.UtcNow + _cluster.Settings.ServerSelectionTimeout;
            }
예제 #18
0
 private IServer SelectServerAttempt(Cluster cluster, IServerSelector operationSelector, bool async)
 {
     if (async)
     {
         return(cluster
                .SelectServerAsync(operationSelector, CancellationToken.None)
                .GetAwaiter()
                .GetResult());
     }
     else
     {
         return(cluster.SelectServer(operationSelector, CancellationToken.None));
     }
 }
        public IServer SelectServer(IServerSelector _, CancellationToken cancellationToken)
        {
            ThrowIfDisposed();

            var index = Task.WaitAny(new[] { _serverReadyTaskCompletionSource.Task }, (int)_settings.ServerSelectionTimeout.TotalMilliseconds, cancellationToken);

            if (index != 0)
            {
                cancellationToken.ThrowIfCancellationRequested();
                throw CreateTimeoutException(_description); // _description will contain dnsException
            }

            return(_server ??
                   throw new InvalidOperationException("The server must be created before usage.")); // should not be reached
        }
        public async Task <IServer> SelectServerAsync(IServerSelector _, CancellationToken cancellationToken)
        {
            ThrowIfDisposed();

            var timeoutTask   = Task.Delay(_settings.ServerSelectionTimeout, cancellationToken);
            var triggeredTask = await Task.WhenAny(_serverReadyTaskCompletionSource.Task, timeoutTask).ConfigureAwait(false);

            if (triggeredTask == timeoutTask)
            {
                cancellationToken.ThrowIfCancellationRequested();
                throw CreateTimeoutException(_description); // _description will contain dnsException
            }

            return(_server ??
                   throw new InvalidOperationException("The server must be created before usage.")); // should not be reached
        }
 // constructors
 /// <summary>
 /// Initializes a new instance of the <see cref="ClusterSettings"/> class.
 /// </summary>
 /// <param name="connectionMode">The connection mode.</param>
 /// <param name="endPoints">The end points.</param>
 /// <param name="maxServerSelectionWaitQueueSize">Maximum size of the server selection wait queue.</param>
 /// <param name="replicaSetName">Name of the replica set.</param>
 /// <param name="serverSelectionTimeout">The server selection timeout.</param>
 /// <param name="preServerSelector">The pre server selector.</param>
 /// <param name="postServerSelector">The post server selector.</param>
 public ClusterSettings(
     Optional<ClusterConnectionMode> connectionMode = default(Optional<ClusterConnectionMode>),
     Optional<IEnumerable<EndPoint>> endPoints = default(Optional<IEnumerable<EndPoint>>),
     Optional<int> maxServerSelectionWaitQueueSize = default(Optional<int>),
     Optional<string> replicaSetName = default(Optional<string>),
     Optional<TimeSpan> serverSelectionTimeout = default(Optional<TimeSpan>),
     Optional<IServerSelector> preServerSelector = default(Optional<IServerSelector>),
     Optional<IServerSelector> postServerSelector = default(Optional<IServerSelector>))
 {
     _connectionMode = connectionMode.WithDefault(ClusterConnectionMode.Automatic);
     _endPoints = Ensure.IsNotNull(endPoints.WithDefault(__defaultEndPoints), "endPoints").ToList();
     _maxServerSelectionWaitQueueSize = Ensure.IsGreaterThanOrEqualToZero(maxServerSelectionWaitQueueSize.WithDefault(500), "maxServerSelectionWaitQueueSize");
     _replicaSetName = replicaSetName.WithDefault(null);
     _serverSelectionTimeout = Ensure.IsGreaterThanOrEqualToZero(serverSelectionTimeout.WithDefault(TimeSpan.FromSeconds(30)), "serverSelectionTimeout");
     _preServerSelector = preServerSelector.WithDefault(null);
     _postServerSelector = postServerSelector.WithDefault(null);
 }
예제 #22
0
 // constructors
 public ClusterSettings(
     Optional <ClusterConnectionMode> connectionMode = default(Optional <ClusterConnectionMode>),
     Optional <IEnumerable <EndPoint> > endPoints    = default(Optional <IEnumerable <EndPoint> >),
     Optional <int> maxServerSelectionWaitQueueSize  = default(Optional <int>),
     Optional <string> replicaSetName              = default(Optional <string>),
     Optional <TimeSpan> serverSelectionTimeout    = default(Optional <TimeSpan>),
     Optional <IServerSelector> preServerSelector  = default(Optional <IServerSelector>),
     Optional <IServerSelector> postServerSelector = default(Optional <IServerSelector>))
 {
     _connectionMode = connectionMode.WithDefault(ClusterConnectionMode.Automatic);
     _endPoints      = Ensure.IsNotNull(endPoints.WithDefault(__defaultEndPoints), "endPoints").ToList();
     _maxServerSelectionWaitQueueSize = Ensure.IsGreaterThanOrEqualToZero(maxServerSelectionWaitQueueSize.WithDefault(500), "maxServerSelectionWaitQueueSize");
     _replicaSetName         = replicaSetName.WithDefault(null);
     _serverSelectionTimeout = Ensure.IsInfiniteOrGreaterThanOrEqualToZero(serverSelectionTimeout.WithDefault(TimeSpan.FromSeconds(30)), "serverSelectionTimeout");
     _preServerSelector      = preServerSelector.WithDefault(null);
     _postServerSelector     = postServerSelector.WithDefault(null);
 }
예제 #23
0
        public async Task <IServer> SelectServerAsync(IServerSelector selector, TimeSpan timeout, CancellationToken cancellationToken)
        {
            ThrowIfDisposedOrNotOpen();
            Ensure.IsNotNull(selector, "selector");
            var slidingTimeout = new SlidingTimeout(timeout);

            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                Task descriptionChangedTask;
                ClusterDescription description;
                lock (_descriptionLock)
                {
                    descriptionChangedTask = _descriptionChangedTaskCompletionSource.Task;
                    description            = _description;
                }

                ThrowIfIncompatible(description);

                var connectedServers = description.Servers.Where(s => s.State == ServerState.Connected);
                var selectedServers  = selector.SelectServers(description, connectedServers).ToList();

                while (selectedServers.Count > 0)
                {
                    var server = selectedServers.Count == 1 ?
                                 selectedServers[0] :
                                 __randomServerSelector.SelectServers(description, selectedServers).Single();

                    IClusterableServer selectedServer;
                    if (TryGetServer(server.EndPoint, out selectedServer))
                    {
                        return(selectedServer);
                    }

                    selectedServers.Remove(server);
                }

                Invalidate();

                await descriptionChangedTask.WithTimeout(slidingTimeout, cancellationToken);
            }
        }
        public static IServer SelectServerAndPinIfNeeded(
            this ICluster cluster,
            ICoreSessionHandle session,
            IServerSelector selector,
            CancellationToken cancellationToken)
        {
            var pinnedServer = GetPinnedServerIfValid(cluster, session);

            if (pinnedServer != null)
            {
                return(pinnedServer);
            }

            // Server selection also updates the cluster type, allowing us to to determine if the server
            // should be pinned.
            var server = cluster.SelectServer(selector, cancellationToken);

            PinServerIfNeeded(cluster, session, server);
            return(server);
        }
예제 #25
0
            private IServerSelector DecorateSelector(IServerSelector selector)
            {
                var settings     = _cluster.Settings;
                var allSelectors = new List <IServerSelector>();

                if (settings.PreServerSelector != null)
                {
                    allSelectors.Add(settings.PreServerSelector);
                }

                allSelectors.Add(selector);

                if (settings.PostServerSelector != null)
                {
                    allSelectors.Add(settings.PostServerSelector);
                }

                allSelectors.Add(_cluster._latencyLimitingServerSelector);

                return(new CompositeServerSelector(allSelectors));
            }
예제 #26
0
 public RedisGroup(string groupName, int poolSize, RedisSettings[] settings, IServerSelector selector = null) : this()
 {
     GroupName = groupName;
     PoolSize  = poolSize;
     foreach (var setting in settings)
     {
         if (setting.Master)
         {
             MasterSettings.Add(setting);
         }
         else
         {
             SlaveSettings.Add(setting);
         }
     }
     if (SlaveSettings.Count == 0)
     {
         SlaveSettings = MasterSettings;
     }
     _serverSelector = selector ?? new SimpleHashingSelector();
 }
예제 #27
0
        private IDisposable RequestStart(IServerSelector serverSelector, ReadPreference readPreference)
        {
            var request = __threadStaticRequest;

            if (request != null)
            {
                var selected = serverSelector.SelectServers(_cluster.Description, new[] { request.ServerDescription }).ToList();
                if (selected.Count == 0)
                {
                    throw new InvalidOperationException("A nested call to RequestStart was made that is not compatible with the existing request.");
                }
                request.NestingLevel++;
                return(new RequestStartResult(this));
            }

            IReadBindingHandle channelBinding;
            ConnectionId       connectionId;
            var server = _cluster.SelectServer(serverSelector, CancellationToken.None);

            using (var channel = server.GetChannel(CancellationToken.None))
            {
                if (readPreference.ReadPreferenceMode == ReadPreferenceMode.Primary)
                {
                    channelBinding = new ReadWriteBindingHandle(new ChannelReadWriteBinding(server, channel.Fork(), NoCoreSession.NewHandle()));
                }
                else
                {
                    channelBinding = new ReadBindingHandle(new ChannelReadBinding(server, channel.Fork(), readPreference, NoCoreSession.NewHandle()));
                }
                connectionId = channel.ConnectionDescription.ConnectionId;
            }

            var serverDescription = server.Description;
            var serverInstance    = _serverInstances.Single(i => EndPointHelper.Equals(i.EndPoint, serverDescription.EndPoint));
            var session           = _operationExecutor.StartImplicitSession(CancellationToken.None);

            __threadStaticRequest = new Request(serverDescription, serverInstance, channelBinding, connectionId, session);

            return(new RequestStartResult(this));
        }
예제 #28
0
        private IDisposable RequestStart(IServerSelector serverSelector, ReadPreference readPreference)
        {
            var request = __threadStaticRequest;

            if (request != null)
            {
                var selected = serverSelector.SelectServers(_cluster.Description, new[] { request.ServerDescription }).ToList();
                if (selected.Count == 0)
                {
                    throw new InvalidOperationException("A nested call to RequestStart was made that is not compatible with the existing request.");
                }
                request.NestingLevel++;
                return(new RequestStartResult(this));
            }

            IReadBindingHandle connectionBinding;
            var server = _cluster.SelectServer(serverSelector);

            using (var connection = server.GetConnection())
            {
                if (readPreference.ReadPreferenceMode == ReadPreferenceMode.Primary)
                {
                    connectionBinding = new ReadWriteBindingHandle(new ConnectionReadWriteBinding(server, connection.Fork()));
                }
                else
                {
                    connectionBinding = new ReadBindingHandle(new ConnectionReadBinding(server, connection.Fork(), readPreference));
                }
            }

            var serverDescription = server.Description;
            var endPoint          = (DnsEndPoint)serverDescription.EndPoint;
            var serverAddress     = new MongoServerAddress(endPoint.Host, endPoint.Port);
            var serverInstance    = _serverInstances.Single(i => i.Address == serverAddress);

            __threadStaticRequest = new Request(serverDescription, serverInstance, connectionBinding);

            return(new RequestStartResult(this));
        }
예제 #29
0
        private async Task WaitForDescriptionChangedAsync(IServerSelector selector, ClusterDescription description, Task descriptionChangedTask, TimeSpan timeout, CancellationToken cancellationToken)
        {
            var cancellationTaskCompletionSource = new TaskCompletionSource <bool>();

            using (cancellationToken.Register(() => cancellationTaskCompletionSource.TrySetCanceled()))
                using (var timeoutCancellationTokenSource = new CancellationTokenSource())
                {
                    var timeoutTask   = Task.Delay(timeout, timeoutCancellationTokenSource.Token);
                    var completedTask = await Task.WhenAny(descriptionChangedTask, timeoutTask, cancellationTaskCompletionSource.Task).ConfigureAwait(false);

                    if (completedTask == timeoutTask)
                    {
                        ThrowTimeoutException(selector, description);
                    }
                    timeoutCancellationTokenSource.Cancel();

                    if (completedTask == cancellationTaskCompletionSource.Task)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                    }

                    await descriptionChangedTask.ConfigureAwait(false); // propagate exceptions
                }
        }
예제 #30
0
        public async Task <IServer> SelectServerAsync(IServerSelector selector, CancellationToken cancellationToken)
        {
            ThrowIfDisposedOrNotOpen();
            Ensure.IsNotNull(selector, "selector");

            var timeoutAt = DateTime.UtcNow + _settings.ServerSelectionTimeout;

            var serverSelectionWaitQueueEntered = false;

            if (_settings.PreServerSelector != null || _settings.PostServerSelector != null)
            {
                var allSelectors = new List <IServerSelector>();
                if (_settings.PreServerSelector != null)
                {
                    allSelectors.Add(_settings.PreServerSelector);
                }

                allSelectors.Add(selector);

                if (_settings.PostServerSelector != null)
                {
                    allSelectors.Add(_settings.PostServerSelector);
                }

                selector = new CompositeServerSelector(allSelectors);
            }

            ClusterDescription description = null;

            try
            {
                var stopwatch = Stopwatch.StartNew();
                while (true)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    Task descriptionChangedTask;
                    lock (_descriptionLock)
                    {
                        descriptionChangedTask = _descriptionChangedTaskCompletionSource.Task;
                        description            = _description;
                    }

                    if (!serverSelectionWaitQueueEntered && _selectingServerEventHandler != null)
                    {
                        // this is our first time through...
                        _selectingServerEventHandler(new ClusterSelectingServerEvent(
                                                         description,
                                                         selector));
                    }

                    ThrowIfIncompatible(description);

                    var connectedServers = description.Servers.Where(s => s.State == ServerState.Connected);
                    var selectedServers  = selector.SelectServers(description, connectedServers).ToList();

                    while (selectedServers.Count > 0)
                    {
                        var server = selectedServers.Count == 1 ?
                                     selectedServers[0] :
                                     __randomServerSelector.SelectServers(description, selectedServers).Single();

                        IClusterableServer selectedServer;
                        if (TryGetServer(server.EndPoint, out selectedServer))
                        {
                            stopwatch.Stop();
                            if (_selectedServerEventHandler != null)
                            {
                                _selectedServerEventHandler(new ClusterSelectedServerEvent(
                                                                description,
                                                                selector,
                                                                server,
                                                                stopwatch.Elapsed));
                            }
                            return(selectedServer);
                        }

                        selectedServers.Remove(server);
                    }

                    if (!serverSelectionWaitQueueEntered)
                    {
                        EnterServerSelectionWaitQueue();
                        serverSelectionWaitQueueEntered = true;
                    }

                    var timeoutRemaining = timeoutAt - DateTime.UtcNow;
                    if (timeoutRemaining <= TimeSpan.Zero)
                    {
                        ThrowTimeoutException(selector, description);
                    }

                    await WaitForDescriptionChangedAsync(selector, description, descriptionChangedTask, timeoutRemaining, cancellationToken).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                if (_selectingServerFailedEventHandler != null)
                {
                    _selectingServerFailedEventHandler(new ClusterSelectingServerFailedEvent(
                                                           description,
                                                           selector,
                                                           ex));
                }
                throw;
            }
            finally
            {
                if (serverSelectionWaitQueueEntered)
                {
                    ExitServerSelectionWaitQueue();
                }
            }
        }
예제 #31
0
 public SelectServerHelper(Cluster cluster, IServerSelector selector)
 {
     _cluster = cluster;
     _selector = DecorateSelector(selector);
     _stopwatch = Stopwatch.StartNew();
     _timeoutAt = DateTime.UtcNow + _cluster.Settings.ServerSelectionTimeout;
 }
 // static methods
 public static IServer SelectServer(this ICluster cluster, IServerSelector selector = null, CancellationToken cancellationToken = default(CancellationToken))
 {
     Ensure.IsNotNull(cluster, "cluster");
     return cluster.SelectServerAsync(selector, cancellationToken).GetAwaiter().GetResult();
 }
 // constructors
 /// <summary>
 /// Initializes a new instance of the <see cref="ReadPreferenceBinding"/> class.
 /// </summary>
 /// <param name="cluster">The cluster.</param>
 /// <param name="readPreference">The read preference.</param>
 public ReadPreferenceBinding(ICluster cluster, ReadPreference readPreference)
 {
     _cluster = Ensure.IsNotNull(cluster, "cluster");
     _readPreference = Ensure.IsNotNull(readPreference, "readPreference");
     _serverSelector = new ReadPreferenceServerSelector(readPreference);
 }
예제 #34
0
 public Task<IServer> SelectServerAsync(IServerSelector selector, CancellationToken cancellationToken)
 {
     throw new NotImplementedException();
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ClusterSelectingServerEvent" /> struct.
 /// </summary>
 /// <param name="clusterDescription">The cluster description.</param>
 /// <param name="serverSelector">The server selector.</param>
 /// <param name="operationId">The operation identifier.</param>
 public ClusterSelectingServerEvent(ClusterDescription clusterDescription, IServerSelector serverSelector, long? operationId)
 {
     _clusterDescription = clusterDescription;
     _serverSelector = serverSelector;
     _operationId = operationId;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ClusterSelectingServerFailedEvent" /> struct.
 /// </summary>
 /// <param name="clusterDescription">The cluster description.</param>
 /// <param name="serverSelector">The server selector.</param>
 /// <param name="exception">The exception.</param>
 public ClusterSelectingServerFailedEvent(ClusterDescription clusterDescription, IServerSelector serverSelector, Exception exception)
 {
     _clusterDescription = clusterDescription;
     _serverSelector = serverSelector;
     _exception = exception;
 }
예제 #37
0
        private void ThrowTimeoutException(IServerSelector selector, ClusterDescription description)
        {
            var message = BuildTimeoutExceptionMessage(_settings.ServerSelectionTimeout, selector, description);

            throw new TimeoutException(message);
        }
예제 #38
0
 private void WaitForDescriptionChanged(IServerSelector selector, ClusterDescription description, Task descriptionChangedTask, TimeSpan timeout, CancellationToken cancellationToken)
 {
     using (var helper = new WaitForDescriptionChangedHelper(this, selector, description, descriptionChangedTask, timeout, cancellationToken))
     {
         var index = Task.WaitAny(helper.Tasks);
         helper.HandleCompletedTask(helper.Tasks[index]);
     }
 }
예제 #39
0
 public IServer SelectServer(IServerSelector selector, CancellationToken cancellationToken)
 {
     throw new NotImplementedException();
 }
예제 #40
0
 public RedisGroup(string groupName, RedisSettings[] settings, IServerSelector selector = null)
 {
     this.GroupName      = groupName;
     this.Settings       = settings;
     this.serverSelector = selector ?? new SimpleHashingSelector();
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ClusterSelectingServerEvent" /> struct.
 /// </summary>
 /// <param name="clusterDescription">The cluster description.</param>
 /// <param name="serverSelector">The server selector.</param>
 public ClusterSelectingServerEvent(ClusterDescription clusterDescription, IServerSelector serverSelector)
 {
     _clusterDescription = clusterDescription;
     _serverSelector = serverSelector;
 }
예제 #42
0
        public async Task<IServer> SelectServerAsync(IServerSelector selector, CancellationToken cancellationToken)
        {
            ThrowIfDisposedOrNotOpen();
            Ensure.IsNotNull(selector, "selector");

            var timeoutAt = DateTime.UtcNow + _settings.ServerSelectionTimeout;

            var serverSelectionWaitQueueEntered = false;

            if (_settings.PreServerSelector != null || _settings.PostServerSelector != null)
            {
                var allSelectors = new List<IServerSelector>();
                if (_settings.PreServerSelector != null)
                {
                    allSelectors.Add(_settings.PreServerSelector);
                }

                allSelectors.Add(selector);

                if (_settings.PostServerSelector != null)
                {
                    allSelectors.Add(_settings.PostServerSelector);
                }

                selector = new CompositeServerSelector(allSelectors);
            }

            ClusterDescription description = null;
            try
            {
                var stopwatch = Stopwatch.StartNew();
                while (true)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    Task descriptionChangedTask;
                    lock (_descriptionLock)
                    {
                        descriptionChangedTask = _descriptionChangedTaskCompletionSource.Task;
                        description = _description;
                    }

                    if (!serverSelectionWaitQueueEntered && _selectingServerEventHandler != null)
                    {
                        // this is our first time through...
                        _selectingServerEventHandler(new ClusterSelectingServerEvent(
                            description,
                            selector));
                    }

                    ThrowIfIncompatible(description);

                    var connectedServers = description.Servers.Where(s => s.State == ServerState.Connected);
                    var selectedServers = selector.SelectServers(description, connectedServers).ToList();

                    while (selectedServers.Count > 0)
                    {
                        var server = selectedServers.Count == 1 ?
                            selectedServers[0] :
                            __randomServerSelector.SelectServers(description, selectedServers).Single();

                        IClusterableServer selectedServer;
                        if (TryGetServer(server.EndPoint, out selectedServer))
                        {
                            stopwatch.Stop();
                            if (_selectedServerEventHandler != null)
                            {
                                _selectedServerEventHandler(new ClusterSelectedServerEvent(
                                    description,
                                    selector,
                                    server,
                                    stopwatch.Elapsed));
                            }
                            return selectedServer;
                        }

                        selectedServers.Remove(server);
                    }

                    if (!serverSelectionWaitQueueEntered)
                    {
                        EnterServerSelectionWaitQueue();
                        serverSelectionWaitQueueEntered = true;
                    }

                    var timeoutRemaining = timeoutAt - DateTime.UtcNow;
                    if (timeoutRemaining <= TimeSpan.Zero)
                    {
                        ThrowTimeoutException(selector, description);
                    }

                    await WaitForDescriptionChangedAsync(selector, description, descriptionChangedTask, timeoutRemaining, cancellationToken).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                if (_selectingServerFailedEventHandler != null)
                {
                    _selectingServerFailedEventHandler(new ClusterSelectingServerFailedEvent(
                        description,
                        selector,
                        ex));
                }
                throw;
            }
            finally
            {
                if (serverSelectionWaitQueueEntered)
                {
                    ExitServerSelectionWaitQueue();
                }
            }
        }
        public async Task PoolClearedError_write_retryablity_test([Values(false, true)] bool async)
        {
            RequireServer.Check()
            .Supports(Feature.FailPointsBlockConnection)
            .ClusterTypes(ClusterType.ReplicaSet, ClusterType.Sharded);

            var heartbeatInterval = TimeSpan.FromMilliseconds(50);
            var eventsWaitTimeout = TimeSpan.FromMilliseconds(5000);

            var failPointCommand = BsonDocument.Parse(
                $@"{{
                    configureFailPoint : 'failCommand',
                    mode : {{ 'times' : 1 }},
                    data :
                    {{
                        failCommands : [ 'insert' ],
                        errorCode : 91,
                        blockConnection: true,
                        blockTimeMS: 1000,
                        errorLabels: [""RetryableWriteError""]
                    }}
                }}");

            IServerSelector failPointSelector = WritableServerSelector.Instance;
            var             settings          = DriverTestConfiguration.GetClientSettings();

            if (CoreTestConfiguration.Cluster.Description.Type == ClusterType.Sharded)
            {
                var serverAddress = settings.Servers.First();
                settings.Servers = new[] { serverAddress };

                // set settings.DirectConnection = true after removing obsolete ConnectionMode
#pragma warning disable CS0618 // Type or member is obsolete
                settings.ConnectionMode = ConnectionMode.Direct;
#pragma warning restore CS0618 // Type or member is obsolete

                failPointSelector = new EndPointServerSelector(new DnsEndPoint(serverAddress.Host, serverAddress.Port));
            }

            settings.MaxConnectionPoolSize = 1;
            settings.RetryWrites           = true;

            var eventCapturer = new EventCapturer()
                                .Capture <ConnectionPoolClearedEvent>()
                                .Capture <ConnectionPoolCheckedOutConnectionEvent>()
                                .Capture <ConnectionPoolCheckingOutConnectionFailedEvent>()
                                .CaptureCommandEvents("insert");

            var failpointServer = DriverTestConfiguration.Client.Cluster.SelectServer(failPointSelector, default);
            using var failPoint = FailPoint.Configure(failpointServer, NoCoreSession.NewHandle(), failPointCommand);

            using var client = CreateClient(settings, eventCapturer, heartbeatInterval);
            var database   = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName);
            var collection = database.GetCollection <BsonDocument>(DriverTestConfiguration.CollectionNamespace.CollectionName);

            eventCapturer.Clear();

            if (async)
            {
                await ThreadingUtilities.ExecuteTasksOnNewThreads(2, async _ =>
                {
                    await collection.InsertOneAsync(new BsonDocument("x", 1));
                });
            }
            else
            {
                ThreadingUtilities.ExecuteOnNewThreads(2, _ =>
                {
                    collection.InsertOne(new BsonDocument("x", 1));
                });
            }

            // wait for 2 CommandSucceededEvent events, meaning that all other events should be received
            eventCapturer.WaitForOrThrowIfTimeout(
                events => events.OfType <CommandSucceededEvent>().Count() == 2,
                eventsWaitTimeout);

            eventCapturer.Events.OfType <CommandStartedEvent>().Count().Should().Be(3);
            eventCapturer.Events.OfType <CommandFailedEvent>().Count().Should().Be(1);
            eventCapturer.Events.OfType <CommandSucceededEvent>().Count().Should().Be(2);
            eventCapturer.Events.OfType <ConnectionPoolClearedEvent>().Count().Should().Be(1);
            eventCapturer.Events.OfType <ConnectionPoolCheckedOutConnectionEvent>().Count().Should().Be(3);
            eventCapturer.Events.OfType <ConnectionPoolCheckingOutConnectionFailedEvent>().Count().Should().Be(1);
        }
예제 #44
0
 private string BuildTimeoutExceptionMessage(TimeSpan timeout, IServerSelector selector, ClusterDescription clusterDescription)
 {
     var ms = (int)Math.Round(timeout.TotalMilliseconds);
     return string.Format(
         "A timeout occured after {0}ms selecting a server using {1}. Client view of cluster state is {2}.",
         ms.ToString(),
         selector.ToString(),
         clusterDescription.ToString());
 }
예제 #45
0
 private async Task WaitForDescriptionChangedAsync(IServerSelector selector, ClusterDescription description, Task descriptionChangedTask, TimeSpan timeout, CancellationToken cancellationToken)
 {
     using (var helper = new WaitForDescriptionChangedHelper(this, selector, description, descriptionChangedTask, timeout, cancellationToken))
     {
         var completedTask  = await Task.WhenAny(helper.Tasks).ConfigureAwait(false);
         helper.HandleCompletedTask(completedTask);
     }
 }
예제 #46
0
        private async Task WaitForDescriptionChangedAsync(IServerSelector selector, ClusterDescription description, Task descriptionChangedTask, TimeSpan timeout, CancellationToken cancellationToken)
        {
            var cancellationTaskCompletionSource = new TaskCompletionSource<bool>();
            using (cancellationToken.Register(() => cancellationTaskCompletionSource.TrySetCanceled()))
            using (var timeoutCancellationTokenSource = new CancellationTokenSource())
            {
                var timeoutTask = Task.Delay(timeout, timeoutCancellationTokenSource.Token);
                var completedTask = await Task.WhenAny(descriptionChangedTask, timeoutTask, cancellationTaskCompletionSource.Task).ConfigureAwait(false);

                if (completedTask == timeoutTask)
                {
                    ThrowTimeoutException(selector, description);
                }
                timeoutCancellationTokenSource.Cancel();

                if (completedTask == cancellationTaskCompletionSource.Task)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                await descriptionChangedTask.ConfigureAwait(false); // propagate exceptions
            }
        }
예제 #47
0
        public async Task<IServer> SelectServerAsync(IServerSelector selector, CancellationToken cancellationToken)
        {
            ThrowIfDisposedOrNotOpen();
            Ensure.IsNotNull(selector, nameof(selector));

            using (var helper = new SelectServerHelper(this, selector))
            {
                try
                {
                    while (true)
                    {
                        var server = helper.SelectServer();
                        if (server != null)
                        {
                            return server;
                        }

                        helper.WaitingForDescriptionToChange();
                        await WaitForDescriptionChangedAsync(helper.Selector, helper.Description, helper.DescriptionChangedTask, helper.TimeoutRemaining, cancellationToken).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    helper.HandleException(ex);
                    throw;
                }
            }
        }
예제 #48
0
 private void ThrowTimeoutException(IServerSelector selector, ClusterDescription description)
 {
     var message = BuildTimeoutExceptionMessage(_settings.ServerSelectionTimeout, selector, description);
     throw new TimeoutException(message);
 }
예제 #49
0
        public async Task<IServer> SelectServerAsync(IServerSelector selector, TimeSpan timeout, CancellationToken cancellationToken)
        {
            ThrowIfDisposedOrNotOpen();
            Ensure.IsNotNull(selector, "selector");
            var slidingTimeout = new SlidingTimeout(timeout);

            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                Task descriptionChangedTask;
                ClusterDescription description;
                lock (_descriptionLock)
                {
                    descriptionChangedTask = _descriptionChangedTaskCompletionSource.Task;
                    description = _description;
                }

                ThrowIfIncompatible(description);

                var connectedServers = description.Servers.Where(s => s.State == ServerState.Connected);
                var selectedServers = selector.SelectServers(description, connectedServers).ToList();

                while (selectedServers.Count > 0)
                {
                    var server = selectedServers.Count == 1 ?
                        selectedServers[0] :
                        __randomServerSelector.SelectServers(description, selectedServers).Single();

                    IClusterableServer selectedServer;
                    if (TryGetServer(server.EndPoint, out selectedServer))
                    {
                        return selectedServer;
                    }

                    selectedServers.Remove(server);
                }

                Invalidate();

                await descriptionChangedTask.WithTimeout(slidingTimeout, cancellationToken);
            }
        }
예제 #50
0
 public  WaitForDescriptionChangedHelper(Cluster cluster, IServerSelector selector, ClusterDescription description, Task descriptionChangedTask , TimeSpan timeout, CancellationToken cancellationToken)
 {
     _cluster = cluster;
     _description = description;
     _selector = selector;
     _descriptionChangedTask = descriptionChangedTask;
     _cancellationToken = cancellationToken;
     _cancellationTaskCompletionSource = new TaskCompletionSource<bool>();
     _cancellationTokenRegistration = cancellationToken.Register(() => _cancellationTaskCompletionSource.TrySetCanceled());
     _timeoutCancellationTokenSource = new CancellationTokenSource();
     _timeoutTask = Task.Delay(timeout, _timeoutCancellationTokenSource.Token);
 }
예제 #51
0
            private IServerSelector DecorateSelector(IServerSelector selector)
            {
                var settings = _cluster.Settings;
                if (settings.PreServerSelector != null || settings.PostServerSelector != null)
                {
                    var allSelectors = new List<IServerSelector>();
                    if (settings.PreServerSelector != null)
                    {
                        allSelectors.Add(settings.PreServerSelector);
                    }

                    allSelectors.Add(selector);

                    if (settings.PostServerSelector != null)
                    {
                        allSelectors.Add(settings.PostServerSelector);
                    }

                    return new CompositeServerSelector(allSelectors);
                }

                return selector;
            }
예제 #52
0
 public RedisGroup(string groupName, RedisSettings[] settings, IServerSelector selector = null)
 {
     this.GroupName = groupName;
     this.Settings = settings;
     this.serverSelector = selector ?? new SimpleHashingSelector();
 }