Пример #1
0
 internal bool AnyOpenConnections(Host host)
 {
     return(_connectedSessions.Any(session => session.HasConnections(host)));
 }
Пример #2
0
        /// <summary>
        /// Create the min amount of connections, if the pool is empty
        /// </summary>
        /// <exception cref="System.Net.Sockets.SocketException" />
        internal Task <Connection[]> MaybeCreateCorePool()
        {
            var coreConnections = _config.GetPoolingOptions(ProtocolVersion).GetCoreConnectionsPerHost(_distance);

            if (!_connections.Any(c => c.IsClosed) && _connections.Count >= coreConnections)
            {
                //Pool has the appropriate size
                return(TaskHelper.ToTask(_connections.ToArray()));
            }
            if (!_poolModificationSemaphore.Wait(0))
            {
                //Couldn't enter semaphore, check if there is a connection available to yield
                var opened = _connections.Where(c => !c.IsClosed).ToArray();
                if (opened.Length > 0)
                {
                    return(TaskHelper.ToTask(opened));
                }
                var alreadyOpening = _openingConnections;
                if (alreadyOpening != null && alreadyOpening.Length > 0)
                {
                    return(Task.Factory.ContinueWhenAny(alreadyOpening, t =>
                    {
                        if (t.Status == TaskStatus.RanToCompletion)
                        {
                            return new[] { t.Result };
                        }
                        if (t.Exception != null)
                        {
                            throw t.Exception.InnerException;
                        }
                        throw new TaskCanceledException("Could not get an opened connection because the Task was cancelled");
                    }, TaskContinuationOptions.ExecuteSynchronously));
                }
                //There isn't a connection available yet, enter semaphore
                _poolModificationSemaphore.Wait();
            }
            //Semaphore entered
            //Remove closed connections from the pool
            var toRemove = _connections.Where(c => c.IsClosed).ToArray();

            foreach (var c in toRemove)
            {
                _connections.Remove(c);
            }
            var opening = new List <Task <Connection> >();

            if (_openingConnections != null)
            {
                opening.AddRange(_openingConnections);
            }
            while (_connections.Count + opening.Count < coreConnections)
            {
                opening.Add(CreateConnection());
            }
            if (opening.Count == 0)
            {
                if (_connections.Count == 0)
                {
                    return(TaskHelper.FromException <Connection[]>(new DriverInternalError("Could not create a connection and no connections found in pool")));
                }
                _poolModificationSemaphore.Release();
                return(TaskHelper.ToTask(_connections.ToArray()));
            }
            var openingArray = opening.ToArray();

            _openingConnections = openingArray;
            //Clean up when all open task finished
            var allCompleted = Task.Factory.ContinueWhenAll(openingArray, tasks =>
            {
                _connections.AddRange(tasks.Where(t => t.Status == TaskStatus.RanToCompletion).Select(t => t.Result).ToArray());
                if (_connections.Count == coreConnections)
                {
                    Logger.Info("{0} connection(s) to host {1} {2} created successfully", coreConnections, _host.Address, _connections.Count < 2 ? "was" : "were");
                    _host.BringUpIfDown();
                }
                _openingConnections  = null;
                var connectionsArray = _connections.ToArray();
                _poolModificationSemaphore.Release();
                if (connectionsArray.Length == 0 && tasks.All(t => t.Status != TaskStatus.RanToCompletion))
                {
                    //Pool could not be created
                    Logger.Info("Connection pool to host {0} could not be created", _host.Address);
                    //There are multiple problems, but we only care about one
                    // ReSharper disable once PossibleNullReferenceException
                    throw tasks.First().Exception.InnerException;
                }
                return(connectionsArray);
            }, TaskContinuationOptions.ExecuteSynchronously);

            //yield the first connection available
            return(Task.Factory.ContinueWhenAny(openingArray, t =>
            {
                if (t.Status == TaskStatus.RanToCompletion)
                {
                    return new[] { t.Result };
                }
                if (t.Exception != null)
                {
                    throw t.Exception.InnerException;
                }
                throw new TaskCanceledException("Could not get an opened connection because the Task was cancelled");
            }, TaskContinuationOptions.ExecuteSynchronously)
                   .ContinueWith(t =>
            {
                if (t.Status != TaskStatus.RanToCompletion)
                {
                    //The first connection failed
                    //Wait for all to complete
                    return allCompleted;
                }
                return TaskHelper.ToTask(t.Result);
            }, TaskContinuationOptions.ExecuteSynchronously).Unwrap());
        }