예제 #1
0
        private void TimerElapsedHandler(object sender, ElapsedEventArgs e)
        {
            NpgsqlConnector Connector;
            var             activeConnectionsExist = false;

            try
            {
                lock (locker)
                {
                    foreach (ConnectorQueue Queue in PooledConnectors.Values)
                    {
                        lock (Queue)
                        {
                            if (Queue.Available.Count > 0)
                            {
                                if (Queue.Available.Count + Queue.Busy.Count > Queue.MinPoolSize)
                                {
                                    if (Queue.InactiveTime >= Queue.ConnectionLifeTime)
                                    {
                                        Int32 diff       = Queue.Available.Count + Queue.Busy.Count - Queue.MinPoolSize;
                                        Int32 toBeClosed = (diff + 1) / 2;
                                        toBeClosed = Math.Min(toBeClosed, Queue.Available.Count);

                                        if (diff < 2)
                                        {
                                            diff = 2;
                                        }

                                        Queue.InactiveTime -= Queue.ConnectionLifeTime / (int)(Math.Log(diff) / Math.Log(2));

                                        for (Int32 i = 0; i < toBeClosed; ++i)
                                        {
                                            Connector = Queue.Available.Dequeue();
                                            Connector.Close();
                                        }
                                    }
                                    else
                                    {
                                        Queue.InactiveTime++;
                                    }
                                }
                                else
                                {
                                    Queue.InactiveTime = 0;
                                }
                                if (Queue.Available.Count > 0 || Queue.Busy.Count > 0)
                                {
                                    activeConnectionsExist = true;
                                }
                            }
                            else
                            {
                                Queue.InactiveTime = 0;
                            }
                        }
                    }
                }
            }
            finally
            {
                if (activeConnectionsExist)
                {
                    Timer.Start();
                }
                else
                {
                    Timer = null;
                }
            }
        }
예제 #2
0
 /// <summary>
 /// Rolls back a transaction from a pending state.
 /// </summary>
 public override void Rollback()
 {
     CheckReady();
     Connector.Rollback();
     Connection = null;
 }
예제 #3
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.RemoteCertificateValidationCallback += Connection.RemoteCertificateValidationCallbackDelegate;
//                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.RemoteCertificateValidationCallback += Connection.RemoteCertificateValidationCallbackDelegate;
//                            Spare.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate;
//                            Spare.CertificateSelectionCallback += Connection.CertificateSelectionCallbackDelegate;
//                            Spare.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate;
//                            Spare.PrivateKeySelectionCallback += Connection.PrivateKeySelectionCallbackDelegate;
//                            Spare.ValidateRemoteCertificateCallback += Connection.ValidateRemoteCertificateCallbackDelegate;

                            Spare.Open();

                            Spare.RemoteCertificateValidationCallback -= Connection.RemoteCertificateValidationCallbackDelegate;
//                            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);
        }
예제 #4
0
 internal override ValueTask <IBackendMessage> ReadMessage(bool async)
 => Connector.ReadMessage(async, DataRowLoadingMode.Sequential);