98 lines
3.4 KiB
C#
98 lines
3.4 KiB
C#
using Npgsql.Internal;
|
|
using Npgsql.Util;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Transactions;
|
|
|
|
namespace Npgsql;
|
|
|
|
abstract class ConnectorSource : IDisposable
|
|
{
|
|
internal NpgsqlConnectionStringBuilder Settings { get; }
|
|
|
|
/// <summary>
|
|
/// Contains the connection string returned to the user from <see cref="NpgsqlConnection.ConnectionString"/>
|
|
/// after the connection has been opened. Does not contain the password unless Persist Security Info=true.
|
|
/// </summary>
|
|
internal string UserFacingConnectionString { get; }
|
|
|
|
// Note that while the dictionary is protected by locking, we assume that the lists it contains don't need to be
|
|
// (i.e. access to connectors of a specific transaction won't be concurrent)
|
|
protected readonly Dictionary<Transaction, List<NpgsqlConnector>> _pendingEnlistedConnectors
|
|
= new();
|
|
|
|
internal abstract (int Total, int Idle, int Busy) Statistics { get; }
|
|
|
|
internal ConnectorSource(NpgsqlConnectionStringBuilder settings, string connString)
|
|
{
|
|
Settings = settings;
|
|
|
|
UserFacingConnectionString = settings.PersistSecurityInfo
|
|
? connString
|
|
: settings.ToStringWithoutPassword();
|
|
}
|
|
|
|
internal abstract ValueTask<NpgsqlConnector> Get(
|
|
NpgsqlConnection conn, NpgsqlTimeout timeout, bool async, CancellationToken cancellationToken);
|
|
|
|
internal abstract bool TryGetIdleConnector([NotNullWhen(true)] out NpgsqlConnector? connector);
|
|
|
|
internal abstract ValueTask<NpgsqlConnector?> OpenNewConnector(
|
|
NpgsqlConnection conn, NpgsqlTimeout timeout, bool async, CancellationToken cancellationToken);
|
|
|
|
internal abstract void Return(NpgsqlConnector connector);
|
|
|
|
internal abstract void Clear();
|
|
|
|
internal abstract bool OwnsConnectors { get; }
|
|
|
|
public virtual void Dispose() { }
|
|
|
|
#region Pending Enlisted Connections
|
|
|
|
internal virtual void AddPendingEnlistedConnector(NpgsqlConnector connector, Transaction transaction)
|
|
{
|
|
lock (_pendingEnlistedConnectors)
|
|
{
|
|
if (!_pendingEnlistedConnectors.TryGetValue(transaction, out var list))
|
|
list = _pendingEnlistedConnectors[transaction] = new List<NpgsqlConnector>();
|
|
list.Add(connector);
|
|
}
|
|
}
|
|
|
|
internal virtual bool TryRemovePendingEnlistedConnector(NpgsqlConnector connector, Transaction transaction)
|
|
{
|
|
lock (_pendingEnlistedConnectors)
|
|
{
|
|
if (!_pendingEnlistedConnectors.TryGetValue(transaction, out var list))
|
|
return false;
|
|
list.Remove(connector);
|
|
if (list.Count == 0)
|
|
_pendingEnlistedConnectors.Remove(transaction);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
internal virtual bool TryRentEnlistedPending(Transaction transaction, NpgsqlConnection connection,
|
|
[NotNullWhen(true)] out NpgsqlConnector? connector)
|
|
{
|
|
lock (_pendingEnlistedConnectors)
|
|
{
|
|
if (!_pendingEnlistedConnectors.TryGetValue(transaction, out var list))
|
|
{
|
|
connector = null;
|
|
return false;
|
|
}
|
|
connector = list[list.Count - 1];
|
|
list.RemoveAt(list.Count - 1);
|
|
if (list.Count == 0)
|
|
_pendingEnlistedConnectors.Remove(transaction);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
} |