Exemplo n.º 1
0
 public void CheckHealth(Connection c)
 {
     if (c.TimedOutOperations < _config.SocketOptions.DefunctReadTimeoutThreshold)
     {
         return;
     }
     //We are in the default thread-pool (non-io thread)
     //Defunct: close it and remove it from the pool
     _connections.Remove(c);
     c.Dispose();
 }
Exemplo n.º 2
0
        /// <summary>
        /// Opens one connection.
        /// If a connection is being opened it yields the same task, preventing creation in parallel.
        /// </summary>
        /// <exception cref="SocketException">Throws a SocketException when the connection could not be established with the host</exception>
        /// <exception cref="AuthenticationException" />
        /// <exception cref="UnsupportedProtocolVersionException" />
        private async Task <Connection> CreateOpenConnection(bool foreground)
        {
            var concurrentOpenTcs = Volatile.Read(ref _connectionOpenTcs);

            // Try to exit early (cheap) as there could be another thread creating / finishing creating
            if (concurrentOpenTcs != null)
            {
                // There is another thread opening a new connection
                return(await concurrentOpenTcs.Task.ConfigureAwait(false));
            }
            var tcs = new TaskCompletionSource <Connection>();

            // Try to set the creation task source
            concurrentOpenTcs = Interlocked.CompareExchange(ref _connectionOpenTcs, tcs, null);
            if (concurrentOpenTcs != null)
            {
                // There is another thread opening a new connection
                return(await concurrentOpenTcs.Task.ConfigureAwait(false));
            }
            if (IsClosing)
            {
                return(await FinishOpen(tcs, false, GetNotConnectedException()).ConfigureAwait(false));
            }
            // Before creating, make sure that its still needed
            // This method is the only one that adds new connections
            // But we don't control the removal, use snapshot
            var connectionsSnapshot = _connections.GetSnapshot();

            if (connectionsSnapshot.Length >= _expectedConnectionLength)
            {
                if (connectionsSnapshot.Length == 0)
                {
                    // Avoid race condition while removing
                    return(await FinishOpen(tcs, false, GetNotConnectedException()).ConfigureAwait(false));
                }
                return(await FinishOpen(tcs, true, null, connectionsSnapshot[0]).ConfigureAwait(false));
            }
            if (foreground && !_canCreateForeground)
            {
                // Foreground creation only cares about one connection
                // If its already there, yield it
                connectionsSnapshot = _connections.GetSnapshot();
                if (connectionsSnapshot.Length == 0)
                {
                    // When creating in foreground, it failed
                    return(await FinishOpen(tcs, false, GetNotConnectedException()).ConfigureAwait(false));
                }
                return(await FinishOpen(tcs, false, null, connectionsSnapshot[0]).ConfigureAwait(false));
            }
            Logger.Info("Creating a new connection to {0}", _host.Address);
            Connection c          = null;
            Exception  creationEx = null;

            try
            {
                c = await DoCreateAndOpen().ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                Logger.Info("Connection to {0} could not be created: {1}", _host.Address, ex);
                // Can not await on catch on C# 5...
                creationEx = ex;
            }
            if (creationEx != null)
            {
                return(await FinishOpen(tcs, true, creationEx).ConfigureAwait(false));
            }
            if (IsClosing)
            {
                Logger.Info("Connection to {0} opened successfully but pool #{1} was being closed",
                            _host.Address, GetHashCode());
                c.Dispose();
                return(await FinishOpen(tcs, false, GetNotConnectedException()).ConfigureAwait(false));
            }
            var newLength = _connections.AddNew(c);

            Logger.Info("Connection to {0} opened successfully, pool #{1} length: {2}",
                        _host.Address, GetHashCode(), newLength);
            if (IsClosing)
            {
                // We haven't use a CAS operation, so it's possible that the pool is being closed while adding a new
                // connection, we should remove it.
                Logger.Info("Connection to {0} opened successfully and added to the pool #{1} but it was being closed",
                            _host.Address, GetHashCode());
                _connections.Remove(c);
                c.Dispose();
                return(await FinishOpen(tcs, false, GetNotConnectedException()).ConfigureAwait(false));
            }
            return(await FinishOpen(tcs, true, null, c).ConfigureAwait(false));
        }
Exemplo n.º 3
0
 /// <exception cref="System.Net.Sockets.SocketException">Throws a SocketException when the connection could not be established with the host</exception>
 /// <exception cref="AuthenticationException" />
 /// <exception cref="UnsupportedProtocolVersionException"></exception>
 internal virtual Task<Connection> CreateConnection()
 {
     Logger.Info("Creating a new connection to the host " + _host.Address);
     var c = new Connection(_serializer, _host.Address, _config);
     return c.Open().ContinueWith(t =>
     {
         if (t.Status == TaskStatus.RanToCompletion)
         {
             if (_config.GetPoolingOptions(_serializer.ProtocolVersion).GetHeartBeatInterval() > 0)
             {
                 //Heartbeat is enabled, subscribe for possible exceptions
                 c.OnIdleRequestException += OnIdleRequestException;
             }
             return c;
         }
         Logger.Info("The connection to {0} could not be opened", _host.Address);
         c.Dispose();
         if (t.Exception != null)
         {
             t.Exception.Handle(_ => true);
             Logger.Error(t.Exception.InnerException);
             throw t.Exception.InnerException;
         }
         throw new TaskCanceledException("The connection creation task was cancelled");
     }, TaskContinuationOptions.ExecuteSynchronously);
 }
Exemplo n.º 4
0
 /// <summary>
 /// Closes the connection and removes it from the pool
 /// </summary>
 public void Remove(Connection c)
 {
     OnConnectionClosing(c);
     c.Dispose();
 }