Ejemplo n.º 1
0
 protected override void Dispose(bool disposing)
 {
     if (!disposing)
     {
         mContext.Close();
         mContext = null;
     }
     base.Dispose(disposing);
 }
Ejemplo n.º 2
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,
            bool cancelRequestCalled)
        {
            try
            {
                // Process commandTimeout behavior.

                if ((context.Mediator.CommandTimeout > 0) &&
                    (!CheckForContextSocketAvailability(context)))
                {
                    // 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 || cancelRequestCalled)))
                    {
                        try
                        {
                            context.CancelRequest();
                            foreach (IServerResponseObject obj in ProcessBackendResponsesEnum(context, true))
                            {
                                if (obj is IDisposable)
                                {
                                    (obj as IDisposable).Dispose();
                                }
                            }
                        }
                        catch
                        {
                        }
                        //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_Ver_3(context));
            }

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

                throw;
            }
        }
Ejemplo n.º 3
0
 internal IEnumerable <IServerResponseObject> ProcessExistingBackendResponses(NpgsqlConnector context)
 {
     try
     {
         return(ProcessBackendResponses_Ver_3(context));
     }
     catch (ThreadAbortException)
     {
         try
         {
             context.CancelRequest();
             context.Close();
         }
         catch { }
         throw;
     }
 }
Ejemplo n.º 4
0
        private static void ClearQueue(ConnectorQueue Queue)
        {
            if (Queue == null)
            {
                return;
            }

            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();
        }
Ejemplo n.º 5
0
        /// <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;

            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();
                }
            }
        }
Ejemplo n.º 6
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;

                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.Open();

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

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

            return(Connector);
        }
Ejemplo n.º 7
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,
            bool cancelRequestCalled)
        {
            try
            {
                // Process commandTimeout behavior.

                if ((context.Mediator.CommandTimeout > 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 || cancelRequestCalled)))
                    {
                        try
                        {
                            context.CancelRequest();
                            foreach (IServerResponseObject obj in ProcessBackendResponsesEnum(context, true))
                            {
                                if (obj is IDisposable)
                                {
                                    (obj as IDisposable).Dispose();
                                }
                            }
                        }
                        catch
                        {
                        }
                        //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_Ver_3(context);

            }

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

                throw;
            }
        }
Ejemplo n.º 8
0
		internal IEnumerable<IServerResponseObject> ProcessExistingBackendResponses(NpgsqlConnector context)
		{
			try
			{
				return ProcessBackendResponses_Ver_3(context);
			}
			catch (ThreadAbortException)
			{
				try
				{
					context.CancelRequest();
					context.Close();
				}
				catch { }
				throw;
			}
		}
Ejemplo n.º 9
0
		/// <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;

			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();
				}
			}
		}