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

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

            // Check if there is any missing argument.
            if (!settings.ContainsKey(Keywords.Host))
            {
                throw new ArgumentException("Exception_MissingConnStrArg: " + Keywords.Host);
            }
            if (!settings.ContainsKey(Keywords.UserName) && !settings.ContainsKey(Keywords.IntegratedSecurity))
            {
                throw new ArgumentException("Exception_MissingConnStrArg: " + 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.Open();
            }

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

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

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

            OpenCounter++;
            this.OnStateChange(new StateChangeEventArgs(ConnectionState.Closed, ConnectionState.Open));
        }
Example #2
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);
        }