Open() private method

Opens the physical connection to the server.
Usually called by the RequestConnector Method of the connection pool manager.
private Open ( ) : void
return void
示例#1
0
        /// <summary>
        /// Opens a database connection with the property settings specified by the
        /// <see cref="Npgsql.NpgsqlConnection.ConnectionString">ConnectionString</see>.
        /// </summary>
        public override void Open()
        {
            // If we're postponing a close (see doc on this variable), the connection is already
            // open and can be silently reused
            if (_postponingClose)
            {
                return;
            }

            CheckConnectionClosed();

            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Open");

            // Check if there is any missing argument.
            if (!settings.ContainsKey(Keywords.Host))
            {
                throw new ArgumentException(resman.GetString("Exception_MissingConnStrArg"),
                                            NpgsqlConnectionStringBuilder.GetKeyName(Keywords.Host));
            }
            if (!settings.ContainsKey(Keywords.UserName) && !settings.ContainsKey(Keywords.IntegratedSecurity))
            {
                throw new ArgumentException(resman.GetString("Exception_MissingConnStrArg"),
                                            NpgsqlConnectionStringBuilder.GetKeyName(Keywords.UserName));
            }

            // Get a Connector, either from the pool or creating one ourselves.
            if (Pooling)
            {
                connector = NpgsqlConnectorPool.ConnectorPoolMgr.RequestConnector(this);
            }
            else
            {
                connector = new NpgsqlConnector(this);

                connector.RemoteCertificateValidationCallback += RemoteCertificateValidationCallback;
//                connector.ProvideClientCertificatesCallback += ProvideClientCertificatesCallbackDelegate;
//                connector.CertificateSelectionCallback += CertificateSelectionCallbackDelegate;
//                connector.CertificateValidationCallback += CertificateValidationCallbackDelegate;
//                connector.PrivateKeySelectionCallback += PrivateKeySelectionCallbackDelegate;
//                connector.ValidateRemoteCertificateCallback += ValidateRemoteCertificateCallbackDelegate;

                connector.Open();
            }

            connector.Notice       += NoticeDelegate;
            connector.Notification += NotificationDelegate;

            if (SyncNotification)
            {
                connector.AddNotificationThread();
            }

            if (Enlist)
            {
                Promotable.Enlist(Transaction.Current);
            }

            this.OnStateChange(new StateChangeEventArgs(ConnectionState.Closed, ConnectionState.Open));
        }
示例#2
0
        /// <summary>
        /// Opens a database connection with the property settings specified by the
        /// <see cref="NpgsqlConnection.ConnectionString">ConnectionString</see>.
        /// </summary>
        public override void Open()
        {
            // If we're postponing a close (see doc on this variable), the connection is already
            // open and can be silently reused
            if (_postponingClose)
            {
                return;
            }

            CheckConnectionClosed();

            _log.Debug("Opening connnection");

            // Check if there is any missing argument.
            if (!_settings.ContainsKey(Keywords.Host))
            {
                throw new ArgumentException(L10N.MissingConnStrArg, Keywords.Host.ToString());
            }
            if (!_settings.ContainsKey(Keywords.UserName) && !_settings.ContainsKey(Keywords.IntegratedSecurity))
            {
                throw new ArgumentException(L10N.MissingConnStrArg, Keywords.UserName.ToString());
            }

            // Get a Connector, either from the pool or creating one ourselves.
            if (Pooling)
            {
                Connector = NpgsqlConnectorPool.ConnectorPoolMgr.RequestConnector(this);
            }
            else
            {
                Connector = new NpgsqlConnector(this);

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

                Connector.Open();
            }

            Connector.Notice       += NoticeDelegate;
            Connector.Notification += NotificationDelegate;

            if (SyncNotification)
            {
                // Disable async notifications for now
                //Connector.AddNotificationThread();
            }

            if (Enlist)
            {
                Promotable.Enlist(Transaction.Current);
            }

            OnStateChange(new StateChangeEventArgs(ConnectionState.Closed, ConnectionState.Open));
        }
示例#3
0
        /// <summary>
        /// Attempts to ensure, on a best-effort basis, that there are enough connections to meet MinPoolSize.
        /// This method never throws an exception.
        /// </summary>
        void EnsureMinPoolSize(NpgsqlConnection conn)
        {
            int missing;

            lock (this)
            {
                missing = _min - (Busy + Idle.Count);
                if (missing <= 0)
                {
                    return;
                }
                Busy += missing;
            }

            for (; missing > 0; missing--)
            {
                try
                {
#if NETSTANDARD1_3
                    var connector = new NpgsqlConnector(conn.Clone())
#else
                    var connector = new NpgsqlConnector((NpgsqlConnection)((ICloneable)conn).Clone())
#endif
                    {
                        ClearCounter = _clearCounter
                    };
                    // TODO: Think about the timeout here...
                    connector.Open(new NpgsqlTimeout(TimeSpan.Zero), false, CancellationToken.None).Wait();
                    connector.Reset();
                    Counters.NumberOfPooledConnections.Increment();
                    lock (this)
                    {
                        Idle.Push(connector);
                        EnsurePruningTimerState();
                        Busy--;
                    }
                }
                catch (Exception e)
                {
                    lock (this)
                        Busy -= missing;
                    Log.Warn("Connection error while attempting to ensure MinPoolSize", e);
                    return;
                }
            }
        }
示例#4
0
        /// <summary>
        /// Attempts to ensure, on a best-effort basis, that there are enough connections to meet MinPoolSize.
        /// This method never throws an exception.
        /// </summary>
        void EnsureMinPoolSize(NpgsqlConnection conn)
        {
            int missing;

            lock (this)
            {
                missing = Min - (Busy + Idle.Count);
                if (missing <= 0)
                {
                    return;
                }
                Busy += missing;
            }

            for (; missing > 0; missing--)
            {
                try
                {
#if NET451 || NET45
                    var connector = new NpgsqlConnector((NpgsqlConnection)((ICloneable)conn).Clone())
#else
                    var connector = new NpgsqlConnector(conn.Clone())
#endif
                    {
                        ClearCounter = _clearCounter
                    };
                    connector.Open();
                    connector.Reset();
                    lock (this)
                    {
                        Idle.Push(connector);
                        EnsurePruningTimerState();
                        Busy--;
                    }
                }
                catch (Exception e)
                {
                    lock (this)
                        Busy -= missing;
                    Log.Warn("Connection error while attempting to ensure MinPoolSize", e);
                    return;
                }
            }
        }
示例#5
0
        /// <summary>
        /// Find an available pooled connector in the pool, or create a new one if none found.
        /// </summary>
        private NpgsqlConnector GetPooledConnector(NpgsqlConnection Connection)
        {
            ConnectorQueue  Queue     = null;
            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)
            {
                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.ProvideClientCertificatesCallback;
                Connector.UserCertificateValidationCallback = Connection.UserCertificateValidationCallback;

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

                    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)
                            {
                                ProvideClientCertificatesCallback = Connection.ProvideClientCertificatesCallback,
                                UserCertificateValidationCallback = Connection.UserCertificateValidationCallback
                            };


                            spare.Open();

                            spare.ProvideClientCertificatesCallback = null;
                            spare.UserCertificateValidationCallback = null;

                            spare.Connection = null;
                            Queue.Available.Enqueue(spare);
                        }
                    }
                }
            }

            return(Connector);
        }
示例#6
0
        internal async ValueTask <NpgsqlConnector> AllocateLong(NpgsqlConnection conn, NpgsqlTimeout timeout, bool async, CancellationToken cancellationToken)
        {
            Debug.Assert(Monitor.IsEntered(this));
            NpgsqlConnector connector;

            Debug.Assert(Busy <= _max);
            if (Busy == _max)
            {
                // TODO: Async cancellation
                var tcs = new TaskCompletionSource <NpgsqlConnector>();
                _waiting.Enqueue(new WaitingOpenAttempt {
                    TaskCompletionSource = tcs, IsAsync = async
                });
                Monitor.Exit(this);

                try
                {
                    if (async)
                    {
                        if (timeout.IsSet)
                        {
                            var timeLeft = timeout.TimeLeft;
                            if (timeLeft <= TimeSpan.Zero || tcs.Task != await Task.WhenAny(tcs.Task, Task.Delay(timeLeft)))
                            {
                                throw new NpgsqlException($"The connection pool has been exhausted, either raise MaxPoolSize (currently {_max}) or Timeout (currently {Settings.Timeout} seconds)");
                            }
                        }
                        else
                        {
                            await tcs.Task;
                        }
                    }
                    else
                    {
                        if (timeout.IsSet)
                        {
                            var timeLeft = timeout.TimeLeft;
                            if (timeLeft <= TimeSpan.Zero || !tcs.Task.Wait(timeLeft))
                            {
                                throw new NpgsqlException($"The connection pool has been exhausted, either raise MaxPoolSize (currently {_max}) or Timeout (currently {Settings.Timeout} seconds)");
                            }
                        }
                        else
                        {
                            tcs.Task.Wait();
                        }
                    }
                }
                catch
                {
                    // We're here if the timeout expired or the cancellation token was triggered
                    // Re-lock and check in case the task was set to completed after coming out of the Wait
                    lock (this)
                    {
                        if (!tcs.Task.IsCompleted)
                        {
                            tcs.SetCanceled();
                            throw;
                        }
                    }
                }
                connector            = tcs.Task.Result;
                connector.Connection = conn;
                return(connector);
            }

            // No idle connectors are available, and we're under the pool's maximum capacity.
            IncrementBusy();
            Monitor.Exit(this);

            try
            {
                connector = new NpgsqlConnector(conn)
                {
                    ClearCounter = _clearCounter
                };
                await connector.Open(timeout, async, cancellationToken);

                Counters.NumberOfPooledConnections.Increment();
                EnsureMinPoolSize(conn);
                return(connector);
            }
            catch
            {
                lock (this)
                    DecrementBusy();
                throw;
            }
        }
示例#7
0
        /// <summary>
        /// Opens a database connection with the property settings specified by the
        /// <see cref="Npgsql.NpgsqlConnection.ConnectionString">ConnectionString</see>.
        /// </summary>
        public override void Open()
        {
            // If we're postponing a close (see doc on this variable), the connection is already
            // open and can be silently reused
            if (_postponingClose)
                return;

            CheckConnectionClosed();

            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Open");

            // Check if there is any missing argument.
            if (!settings.ContainsKey(Keywords.Host))
            {
                throw new ArgumentException(resman.GetString("Exception_MissingConnStrArg"),
                                            NpgsqlConnectionStringBuilder.GetKeyName(Keywords.Host));
            }
            if (!settings.ContainsKey(Keywords.UserName) && !settings.ContainsKey(Keywords.IntegratedSecurity))
            {
                throw new ArgumentException(resman.GetString("Exception_MissingConnStrArg"),
                                            NpgsqlConnectionStringBuilder.GetKeyName(Keywords.UserName));
            }

            // Get a Connector, either from the pool or creating one ourselves.
            if (Pooling)
            {
                connector = NpgsqlConnectorPool.ConnectorPoolMgr.RequestConnector(this);
            }
            else
            {
                connector = new NpgsqlConnector(this);

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

                connector.Open();
            }

            connector.Notice += NoticeDelegate;
            connector.Notification += NotificationDelegate;

            if (SyncNotification)
            {
                connector.AddNotificationThread();
            }

            if (Enlist)
            {
                Promotable.Enlist(Transaction.Current);
            }

            this.OnStateChange (new StateChangeEventArgs(ConnectionState.Closed, ConnectionState.Open));

        }
示例#8
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;
        }
示例#9
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);
        }
示例#10
0
        internal NpgsqlConnector Allocate(NpgsqlConnection conn, NpgsqlTimeout timeout)
        {
            NpgsqlConnector connector;

            Monitor.Enter(this);

            while (Idle.Count > 0)
            {
                connector = Idle.Pop();
                // An idle connector could be broken because of a keepalive
                if (connector.IsBroken)
                {
                    continue;
                }
                connector.Connection = conn;
                Busy++;
                EnsurePruningTimerState();
                Monitor.Exit(this);
                return(connector);
            }

            Contract.Assert(Busy <= _max);
            if (Busy == _max)
            {
                // TODO: Async cancellation
                var tcs = new TaskCompletionSource <NpgsqlConnector>();
                EnqueueWaitingOpenAttempt(tcs);
                Monitor.Exit(this);
                try
                {
                    WaitForTask(tcs.Task, timeout.TimeLeft);
                }
                catch
                {
                    // We're here if the timeout expired or the cancellation token was triggered
                    // Re-lock and check in case the task was set to completed after coming out of the Wait
                    lock (this)
                    {
                        if (!tcs.Task.IsCompleted)
                        {
                            tcs.SetCanceled();
                            throw;
                        }
                    }
                }
                connector            = tcs.Task.Result;
                connector.Connection = conn;
                return(connector);
            }

            // No idle connectors are available, and we're under the pool's maximum capacity.
            Busy++;
            Monitor.Exit(this);

            try
            {
                connector = new NpgsqlConnector(conn)
                {
                    ClearCounter = _clearCounter
                };
                connector.Open(timeout);
                EnsureMinPoolSize(conn);
                return(connector);
            }
            catch
            {
                lock (this)
                    Busy--;
                throw;
            }
        }
示例#11
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);
        }
示例#12
0
        /// <summary>
        /// Find an available pooled connector in the pool, or create a new one if none found.
        /// </summary>
        private NpgsqlConnector GetPooledConnector(NpgsqlConnection Connection)
        {
            ConnectorQueue Queue = null;
            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) 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.ProvideClientCertificatesCallback;
                Connector.UserCertificateValidationCallback = Connection.UserCertificateValidationCallback;

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

                    throw;
                }

                // Meet the MinPoolSize requirement if needed.
                if (Connection.MinPoolSize > 1)
                {
                    try
                    {
                        lock (Queue)
                        {

                            while (Queue.Available.Count + Queue.Busy.Count < Connection.MinPoolSize)
                            {
                                NpgsqlConnector spare = new NpgsqlConnector(Connection) {
                                    ProvideClientCertificatesCallback = Connection.ProvideClientCertificatesCallback,
                                    UserCertificateValidationCallback = Connection.UserCertificateValidationCallback
                                };


                                spare.Open();

                                spare.ProvideClientCertificatesCallback = null;
                                spare.UserCertificateValidationCallback = null;

                                spare.Connection = null;
                                Queue.Available.Enqueue(spare);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Warn("Exception while trying to open spare connectors to meet MinPoolSize", e);
                    }
                }
            }

            return Connector;
        }
        /// <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);
        }
示例#14
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);
        }
示例#15
0
        /// <summary>
        /// Opens a database connection with the property settings specified by the
        /// <see cref="NpgsqlConnection.ConnectionString">ConnectionString</see>.
        /// </summary>
        public override void Open()
        {
            if (string.IsNullOrWhiteSpace(Host))
            {
                throw new ArgumentException("Host can't be null");
            }
            if (string.IsNullOrWhiteSpace(Database))
            {
                throw new ArgumentException("Database can't be null");
            }
            if (string.IsNullOrWhiteSpace(UserName) && !IntegratedSecurity)
            {
                throw new ArgumentException("Either Username must be specified or IntegratedSecurity must be on");
            }
            Contract.EndContractBlock();

            // If we're postponing a close (see doc on this variable), the connection is already
            // open and can be silently reused
            if (_postponingClose)
            {
                return;
            }

            CheckConnectionClosed();

            Log.Debug("Opening connnection");

            WasBroken = false;

            try
            {
                // Get a Connector, either from the pool or creating one ourselves.
                if (Pooling)
                {
                    Connector = NpgsqlConnectorPool.ConnectorPoolMgr.RequestConnector(this);
                }
                else
                {
                    Connector = new NpgsqlConnector(this)
                    {
                        ProvideClientCertificatesCallback = ProvideClientCertificatesCallback,
                        UserCertificateValidationCallback = UserCertificateValidationCallback
                    };

                    Connector.Open();
                }

                Connector.Notice       += NoticeDelegate;
                Connector.Notification += NotificationDelegate;

#if !DNXCORE50
                if (Enlist)
                {
                    Promotable.Enlist(Transaction.Current);
                }
#endif
            }
            catch
            {
                Connector = null;
                throw;
            }
            OpenCounter++;
            OnStateChange(new StateChangeEventArgs(ConnectionState.Closed, ConnectionState.Open));
        }
示例#16
0
        /// <summary>
        /// Opens a database connection with the property settings specified by the
        /// <see cref="NpgsqlConnection.ConnectionString">ConnectionString</see>.
        /// </summary>
        public override void Open()
        {
            // If we're postponing a close (see doc on this variable), the connection is already
            // open and can be silently reused
            if (_postponingClose)
                return;

            CheckConnectionClosed();

            _log.Debug("Opening connnection");

            // Check if there is any missing argument.
            if (!_settings.ContainsKey(Keywords.Host))
            {
                throw new ArgumentException(L10N.MissingConnStrArg, Keywords.Host.ToString());
            }
            if (!_settings.ContainsKey(Keywords.UserName) && !_settings.ContainsKey(Keywords.IntegratedSecurity))
            {
                throw new ArgumentException(L10N.MissingConnStrArg, Keywords.UserName.ToString());
            }

            // Get a Connector, either from the pool or creating one ourselves.
            if (Pooling)
            {
                Connector = NpgsqlConnectorPool.ConnectorPoolMgr.RequestConnector(this);
            }
            else
            {
                Connector = new NpgsqlConnector(this);

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

                Connector.Open();
            }

            Connector.Notice += NoticeDelegate;
            Connector.Notification += NotificationDelegate;

            if (SyncNotification)
            {
                Connector.AddNotificationThread();
            }

            if (Enlist)
            {
                Promotable.Enlist(Transaction.Current);
            }

            OnStateChange(new StateChangeEventArgs(ConnectionState.Closed, ConnectionState.Open));
        }