Beispiel #1
0
        internal ValueTask <NpgsqlConnector> Allocate(NpgsqlConnection conn, NpgsqlTimeout timeout, bool async, CancellationToken cancellationToken)
        {
            Monitor.Enter(this);

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

            // No idle connectors available. Have to actually open a new connector or wait for one.
            return(AllocateLong(conn, timeout, async, cancellationToken));
        }
Beispiel #2
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;
            }
        }