예제 #1
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;
            }

            // Now we can simply lock on the pool itself.
            lock (Queue)
            {
                if (Queue.AvailableCount > 0)
                {
                    // Found a queue with connectors.  Grab the top one.
                    // Check if the connector is still valid.
                    Connector = Queue.TakeAvailable();
                    Queue.AddBusy(Connector);
                }
            }

            if (Connector != null)
            {
                if (!Connector.IsValid())
                {
                    Queue.RemoveBusy(Connector);

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

                return(Connector);
            }

            lock (Queue)
            {
                if (Queue.AvailableCount + Queue.BusyCount < Connection.MaxPoolSize)
                {
                    Connector = new NpgsqlConnector(Connection);
                    Queue.AddBusy(Connector);
                }
            }

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

                try
                {
                    Connector.Open();
                }
                catch
                {
                    Queue.RemoveBusy(Connector);

                    Connector.Close();

                    throw;
                }

                // Meet the MinPoolSize requirement if needed.
                if (Connection.MinPoolSize > 1)
                {
                    lock (Queue)
                    {
                        while (Queue.AvailableCount + Queue.BusyCount < 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.EnqueueAvailable(Spare);
                        }
                    }
                }
            }

            return(Connector);
        }