Close() private method

Closes the physical connection to the server.
private Close ( ) : void
return void
        /// <summary>
        /// Put a pooled connector into the pool queue.
        /// </summary>
        /// <param name="Connector">Connector to pool</param>
        private void UngetPooledConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
        {
            ConnectorQueue Queue;

            // Find the queue.
            if (!PooledConnectors.TryGetValue(Connection.ConnectionString, out Queue) || Queue == null)
            {
                return;                 // Queue may be emptied by connection problems. See ClearPool below.
            }

            Connector.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate;
            Connector.CertificateSelectionCallback      -= Connection.CertificateSelectionCallbackDelegate;
            Connector.CertificateValidationCallback     -= Connection.CertificateValidationCallbackDelegate;
            Connector.PrivateKeySelectionCallback       -= Connection.PrivateKeySelectionCallbackDelegate;

            Queue.UseCount--;

            if (!Connector.IsInitialized)
            {
                if (Connector.Transaction != null)
                {
                    Connector.Transaction.Cancel();
                }

                Connector.Close();
            }
            else
            {
                if (Connector.Transaction != null)
                {
                    try
                    {
                        Connector.Transaction.Rollback();
                    }
                    catch
                    {
                        Connector.Close();
                    }
                }
            }

            if (Connector.State == ConnectionState.Open &&
                (Thread.CurrentThread.ThreadState & (ThreadState.Aborted | ThreadState.AbortRequested)) == 0)
            {
                // Release all resources associated with this connector.
                Connector.ReleaseResources();

                Queue.Enqueue(Connector);
            }
        }
        /// <summary>
        /// Put a pooled connector into the pool queue.
        /// </summary>
        /// <param name="Connector">Connector to pool</param>
        private void UngetPooledConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
        {
            ConnectorQueue Queue;

            // Find the queue.
            Queue = (ConnectorQueue)PooledConnectors[Connector.ConnectionString.ToString()];

            if (Queue == null)
            {
                return; // Queue may be emptied by connection problems. See ClearPool below.
            }
            Connector.CertificateSelectionCallback  -= Connection.CertificateSelectionCallbackDelegate;
            Connector.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate;
            Connector.PrivateKeySelectionCallback   -= Connection.PrivateKeySelectionCallbackDelegate;

            Queue.UseCount--;

            if (!Connector.IsInitialized)
            {
                if (Connector.Transaction != null)
                {
                    Connector.Transaction.Cancel();
                }

                Connector.Close();
            }
            else
            {
                if (Connector.Transaction != null)
                {
                    try
                    {
                        Connector.Transaction.Rollback();
                    }
                    catch
                    {
                        Connector.Close()
                        ;
                    }
                }
            }

            if (Connector.State == System.Data.ConnectionState.Open)
            {
                // Release all resources associated with this connector.
                Connector.ReleaseResources();

                Queue.Enqueue(Connector);
            }
        }
示例#3
0
        ///<summary>
        /// This method is responsible to handle all protocol messages sent from the backend.
        /// It holds all the logic to do it.
        /// To exchange data, it uses a Mediator object from which it reads/writes information
        /// to handle backend requests.
        /// </summary>
        ///
        internal IEnumerable <IServerResponseObject> ProcessBackendResponsesEnum(NpgsqlConnector context)
        {
            try
            {
                // Flush buffers to the wire.
                context.Stream.Flush();

                // Process commandTimeout behavior.

                if ((context.Mediator.BackendCommandTimeout > 0) &&
                    (!CheckForContextSocketAvailability(context, SelectMode.SelectRead)))
                {
                    // If timeout occurs when establishing the session with server then
                    // throw an exception instead of trying to cancel query. This helps to prevent loop as
                    // CancelRequest will also try to stablish a connection and sends commands.
                    if (!((this is NpgsqlStartupState || this is NpgsqlConnectedState)))
                    {
                        try
                        {
                            context.CancelRequest();

                            ProcessAndDiscardBackendResponses(context);
                        }
                        catch (Exception)
                        {
                        }
                        // We should have gotten an error from CancelRequest(). Whether we did or not, what we
                        // really have is a timeout exception, and that will be less confusing to the user than
                        // "operation cancelled by user" or similar, so whatever the case, that is what we'll throw.
                        // Changed message again to report about the two possible timeouts: connection or command
                        // as the establishment timeout only was confusing users when the timeout was a command timeout.
                    }

                    throw new NpgsqlException(resman.GetString("Exception_ConnectionOrCommandTimeout"));
                }

                switch (context.BackendProtocolVersion)
                {
                case ProtocolVersion.Version2:
                    return(ProcessBackendResponses_Ver_2(context));

                case ProtocolVersion.Version3:
                    return(ProcessBackendResponses_Ver_3(context));

                default:
                    throw new NpgsqlException(resman.GetString("Exception_UnknownProtocol"));
                }
            }
            catch (ThreadAbortException)
            {
                try
                {
                    context.CancelRequest();
                    context.Close();
                }
                catch {}

                throw;
            }
        }
示例#4
0
        private static void ClearQueue(ConnectorQueue Queue)
        {
            if (Queue == null)
            {
                return;
            }

            lock (Queue)
            {
                while (Queue.Available.Count > 0)
                {
                    NpgsqlConnector connector = Queue.Available.Dequeue();

                    try
                    {
                        connector.Close();
                    }
                    catch
                    {
                        // Maybe we should log something here to say we got an exception while closing connector?
                    }
                }

                //Clear the busy list so that the current connections don't get re-added to the queue
                Queue.Busy.Clear();
            }
        }
示例#5
0
 protected override void Dispose(bool disposing)
 {
     if (!disposing)
     {
         mContext.Close();
         mContext = null;
     }
     base.Dispose(disposing);
 }
        /// <summary>
        /// Close the connector.
        /// </summary>
        /// <param name="Connection"></param>
        /// <param name="Connector">Connector to release</param>
        private static void UngetNonPooledConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
        {
            Connector.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate;

            if (Connector.Transaction != null)
            {
                Connector.Transaction.Cancel();
            }

            Connector.Close();
        }
示例#7
0
        internal void Release(NpgsqlConnector connector)
        {
            // If Clear/ClearAll has been been called since this connector was first opened,
            // throw it away.
            if (connector.ClearCounter < _clearCounter)
            {
                try
                {
                    connector.Close();
                }
                catch (Exception e)
                {
                    Log.Warn("Exception while closing outdated connector", e, connector.Id);
                }

                lock (this)
                    Busy--;
                return;
            }

            if (connector.IsBroken)
            {
                lock (this)
                    Busy--;
                return;
            }

            connector.Reset();
            lock (this)
            {
                // If there are any pending open attempts in progress hand the connector off to
                // them directly.
                while (Waiting.Count > 0)
                {
                    var tcs = Waiting.Dequeue();
                    // Some attempts may be in the queue but in cancelled state, since they've already timed out.
                    // Simply dequeue these and move on.
                    if (tcs.Task.IsCanceled)
                    {
                        continue;
                    }
                    // We have a pending open attempt. "Complete" it, handing off the connector.
                    // We do this in another thread because we don't want to execute the continuation here.
                    Task.Run(() => tcs.SetResult(connector));
                    return;
                }

                Idle.Push(connector);
                Busy--;
                EnsurePruningTimerState();
                Contract.Assert(Idle.Count <= _max);
            }
        }
示例#8
0
        /// <summary>
        /// Close the connector.
        /// </summary>
        /// <param name="Connector">Connector to release</param>
        private void UngetNonPooledConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
        {
            Connector.CertificateSelectionCallback  -= Connection.CertificateSelectionCallbackDelegate;
            Connector.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate;
            Connector.PrivateKeySelectionCallback   -= Connection.PrivateKeySelectionCallbackDelegate;

            if (Connector.Transaction != null)
            {
                Connector.Transaction.Cancel();
            }

            Connector.Close();
        }
示例#9
0
 internal IEnumerable <IServerResponseObject> ProcessExistingBackendResponses(NpgsqlConnector context)
 {
     try
     {
         return(ProcessBackendResponses_Ver_3(context));
     }
     catch (ThreadAbortException)
     {
         try
         {
             context.CancelRequest();
             context.Close();
         }
         catch { }
         throw;
     }
 }
示例#10
0
        void Dispose()
        {
            if (_isDisposed)
            {
                return;
            }
            Debug.Assert(_transaction != null, "No transaction");
            Debug.Assert(_connector != null, "No connector");

            Log.CleaningUpResourceManager(_connector.Id, _txId);
            if (_localTx != null)
            {
                _localTx.Dispose();
                _localTx = null;
            }

            if (_connector.Connection != null)
            {
                _connector.Connection.EnlistedTransaction = null;
            }
            else
            {
                // We're here for connections which were closed before their TransactionScope completes.
                // These need to be closed now.
                if (_connector.Settings.Pooling)
                {
                    ConnectorPool pool;
                    lock (PoolManager.Pools)
                    {
                        var found = PoolManager.Pools.TryGetValue(_connector.ConnectionString, out pool);
                        Debug.Assert(found);
                    }
                    pool.RemovePendingEnlistedConnector(_connector, _transaction);
                    pool.Release(_connector);
                }
                else
                {
                    _connector.Close();
                }
            }

            _connector   = null;
            _transaction = null;
            _isDisposed  = true;
        }
示例#11
0
        private void ClearQueue(ConnectorQueue Queue)
        {
            if (Queue == null)
            {
                return;
            }

            while (Queue.Count > 0)
            {
                NpgsqlConnector connector = (NpgsqlConnector)Queue.Dequeue();

                try
                {
                    connector.Close();
                }
                catch {
                    // Maybe we should log something here to say we got an exception while closing connector?
                }
            }
        }
示例#12
0
#pragma warning disable CS8625
        void Dispose()
        {
            if (_isDisposed)
            {
                return;
            }

            Log.Trace($"Cleaning up resource manager (localid={_txId}", _connector.Id);
            if (_localTx != null)
            {
                _localTx.Dispose();
                _localTx = null;
            }

            if (_connector.Connection != null)
            {
                _connector.Connection.EnlistedTransaction = null;
            }
            else
            {
                // We're here for connections which were closed before their TransactionScope completes.
                // These need to be closed now.
                if (_connector.Settings.Pooling)
                {
                    var found = PoolManager.TryGetValue(_connector.ConnectionString, out var pool);
                    Debug.Assert(found);
                    pool !.TryRemovePendingEnlistedConnector(_connector, _transaction);
                    pool.Return(_connector);
                }
                else
                {
                    _connector.Close();
                }
            }

            _connector   = null !;
            _transaction = null !;
            _isDisposed  = true;
        }
        /// <summary>
        /// Close the connector.
        /// </summary>
        /// <param name="Connection"></param>
        /// <param name="Connector">Connector to release</param>
        private static void UngetNonPooledConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
        {
            Connector.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate;
            Connector.CertificateSelectionCallback -= Connection.CertificateSelectionCallbackDelegate;
            Connector.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate;
            Connector.PrivateKeySelectionCallback -= Connection.PrivateKeySelectionCallbackDelegate;

            if (Connector.Transaction != null)
            {
                Connector.Transaction.Cancel();
            }

            Connector.Close();
        }
示例#14
0
        /// <summary>
        /// Put a pooled connector into the pool queue.
        /// </summary>
        /// <param name="Connector">Connector to pool</param>
        private void UngetPooledConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
        {
            ConnectorQueue queue;

            // Find the queue.
            if (!PooledConnectors.TryGetValue(Connection.ConnectionString, out queue) || queue == null)
            {
                Connector.Close();      // Release connection to postgres
                return;                 // Queue may be emptied by connection problems. See ClearPool below.
            }

            Connector.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate;
            Connector.CertificateSelectionCallback      -= Connection.CertificateSelectionCallbackDelegate;
            Connector.CertificateValidationCallback     -= Connection.CertificateValidationCallbackDelegate;
            Connector.PrivateKeySelectionCallback       -= Connection.PrivateKeySelectionCallbackDelegate;

            bool inQueue = queue.Busy.ContainsKey(Connector);

            queue.Busy.Remove(Connector);

            if (!Connector.IsInitialized)
            {
                if (Connector.Transaction != null)
                {
                    Connector.Transaction.Cancel();
                }

                Connector.Close();
            }
            else
            {
                if (Connector.Transaction != null)
                {
                    try
                    {
                        Connector.Transaction.Rollback();
                    }
                    catch
                    {
                        Connector.Close();
                    }
                }
            }

            if (Connector.State == ConnectionState.Open)
            {
                //If thread is good

                if ((Thread.CurrentThread.ThreadState & (ThreadState.Aborted | ThreadState.AbortRequested)) == 0)

                {
                    // Release all resources associated with this connector.

                    try

                    {
                        Connector.ReleaseResources();
                    }

                    catch (Exception)

                    {
                        //If the connector fails to release its resources then it is probably broken, so make sure we don't add it to the queue.

                        // Usually it already won't be in the queue as it would of broken earlier

                        inQueue = false;
                    }



                    if (inQueue)
                    {
                        queue.Available.Enqueue(Connector);
                    }

                    else
                    {
                        Connector.Close();
                    }
                }

                else

                {
                    //Thread is being aborted, this connection is possibly broken. So kill it rather than returning it to the pool

                    Connector.Close();
                }
            }
        }
示例#15
0
        /// <summary>
        /// Find an available pooled connector in the non-shared pool, or create
        /// a new one if none found.
        /// </summary>
        private NpgsqlConnector GetPooledConnector(NpgsqlConnection Connection)
        {
            ConnectorQueue  Queue;
            NpgsqlConnector Connector = null;

            // Try to find a queue.
            Queue = (ConnectorQueue)PooledConnectors[Connection.ConnectionString.ToString()];

            if (Queue == null)
            {
                Queue = new ConnectorQueue();
                Queue.ConnectionLifeTime = Connection.ConnectionLifeTime;
                Queue.MinPoolSize        = Connection.MinPoolSize;
                PooledConnectors[Connection.ConnectionString.ToString()] = Queue;
            }

            // Fix queue use count. Use count may be dropped below zero if Queue was cleared and there were connections open.
            if (Queue.UseCount < 0)
            {
                Queue.UseCount = 0;
            }


            if (Queue.Count > 0)
            {
                // Found a queue with connectors.  Grab the top one.

                // Check if the connector is still valid.

                Connector = (NpgsqlConnector)Queue.Dequeue();
                Queue.UseCount++;
            }
            else if (Queue.Count + Queue.UseCount < Connection.MaxPoolSize)
            {
                Connector = CreateConnector(Connection);

                Connector.CertificateSelectionCallback  += Connection.CertificateSelectionCallbackDelegate;
                Connector.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate;
                Connector.PrivateKeySelectionCallback   += Connection.PrivateKeySelectionCallbackDelegate;

                try
                {
                    Connector.Open();
                }
                catch {
                    try
                    {
                        Connector.Close();
                    }
                    catch {}

                    throw;
                }


                Queue.UseCount++;
            }

            // Meet the MinPoolSize requirement if needed.
            if (Connection.MinPoolSize > 0)
            {
                while (Queue.Count + Queue.UseCount < Connection.MinPoolSize)
                {
                    NpgsqlConnector Spare = CreateConnector(Connection);

                    Spare.CertificateSelectionCallback  += Connection.CertificateSelectionCallbackDelegate;
                    Spare.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate;
                    Spare.PrivateKeySelectionCallback   += Connection.PrivateKeySelectionCallbackDelegate;

                    Spare.Open();

                    Spare.CertificateSelectionCallback  -= Connection.CertificateSelectionCallbackDelegate;
                    Spare.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate;
                    Spare.PrivateKeySelectionCallback   -= Connection.PrivateKeySelectionCallbackDelegate;

                    Queue.Enqueue(Spare);
                }
            }

            return(Connector);
        }
示例#16
0
        internal void Release(NpgsqlConnector connector)
        {
            // If Clear/ClearAll has been been called since this connector was first opened,
            // throw it away.
            if (connector.ClearCounter < _clearCounter)
            {
                try
                {
                    connector.Close();
                }
                catch (Exception e)
                {
                    Log.Warn("Exception while closing outdated connector", e, connector.Id);
                }

                lock (this)
                    Busy--;
                return;
            }

            if (connector.IsBroken)
            {
                lock (this)
                    Busy--;
                return;
            }

            connector.Reset();
            lock (this)
            {
                // If there are any pending open attempts in progress hand the connector off to
                // them directly.
                while (Waiting.Count > 0)
                {
                    var waitingOpenAttempt = Waiting.Dequeue();
                    var tcs = waitingOpenAttempt.TaskCompletionSource;
                    // Some attempts may be in the queue but in cancelled state, since they've already timed out.
                    // Simply dequeue these and move on.
                    if (tcs.Task.IsCanceled)
                    {
                        continue;
                    }
                    // We have a pending open attempt. "Complete" it, handing off the connector.
                    if (waitingOpenAttempt.IsAsync)
                    {
                        // If the waiting open attempt is asynchronous (i.e. OpenAsync()), we can't simply
                        // call SetResult on its TaskCompletionSource, since it would execute the open's
                        // continuation in our thread (the closing thread). Instead we schedule the completion
                        // to run in the TP
                        Task.Run(() => tcs.SetResult(connector));
                    }
                    else
                    {
                        tcs.SetResult(connector);
                    }
                    return;
                }

                Idle.Push(connector);
                Busy--;
                EnsurePruningTimerState();
                Contract.Assert(Idle.Count <= _max);
            }
        }
示例#17
0
        /*
         *      /// <summary>
         *      /// Find an available shared connector in the shared pool, or create
         *      /// a new one if none found.
         *      /// </summary>
         *      private NpgsqlConnector GetSharedConnector(NpgsqlConnection Connection)
         *      {
         *          // To be implemented
         *
         *          return null;
         *      }
         */

        /// <summary>
        /// Put a pooled connector into the pool queue.
        /// </summary>
        /// <param name="Connection">Connection <paramref name="Connector"/> is leased to.</param>
        /// <param name="Connector">Connector to pool</param>
        private void UngetConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
        {
            ConnectorQueue queue;

            // Find the queue.
            // As we are handling all possible queues, we have to lock everything...
            lock (locker)
            {
                PooledConnectors.TryGetValue(Connection.ConnectionString, out queue);
            }

            if (queue == null)
            {
                Connector.Close(); // Release connection to postgres
                return;            // Queue may be emptied by connection problems. See ClearPool below.
            }

            Connector.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate;
            Connector.CertificateSelectionCallback      -= Connection.CertificateSelectionCallbackDelegate;
            Connector.CertificateValidationCallback     -= Connection.CertificateValidationCallbackDelegate;
            Connector.PrivateKeySelectionCallback       -= Connection.PrivateKeySelectionCallbackDelegate;
            Connector.ValidateRemoteCertificateCallback -= Connection.ValidateRemoteCertificateCallbackDelegate;

            /*bool inQueue = false;
             *
             * lock (queue)
             * {
             *  inQueue = queue.Busy.ContainsKey(Connector);
             *  queue.Busy.Remove(Connector);
             * }
             */

            if (!Connector.IsInitialized)
            {
                if (Connector.Transaction != null)
                {
                    Connector.Transaction.Cancel();
                }

                Connector.Close();
            }
            else
            {
                if (Connector.Transaction != null)
                {
                    try
                    {
                        Connector.Transaction.Rollback();
                    }
                    catch
                    {
                        Connector.Close();
                    }
                }
            }

            bool inQueue = queue.Busy.ContainsKey(Connector);

            if (Connector.State == ConnectionState.Open)
            {
                //If thread is good
                if ((Thread.CurrentThread.ThreadState & (ThreadState.Aborted | ThreadState.AbortRequested)) == 0)
                {
                    // Release all resources associated with this connector.
                    try
                    {
                        Connector.ReleaseResources();
                    }
                    catch (Exception)
                    {
                        //If the connector fails to release its resources then it is probably broken, so make sure we don't add it to the queue.
                        // Usually it already won't be in the queue as it would of broken earlier
                        inQueue = false;
                        Connector.Close();
                    }
                }
                else
                {
                    //Thread is being aborted, this connection is possibly broken. So kill it rather than returning it to the pool
                    inQueue = false;
                    Connector.Close();
                }
            }

            // Check if Connector should return to the queue of available connectors. If not, this connector is invalid and should
            // only be removed from the busy queue which effectvely removes it from the pool.
            if (inQueue)
            {
                lock (queue)
                {
                    queue.Busy.Remove(Connector);
                    queue.Available.Enqueue(Connector);
                }
            }
            else
            {
                lock (queue)
                {
                    queue.Busy.Remove(Connector);
                }
            }
        }
示例#18
0
        /// <summary>
        /// Find an available pooled connector in the non-shared pool, or create
        /// a new one if none found.
        /// </summary>
        private NpgsqlConnector GetPooledConnector(NpgsqlConnection Connection)
        {
            ConnectorQueue  Queue;
            NpgsqlConnector Connector = null;

            // Try to find a queue.
            if (!PooledConnectors.TryGetValue(Connection.ConnectionString, out Queue))
            {
                Queue = new ConnectorQueue();
                Queue.ConnectionLifeTime = Connection.ConnectionLifeTime;
                Queue.MinPoolSize        = Connection.MinPoolSize;
                PooledConnectors[Connection.ConnectionString] = Queue;
            }

            if (Queue.Available.Count > 0)
            {
                // Found a queue with connectors.  Grab the top one.

                // Check if the connector is still valid.

                Connector = Queue.Available.Dequeue();
                if (!Connector.IsValid())
                {
                    Connector.Close();

                    return(GetPooledConnector(Connection));                    //Try again
                }
                Queue.Busy.Add(Connector, null);
            }
            else if (Queue.Available.Count + Queue.Busy.Count < Connection.MaxPoolSize)
            {
                Connector = CreateConnector(Connection);

                Connector.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate;
                Connector.CertificateSelectionCallback      += Connection.CertificateSelectionCallbackDelegate;
                Connector.CertificateValidationCallback     += Connection.CertificateValidationCallbackDelegate;
                Connector.PrivateKeySelectionCallback       += Connection.PrivateKeySelectionCallbackDelegate;

                try
                {
                    Connector.Open();
                }
                catch
                {
                    Connector.Close();

                    throw;
                }


                Queue.Busy.Add(Connector, null);
            }

            // Meet the MinPoolSize requirement if needed.
            if (Connection.MinPoolSize > 0)
            {
                while (Queue.Available.Count + Queue.Busy.Count < Connection.MinPoolSize)
                {
                    NpgsqlConnector Spare = CreateConnector(Connection);

                    Spare.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate;
                    Spare.CertificateSelectionCallback      += Connection.CertificateSelectionCallbackDelegate;
                    Spare.CertificateValidationCallback     += Connection.CertificateValidationCallbackDelegate;
                    Spare.PrivateKeySelectionCallback       += Connection.PrivateKeySelectionCallbackDelegate;

                    Spare.Open();

                    Spare.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate;
                    Spare.CertificateSelectionCallback      -= Connection.CertificateSelectionCallbackDelegate;
                    Spare.CertificateValidationCallback     -= Connection.CertificateValidationCallbackDelegate;
                    Spare.PrivateKeySelectionCallback       -= Connection.PrivateKeySelectionCallbackDelegate;

                    Queue.Available.Enqueue(Spare);
                }
            }

            return(Connector);
        }
示例#19
0
        /// <summary>
        /// Releases a connector, possibly back to the pool for future use.
        /// </summary>
        /// <remarks>
        /// Pooled connectors will be put back into the pool if there is room.
        /// </remarks>
        /// <param name="connection">Connection to which the connector is leased.</param>
        /// <param name="connector">The connector to release.</param>
        internal void ReleaseConnector(NpgsqlConnection connection, NpgsqlConnector connector)
        {
            Contract.Requires(connector.IsReady || connector.IsClosed || connector.IsBroken);

            ConnectorQueue queue;

            // Find the queue.
            // As we are handling all possible queues, we have to lock everything...
            lock (locker)
            {
                PooledConnectors.TryGetValue(connection.ConnectionString, out queue);
            }

            if (queue == null)
            {
                connector.Close(); // Release connection to postgres
                return;            // Queue may be emptied by connection problems. See ClearPool below.
            }

            /*bool inQueue = false;
             *
             * lock (queue)
             * {
             *  inQueue = queue.Busy.ContainsKey(Connector);
             *  queue.Busy.Remove(Connector);
             * }
             */

            bool inQueue = queue.Busy.ContainsKey(connector);

            if (connector.IsBroken || connector.IsClosed)
            {
                if (connector.InTransaction)
                {
                    connector.ClearTransaction();
                }

                connector.Close();
                inQueue = false;
            }
            else
            {
                Contract.Assert(connector.IsReady);

                //If thread is good
                if ((Thread.CurrentThread.ThreadState & (ThreadState.Aborted | ThreadState.AbortRequested)) == 0)
                {
                    // Release all resources associated with this connector.
                    try {
                        connector.Reset();
                    } catch {
                        connector.Close();
                        inQueue = false;
                    }
                }
                else
                {
                    //Thread is being aborted, this connection is possibly broken. So kill it rather than returning it to the pool
                    inQueue = false;
                    connector.Close();
                }
            }

            // Check if Connector should return to the queue of available connectors. If not, this connector is invalid and should
            // only be removed from the busy queue which effectvely removes it from the pool.
            if (inQueue)
            {
                lock (queue)
                {
                    queue.Busy.Remove(connector);
                    queue.Available.Enqueue(connector);
                }
            }
            else
            {
                lock (queue)
                {
                    queue.Busy.Remove(connector);
                }
            }

            connector.ProvideClientCertificatesCallback = null;
            connector.UserCertificateValidationCallback = null;
        }
示例#20
0
        /// <summary>
        /// Put a pooled connector into the pool queue.
        /// </summary>
        /// <param name="Connector">Connector to pool</param>
        private void UngetPooledConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
        {
            ConnectorQueue           Queue;

            // Find the queue.
            Queue = (ConnectorQueue)PooledConnectors[Connector.ConnectionString.ToString()];

            if (Queue == null)
                return;  // Queue may be emptied by connection problems. See ClearPool below.

            Connector.CertificateSelectionCallback -= Connection.CertificateSelectionCallbackDelegate;
            Connector.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate;
            Connector.PrivateKeySelectionCallback -= Connection.PrivateKeySelectionCallbackDelegate;

            Queue.UseCount--;

            if (! Connector.IsInitialized)
            {
                if (Connector.Transaction != null)
                {
                    Connector.Transaction.Cancel();
                }

                Connector.Close();
            }
            else
            {
                if (Connector.Transaction != null)
                {
                    try
                    {
                        Connector.Transaction.Rollback();
                    }
                    catch {
                        Connector.Close()
                        ;
                    }
                }
        }

        if (Connector.State == System.Data.ConnectionState.Open)
            {
                // Release all resources associated with this connector.
                Connector.ReleaseResources();

                Queue.Enqueue(Connector);
            }
        }
示例#21
0
        ///<summary>
        /// This method is responsible to handle all protocol messages sent from the backend.
        /// It holds all the logic to do it.
        /// To exchange data, it uses a Mediator object from which it reads/writes information
        /// to handle backend requests.
        /// </summary>
        ///
        internal IEnumerable<IServerResponseObject> ProcessBackendResponsesEnum(NpgsqlConnector context)
        {
            try
            {
            // Process commandTimeout behavior.

            if ((context.Mediator.CommandTimeout > 0) &&
                (!context.Socket.Poll(1000000*context.Mediator.CommandTimeout, SelectMode.SelectRead)))
            {
                // If timeout occurs when establishing the session with server then
                // throw an exception instead of trying to cancel query. This helps to prevent loop as CancelRequest will also try to stablish a connection and sends commands.
                if (!((this is NpgsqlStartupState || this is NpgsqlConnectedState || context.CancelRequestCalled)))
                {
                    try
                    {
                        context.CancelRequest();
                        foreach (IServerResponseObject obj in ProcessBackendResponsesEnum(context))
                        {
                            if (obj is IDisposable)
                            {
                                (obj as IDisposable).Dispose();
                            }
                        }
                    }
                    catch(Exception ex)
                    {
                    }
                    //We should have gotten an error from CancelRequest(). Whether we did or not, what we
                    //really have is a timeout exception, and that will be less confusing to the user than
                    //"operation cancelled by user" or similar, so whatever the case, that is what we'll throw.
                    // Changed message again to report about the two possible timeouts: connection or command as the establishment timeout only was confusing users when the timeout was a command timeout.
                }
                throw new NpgsqlException(resman.GetString("Exception_ConnectionOrCommandTimeout"));
            }
            switch (context.BackendProtocolVersion)
            {
                case ProtocolVersion.Version2:
                    return ProcessBackendResponses_Ver_2(context);
                case ProtocolVersion.Version3:
                    return ProcessBackendResponses_Ver_3(context);
                default:
                    throw new NpgsqlException(resman.GetString("Exception_UnknownProtocol"));
            }

            }

            catch(ThreadAbortException)
            {
                try
                {
                    context.CancelRequest();
                    context.Close();
                }
                catch {}

                throw;
            }
        }
        /// <summary>
        /// Find an available pooled connector in the non-shared pool, or create
        /// a new one if none found.
        /// </summary>
        private NpgsqlConnector GetPooledConnector(NpgsqlConnection Connection)
        {
            ConnectorQueue  Queue;
            NpgsqlConnector Connector = null;

            // Try to find a queue.
            if (!PooledConnectors.TryGetValue(Connection.ConnectionString, out Queue))
            {
                Queue = new ConnectorQueue();
                Queue.ConnectionLifeTime = Connection.ConnectionLifeTime;
                Queue.MinPoolSize        = Connection.MinPoolSize;
                PooledConnectors[Connection.ConnectionString] = Queue;
            }

            // Fix queue use count. Use count may be dropped below zero if Queue was cleared and there were connections open.
            if (Queue.UseCount < 0)
            {
                Queue.UseCount = 0;
            }


            if (Queue.Count > 0)
            {
                // Found a queue with connectors.  Grab the top one.

                // Check if the connector is still valid.

                Connector = Queue.Dequeue();

                /*try
                 * {
                 *      Connector.TestConnector();
                 *      Connector.RequireReadyForQuery = true;
                 * }
                 * catch //This connector is broken!
                 * {
                 *      try
                 *      {
                 *              Connector.Close();
                 *      }
                 *      catch
                 *      {
                 *              try
                 *              {
                 *                      Connector.Stream.Close();
                 *              }
                 *              catch
                 *              {
                 *              }
                 *      }
                 *      return GetPooledConnector(Connection); //Try again
                 * }*/

                if (!Connector.IsValid())
                {
                    try
                    {
                        Connector.Close();
                    }
                    catch
                    {
                        try
                        {
                            Connector.Stream.Close();
                        }
                        catch
                        {
                        }
                    }
                    return(GetPooledConnector(Connection));                            //Try again
                }
                Queue.UseCount++;
            }
            else if (Queue.Count + Queue.UseCount < Connection.MaxPoolSize)
            {
                Connector = CreateConnector(Connection);

                Connector.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate;
                Connector.CertificateSelectionCallback      += Connection.CertificateSelectionCallbackDelegate;
                Connector.CertificateValidationCallback     += Connection.CertificateValidationCallbackDelegate;
                Connector.PrivateKeySelectionCallback       += Connection.PrivateKeySelectionCallbackDelegate;

                try
                {
                    Connector.Open();
                }
                catch
                {
                    try
                    {
                        Connector.Close();
                    }
                    catch
                    {
                    }

                    throw;
                }


                Queue.UseCount++;
            }

            // Meet the MinPoolSize requirement if needed.
            if (Connection.MinPoolSize > 0)
            {
                while (Queue.Count + Queue.UseCount < Connection.MinPoolSize)
                {
                    NpgsqlConnector Spare = CreateConnector(Connection);

                    Spare.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate;
                    Spare.CertificateSelectionCallback      += Connection.CertificateSelectionCallbackDelegate;
                    Spare.CertificateValidationCallback     += Connection.CertificateValidationCallbackDelegate;
                    Spare.PrivateKeySelectionCallback       += Connection.PrivateKeySelectionCallbackDelegate;

                    Spare.Open();

                    Spare.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate;
                    Spare.CertificateSelectionCallback      -= Connection.CertificateSelectionCallbackDelegate;
                    Spare.CertificateValidationCallback     -= Connection.CertificateValidationCallbackDelegate;
                    Spare.PrivateKeySelectionCallback       -= Connection.PrivateKeySelectionCallbackDelegate;

                    Queue.Enqueue(Spare);
                }
            }

            return(Connector);
        }
示例#23
0
        /// <summary>
        /// Releases a connector, possibly back to the pool for future use.
        /// </summary>
        /// <remarks>
        /// Pooled connectors will be put back into the pool if there is room.
        /// </remarks>
        /// <param name="connection">Connection to which the connector is leased.</param>
        /// <param name="connector">The connector to release.</param>
        internal void ReleaseConnector(NpgsqlConnection connection, NpgsqlConnector connector)
        {
            Contract.Requires(connector.IsReady || connector.IsClosed || connector.IsBroken);

            ConnectorQueue queue;

            // Find the queue.
            // As we are handling all possible queues, we have to lock everything...
            lock (locker)
            {
                PooledConnectors.TryGetValue(connection.ConnectionString, out queue);
            }

            if (queue == null)
            {
                connector.Close(); // Release connection to postgres
                return; // Queue may be emptied by connection problems. See ClearPool below.
            }

            /*bool inQueue = false;

            lock (queue)
            {
                inQueue = queue.Busy.ContainsKey(Connector);
                queue.Busy.Remove(Connector);
            }
            */

            bool inQueue = queue.Busy.ContainsKey(connector);

            if (connector.IsBroken || connector.IsClosed)
            {
                if (connector.InTransaction)
                {
                    connector.ClearTransaction();
                }

                connector.Close();
                inQueue = false;
            }
            else
            {
                Contract.Assert(connector.IsReady);

                //If thread is good
                if ((Thread.CurrentThread.ThreadState & (ThreadState.Aborted | ThreadState.AbortRequested)) == 0)
                {
                    // Release all resources associated with this connector.
                    try {
                        connector.Reset();
                    } catch {
                        connector.Close();
                        inQueue = false;
                    }
                } else {
                    //Thread is being aborted, this connection is possibly broken. So kill it rather than returning it to the pool
                    inQueue = false;
                    connector.Close();
                }
            }

            // Check if Connector should return to the queue of available connectors. If not, this connector is invalid and should
            // only be removed from the busy queue which effectvely removes it from the pool.
            if (inQueue)
                lock (queue)
                {
                    queue.Busy.Remove(connector);
                    queue.Available.Enqueue(connector);
                }
            else
                lock (queue)
                {
                    queue.Busy.Remove(connector);
                }

            connector.ProvideClientCertificatesCallback = null;
            connector.UserCertificateValidationCallback = null;
        }
示例#24
0
        /// <summary>
        /// Creates another connector and sends a cancel request through it for this connector.
        /// </summary>
        internal void CancelRequest()
        {
            var cancelConnector = new NpgsqlConnector(_settings, false);

            try
            {
                // Get a raw connection, possibly SSL...
                cancelConnector.RawOpen(cancelConnector.ConnectionTimeout*1000);

                // Cancel current request.
                cancelConnector.SendCancelRequest(BackEndKeyData);
            }
            finally
            {
                cancelConnector.Close();
            }
        }
示例#25
0
        /*
                /// <summary>
                /// Find an available shared connector in the shared pool, or create
                /// a new one if none found.
                /// </summary>
                private NpgsqlConnector GetSharedConnector(NpgsqlConnection Connection)
                {
                    // To be implemented

                    return null;
                }
        */
        /// <summary>
        /// Put a pooled connector into the pool queue.
        /// </summary>
        /// <param name="Connector">Connector to pool</param>
        private void UngetConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
        {
            ConnectorQueue queue;

            // Find the queue.
            // As we are handling all possible queues, we have to lock everything...
            lock (locker)
            {
                PooledConnectors.TryGetValue(Connection.ConnectionString, out queue);
            }

            if (queue == null)
            {
                Connector.Close(); // Release connection to postgres
                return; // Queue may be emptied by connection problems. See ClearPool below.
            }

            Connector.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate;
            Connector.CertificateSelectionCallback -= Connection.CertificateSelectionCallbackDelegate;
            Connector.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate;
            Connector.PrivateKeySelectionCallback -= Connection.PrivateKeySelectionCallbackDelegate;
            Connector.ValidateRemoteCertificateCallback -= Connection.ValidateRemoteCertificateCallbackDelegate;

            bool inQueue = false;

            lock (queue)
            {
                inQueue = queue.Busy.ContainsKey(Connector);
                queue.Busy.Remove(Connector);
            }

            if (!Connector.IsInitialized)
            {
                if (Connector.Transaction != null)
                {
                    Connector.Transaction.Cancel();
                }

                Connector.Close();
            }
            else
            {
                if (Connector.Transaction != null)
                {
                    try
                    {
                        Connector.Transaction.Rollback();
                    }
                    catch
                    {
                        Connector.Close();
                    }
                }
            }

            if (Connector.State == ConnectionState.Open)
            {
                //If thread is good
                if ((Thread.CurrentThread.ThreadState & (ThreadState.Aborted | ThreadState.AbortRequested)) == 0)
                {
                    // Release all resources associated with this connector.
                    try
                    {
                        Connector.ReleaseResources();
                    }
                    catch (Exception)
                    {
                        //If the connector fails to release its resources then it is probably broken, so make sure we don't add it to the queue.
                        // Usually it already won't be in the queue as it would of broken earlier
                        inQueue = false;
                    }

                    if (inQueue)
                        lock (queue)
                        {
                            queue.Available.Enqueue(Connector);
                        }
                    else
                        Connector.Close();
                }
                else
                {
                    //Thread is being aborted, this connection is possibly broken. So kill it rather than returning it to the pool
                    Connector.Close();
                }
            }
        }
示例#26
0
 internal IEnumerable<IServerResponseObject> ProcessExistingBackendResponses(NpgsqlConnector context)
 {
     try
     {
         return ProcessBackendResponses_Ver_3(context);
     }
     catch (ThreadAbortException)
     {
         try
         {
             context.CancelRequest();
             context.Close();
         }
         catch { }
         throw;
     }
 }
示例#27
0
        internal void Release(NpgsqlConnector connector)
        {
            // If Clear/ClearAll has been been called since this connector was first opened,
            // throw it away.
            if (connector.ClearCounter < _clearCounter)
            {
                try
                {
                    connector.Close();
                }
                catch (Exception e)
                {
                    Log.Warn("Exception while closing outdated connector", e, connector.Id);
                }

                lock (this)
                    DecrementBusy();
                Counters.SoftDisconnectsPerSecond.Increment();
                Counters.NumberOfPooledConnections.Decrement();
                return;
            }

            if (connector.IsBroken)
            {
                lock (this)
                    DecrementBusy();
                Counters.NumberOfPooledConnections.Decrement();
                return;
            }

            connector.Reset();
            lock (this)
            {
                // If there are any pending open attempts in progress hand the connector off to
                // them directly.
                while (_waiting.Count > 0)
                {
                    var waitingOpenAttempt = _waiting.Dequeue();
                    var tcs = waitingOpenAttempt.TaskCompletionSource;
                    // Some attempts may be in the queue but in cancelled state, since they've already timed out.
                    // Simply dequeue these and move on.
                    if (tcs.Task.IsCanceled)
                    {
                        continue;
                    }

                    // We have a pending open attempt. "Complete" it, handing off the connector.
                    if (waitingOpenAttempt.IsAsync)
                    {
                        // If the waiting open attempt is asynchronous (i.e. OpenAsync()), we can't simply
                        // call SetResult on its TaskCompletionSource, since it would execute the open's
                        // continuation in our thread (the closing thread). Instead we schedule the completion
                        // to run in the TP

                        // We copy tcs2 and especially connector2 to avoid allocations caused by the closure, see
                        // http://stackoverflow.com/questions/41507166/closure-heap-allocation-happening-at-start-of-method
                        var tcs2       = tcs;
                        var connector2 = connector;

                        Task.Run(() =>
                        {
                            if (!tcs2.TrySetResult(connector2))
                            {
                                // Race condition: the waiter timed out between our IsCanceled check above and here
                                // Recursively call Release again, this will dequeue another open attempt and retry.
                                Debug.Assert(tcs2.Task.IsCanceled);
                                Release(connector2);
                            }
                        });
                    }
                    else
                    {
                        tcs.SetResult(connector);
                    }
                    return;
                }

                Idle.Push(connector);
                DecrementBusy();
                EnsurePruningTimerState();
                Debug.Assert(Idle.Count <= _max);
            }
        }
示例#28
0
        ///<summary>
        /// This method is responsible to handle all protocol messages sent from the backend.
        /// It holds all the logic to do it.
        /// To exchange data, it uses a Mediator object from which it reads/writes information
        /// to handle backend requests.
        /// </summary>
        ///
        internal IEnumerable<IServerResponseObject> ProcessBackendResponsesEnum(NpgsqlConnector context)
        {
            try
            {
                // Flush buffers to the wire.
                context.Stream.Flush();

                // Process commandTimeout behavior.

                // We will give an extra 5 seconds to context.Mediator.CommandTimeout
                // because we'd prefer to receive a timeout error from PG
                // than to be forced to start a new connection and send a cancel request.
                // The result is that a timeout could take 5 seconds too long to occur, but if everything
                // is healthy, that shouldn't happen.
                if ((context.Mediator.BackendCommandTimeout > 0) && (!context.Stream.WaitAvailable(TimeSpan.FromSeconds(context.Mediator.BackendCommandTimeout + 5))))
                {
                    // If timeout occurs when establishing the session with server then
                    // throw an exception instead of trying to cancel query. This helps to prevent loop as
                    // CancelRequest will also try to stablish a connection and sends commands.
                    if (!((this is NpgsqlStartupState || this is NpgsqlConnectedState)))
                    {
                        try
                        {
                            context.CancelRequest();

                            ProcessAndDiscardBackendResponses(context);
                        }
                        catch(Exception)
                        {
                        }
                        // We should have gotten an error from CancelRequest(). Whether we did or not, what we
                        // really have is a timeout exception, and that will be less confusing to the user than
                        // "operation cancelled by user" or similar, so whatever the case, that is what we'll throw.
                        // Changed message again to report about the two possible timeouts: connection or command
                        // as the establishment timeout only was confusing users when the timeout was a command timeout.
                    }

                    throw new NpgsqlException(resman.GetString("Exception_ConnectionOrCommandTimeout"));
                }

                switch (context.BackendProtocolVersion)
                {
                    case ProtocolVersion.Version2:
                        return ProcessBackendResponses_Ver_2(context);
                    case ProtocolVersion.Version3:
                        return ProcessBackendResponses_Ver_3(context);
                    default:
                        throw new NpgsqlException(resman.GetString("Exception_UnknownProtocol"));
                }

            }
            catch(ThreadAbortException)
            {
                try
                {
                    context.CancelRequest();
                    context.Close();
                }
                catch {}

                throw;
            }
        }
示例#29
0
        /// <summary>
        /// Creates another connector and sends a cancel request through it for this connector.
        /// </summary>
        internal void CancelRequest()
        {
            var cancelConnector = new NpgsqlConnector(_settings, false);

            try
            {
                cancelConnector.RawOpen(cancelConnector.ConnectionTimeout*1000);
                cancelConnector.SendSingleMessage(new CancelRequestMessage(BackendProcessId, BackendSecretKey));
            }
            finally
            {
                cancelConnector.Close();
            }
        }
示例#30
0
        /// <summary>
        /// Find an available pooled connector in the non-shared pool, or create
        /// a new one if none found.
        /// </summary>
        private NpgsqlConnector GetPooledConnector(NpgsqlConnection Connection)
        {
            ConnectorQueue  Queue;
            NpgsqlConnector Connector = null;

            // We only need to lock all pools when trying to get one pool or create one.

            lock (locker)
            {
                // Try to find a queue.
                if (!PooledConnectors.TryGetValue(Connection.ConnectionString, out Queue))
                {
                    Queue = new ConnectorQueue();
                    Queue.ConnectionLifeTime = Connection.ConnectionLifeTime;
                    Queue.MinPoolSize        = Connection.MinPoolSize;
                    PooledConnectors[Connection.ConnectionString] = Queue;
                }
            }

            // Now we can simply lock on the pool itself.
            lock (Queue)
            {
                if (Queue.Available.Count > 0)
                {
                    // Found a queue with connectors.  Grab the top one.

                    // Check if the connector is still valid.

                    Connector = Queue.Available.Dequeue();
                    Queue.Busy.Add(Connector, null);
                }
            }

            if (Connector != null)
            {
                if (!Connector.IsValid())
                {
                    lock (Queue)
                    {
                        Queue.Busy.Remove(Connector);
                    }

                    Connector.Close();
                    return(GetPooledConnector(Connection)); //Try again
                }

                return(Connector);
            }

            lock (Queue)
            {
                if (Queue.Available.Count + Queue.Busy.Count < Connection.MaxPoolSize)
                {
                    Connector = new NpgsqlConnector(Connection);
                    Queue.Busy.Add(Connector, null);
                }
            }

            if (Connector != null)
            {
                Connector.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate;
                Connector.CertificateSelectionCallback      += Connection.CertificateSelectionCallbackDelegate;
                Connector.CertificateValidationCallback     += Connection.CertificateValidationCallbackDelegate;
                Connector.PrivateKeySelectionCallback       += Connection.PrivateKeySelectionCallbackDelegate;
                Connector.ValidateRemoteCertificateCallback += Connection.ValidateRemoteCertificateCallbackDelegate;

                try
                {
                    Connector.Open();
                }
                catch
                {
                    lock (Queue)
                    {
                        Queue.Busy.Remove(Connector);
                    }

                    Connector.Close();

                    throw;
                }

                // Meet the MinPoolSize requirement if needed.
                if (Connection.MinPoolSize > 1)
                {
                    lock (Queue)
                    {
                        while (Queue.Available.Count + Queue.Busy.Count < Connection.MinPoolSize)
                        {
                            NpgsqlConnector Spare = new NpgsqlConnector(Connection);

                            Spare.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate;
                            Spare.CertificateSelectionCallback      += Connection.CertificateSelectionCallbackDelegate;
                            Spare.CertificateValidationCallback     += Connection.CertificateValidationCallbackDelegate;
                            Spare.PrivateKeySelectionCallback       += Connection.PrivateKeySelectionCallbackDelegate;
                            Spare.ValidateRemoteCertificateCallback += Connection.ValidateRemoteCertificateCallbackDelegate;

                            Spare.Open();

                            Spare.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate;
                            Spare.CertificateSelectionCallback      -= Connection.CertificateSelectionCallbackDelegate;
                            Spare.CertificateValidationCallback     -= Connection.CertificateValidationCallbackDelegate;
                            Spare.PrivateKeySelectionCallback       -= Connection.PrivateKeySelectionCallbackDelegate;
                            Spare.ValidateRemoteCertificateCallback -= Connection.ValidateRemoteCertificateCallbackDelegate;

                            Queue.Available.Enqueue(Spare);
                        }
                    }
                }
            }

            return(Connector);
        }
        /// <summary>
        /// Put a pooled connector into the pool queue.
        /// </summary>
        /// <param name="Connector">Connector to pool</param>
        private void UngetPooledConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
        {
            ConnectorQueue           Queue;

            // Find the queue.
            Queue = (ConnectorQueue)PooledConnectors[Connector.ConnectionString.ToString()];

            if (Queue == null)
            {
                throw new InvalidOperationException("Internal: No connector queue found for existing connector.");
            }

            Connector.CertificateSelectionCallback -= Connection.CertificateSelectionCallbackDelegate;
            Connector.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate;
            Connector.PrivateKeySelectionCallback -= Connection.PrivateKeySelectionCallbackDelegate;

            Queue.UseCount--;

            if (! Connector.IsInitialized)
            {
                if (Connector.Transaction != null)
                {
                    Connector.Transaction.Cancel();
                }

                Connector.Close();
            }
            else
            {
                if (Connector.Transaction != null)
                {
                    try
                    {
                        Connector.Transaction.Rollback();
                    }
                    catch {
                        Connector.Close()
                        ;
                    }
                }
        }

        if (Connector.State == System.Data.ConnectionState.Open)
            {
                // Release all plans and portals associated with this connector.
                Connector.ReleasePlansPortals();

                Queue.Enqueue(Connector);
            }
        }
示例#32
0
        ///<summary>
        /// This method is responsible to handle all protocol messages sent from the backend.
        /// It holds all the logic to do it.
        /// To exchange data, it uses a Mediator object from which it reads/writes information
        /// to handle backend requests.
        /// </summary>
        ///
        internal IEnumerable<IServerResponseObject> ProcessBackendResponsesEnum(NpgsqlConnector context)
        {
            try
            {
                // Flush buffers to the wire.
                context.Stream.Flush();

                // Process commandTimeout behavior.

                if ((context.Mediator.BackendCommandTimeout > 0) &&
                        (!CheckForContextSocketAvailability(context, SelectMode.SelectRead)))
                {
                    // If timeout occurs when establishing the session with server then
                    // throw an exception instead of trying to cancel query. This helps to prevent loop as
                    // CancelRequest will also try to stablish a connection and sends commands.
                    if (!((this is NpgsqlStartupState || this is NpgsqlConnectedState)))
                    {
                        try
                        {
                            context.CancelRequest();

                            ProcessAndDiscardBackendResponses(context);
                        }
                        catch(Exception)
                        {
                        }
                        // We should have gotten an error from CancelRequest(). Whether we did or not, what we
                        // really have is a timeout exception, and that will be less confusing to the user than
                        // "operation cancelled by user" or similar, so whatever the case, that is what we'll throw.
                        // Changed message again to report about the two possible timeouts: connection or command
                        // as the establishment timeout only was confusing users when the timeout was a command timeout.
                    }

                    throw new NpgsqlException(resman.GetString("Exception_ConnectionOrCommandTimeout"));
                }

                return ProcessBackendResponses(context);
            }
            catch(ThreadAbortException)
            {
                try
                {
                    context.CancelRequest();
                    context.Close();
                }
                catch {}

                throw;
            }

        }