Example #1
0
        /*
         *      /// <summary>
         *      /// Stop sharing a shared connector.
         *      /// </summary>
         *      /// <param name="Connector">Connector to unshare</param>
         *      private void UngetSharedConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
         *      {
         *          // To be implemented
         *      }
         */

        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();
            }
        }
Example #2
0
        protected override void Dispose(bool disposing)
        {
            if (!disposing)
            {
                if (mContext != null)
                {
                    mContext.Close();
                    mContext = null;
                }
            }

            base.Dispose(disposing);
        }
Example #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("Exception_ConnectionOrCommandTimeout");
                }

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

                throw;
            }
        }
Example #4
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.
            }

            /*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);
                }
            }
        }
Example #5
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     = null;
            NpgsqlConnector Connector = null;

            do
            {
                if (Connector != null)
                {
                    //This means Connector was found to be invalid at the end of the loop

                    lock (Queue)
                    {
                        Queue.Busy.Remove(Connector);
                    }

                    Connector.Close();
                    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);
                    }
                }
            } while (Connector != null && !Connector.IsValid());

            if (Connector != null)
            {
                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)
            {
                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.Open();

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

            return(Connector);
        }