diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/ProviderBase/DbConnectionPoolGroup.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/ProviderBase/DbConnectionPoolGroup.cs
index 51109fc388..4fc7e89f67 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/ProviderBase/DbConnectionPoolGroup.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/ProviderBase/DbConnectionPoolGroup.cs
@@ -149,7 +149,7 @@ internal DbConnectionPool GetConnectionPool(DbConnectionFactory connectionFactor
DbConnectionPool pool = null;
if (null != _poolGroupOptions)
{
- DbConnectionPoolIdentity currentIdentity = DbConnectionPoolIdentity.NoIdentity;
+ DbConnectionPoolIdentity currentIdentity = DbConnectionPoolIdentity.s_noIdentity;
if (_poolGroupOptions.PoolByIdentity)
{
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
index 06e35fbe13..84a9fb727c 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -73,6 +73,9 @@
Microsoft\Data\ProviderBase\DbConnectionPoolAuthenticationContext.cs
+
+ Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.cs
+
Microsoft\Data\ProviderBase\DbConnectionPoolAuthenticationContextKey.cs
@@ -482,7 +485,9 @@
-
+
+ Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.cs
+
Microsoft\Data\SqlClient\EnclaveDelegate.cs
@@ -490,7 +495,6 @@
Microsoft\Data\SqlClient\EnclavePackage.cs
-
@@ -651,7 +655,9 @@
-
+
+ Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.Unix.cs
+
@@ -663,7 +669,9 @@
-
+
+ Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.Windows.cs
+
Common\Interop\Windows\kernel32\Interop.LoadLibraryEx.cs
@@ -808,7 +816,9 @@
-
+
+ Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.Unix.cs
+
Common\System\Net\Security\NegotiateStreamPal.Unix.cs
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.NetCoreApp.cs
index 11c153e5b3..4a284d64a9 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.NetCoreApp.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.NetCoreApp.cs
@@ -26,28 +26,19 @@ private bool IsBlockingPeriodEnabled()
{
return true;
}
- var policy = poolGroupConnectionOptions.PoolBlockingPeriod;
- switch (policy)
+ switch (poolGroupConnectionOptions.PoolBlockingPeriod)
{
case PoolBlockingPeriod.Auto:
- {
- return !ADP.IsAzureSqlServerEndpoint(poolGroupConnectionOptions.DataSource);
- }
+ return !ADP.IsAzureSqlServerEndpoint(poolGroupConnectionOptions.DataSource);
case PoolBlockingPeriod.AlwaysBlock:
- {
- return true; //Enabled
- }
+ return true;
case PoolBlockingPeriod.NeverBlock:
- {
- return false; //Disabled
- }
+ return false;
default:
- {
- //we should never get into this path.
- Debug.Fail("Unknown PoolBlockingPeriod. Please specify explicit results in above switch case statement.");
- return true;
- }
+ Debug.Fail("Unknown PoolBlockingPeriod. Please specify explicit results in above switch case statement.");
+ return true;
+
}
}
}
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs
index c6f5a39693..7fe76d8c3b 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs
@@ -7,6 +7,9 @@
using System.Collections.Generic;
using System.Data.Common;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
using System.Transactions;
@@ -15,7 +18,7 @@
namespace Microsoft.Data.ProviderBase
{
- sealed internal partial class DbConnectionPool
+ internal sealed partial class DbConnectionPool
{
private enum State
{
@@ -27,21 +30,17 @@ private enum State
// This class is a way to stash our cloned Tx key for later disposal when it's no longer needed.
// We can't get at the key in the dictionary without enumerating entries, so we stash an extra
// copy as part of the value.
- sealed private class TransactedConnectionList : List
+ private sealed class TransactedConnectionList : List
{
- private Transaction _transaction;
- internal TransactedConnectionList(int initialAllocation, Transaction tx) : base(initialAllocation)
+ private readonly Transaction _transaction;
+
+ internal TransactedConnectionList(int initialAllocation, Transaction tx)
+ : base(initialAllocation)
{
_transaction = tx;
}
- internal void Dispose()
- {
- if (null != _transaction)
- {
- _transaction.Dispose();
- }
- }
+ internal void Dispose() => _transaction?.Dispose();
}
private sealed class PendingGetConnection
@@ -53,49 +52,37 @@ public PendingGetConnection(long dueTime, DbConnection owner, TaskCompletionSour
Completion = completion;
UserOptions = userOptions;
}
+
public long DueTime { get; private set; }
public DbConnection Owner { get; private set; }
public TaskCompletionSource Completion { get; private set; }
public DbConnectionOptions UserOptions { get; private set; }
}
- sealed private class TransactedConnectionPool
+ private sealed class TransactedConnectionPool
{
- Dictionary _transactedCxns;
+ private static int s_objectTypeCount;
- DbConnectionPool _pool;
-
- private static int _objectTypeCount; // EventSource Counter
- internal readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);
+ private readonly Dictionary _transactedCxns;
+ private readonly DbConnectionPool _pool;
+ private readonly int _objectID;
internal TransactedConnectionPool(DbConnectionPool pool)
{
- Debug.Assert(null != pool, "null pool?");
-
+ Debug.Assert(pool != null, "null pool?");
+ _objectID = Interlocked.Increment(ref s_objectTypeCount);
_pool = pool;
_transactedCxns = new Dictionary();
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Constructed for connection pool {1}", ObjectID, _pool.ObjectID);
}
- internal int ObjectID
- {
- get
- {
- return _objectID;
- }
- }
+ internal int ObjectID => _objectID;
- internal DbConnectionPool Pool
- {
- get
- {
- return _pool;
- }
- }
+ internal DbConnectionPool Pool => _pool;
internal DbConnectionInternal GetTransactedObject(Transaction transaction)
{
- Debug.Assert(null != transaction, "null transaction?");
+ Debug.Assert(transaction != null, "null transaction?");
DbConnectionInternal transactedObject = null;
@@ -131,7 +118,7 @@ internal DbConnectionInternal GetTransactedObject(Transaction transaction)
}
}
- if (null != transactedObject)
+ if (transactedObject != null)
{
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Transaction {1}, Connection {2}, Popped.", ObjectID, transaction.GetHashCode(), transactedObject.ObjectID);
}
@@ -140,8 +127,8 @@ internal DbConnectionInternal GetTransactedObject(Transaction transaction)
internal void PutTransactedObject(Transaction transaction, DbConnectionInternal transactedObject)
{
- Debug.Assert(null != transaction, "null transaction?");
- Debug.Assert(null != transactedObject, "null transactedObject?");
+ Debug.Assert(transaction != null, "null transaction?");
+ Debug.Assert(transactedObject != null, "null transactedObject?");
TransactedConnectionList connections;
bool txnFound = false;
@@ -213,7 +200,7 @@ internal void PutTransactedObject(Transaction transaction, DbConnectionInternal
}
finally
{
- if (null != transactionClone)
+ if (transactionClone != null)
{
if (newConnections != null)
{
@@ -237,7 +224,6 @@ internal void PutTransactedObject(Transaction transaction, DbConnectionInternal
internal void TransactionEnded(Transaction transaction, DbConnectionInternal transactedObject)
{
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Transaction {1}, Connection {2}, Transaction Completed", ObjectID, transaction.GetHashCode(), transactedObject.ObjectID);
- TransactedConnectionList connections;
int entry = -1;
// NOTE: because TransactionEnded is an asynchronous notification, there's no guarantee
@@ -250,7 +236,7 @@ internal void TransactionEnded(Transaction transaction, DbConnectionInternal tra
lock (_transactedCxns)
{
- if (_transactedCxns.TryGetValue(transaction, out connections))
+ if (_transactedCxns.TryGetValue(transaction, out TransactedConnectionList connections))
{
Debug.Assert(connections != null);
@@ -346,79 +332,72 @@ internal WaitHandle[] GetHandles(bool withCreate)
}
}
- private const int MAX_Q_SIZE = (int)0x00100000;
+ private const int MAX_Q_SIZE = 0x00100000;
// The order of these is important; we want the WaitAny call to be signaled
// for a free object before a creation signal. Only the index first signaled
// object is returned from the WaitAny call.
- private const int SEMAPHORE_HANDLE = (int)0x0;
- private const int ERROR_HANDLE = (int)0x1;
- private const int CREATION_HANDLE = (int)0x2;
- private const int BOGUS_HANDLE = (int)0x3;
+ private const int SEMAPHORE_HANDLE = 0x0;
+ private const int ERROR_HANDLE = 0x1;
+ private const int CREATION_HANDLE = 0x2;
+ private const int BOGUS_HANDLE = 0x3;
private const int ERROR_WAIT_DEFAULT = 5 * 1000; // 5 seconds
// we do want a testable, repeatable set of generated random numbers
private static readonly Random s_random = new Random(5101977); // Value obtained from Dave Driver
+ private static int s_objectTypeCount;
+ private readonly int _objectID;
+ private readonly WaitCallback _poolCreateRequest;
+ private readonly PoolWaitHandles _waitHandles;
+ private readonly TransactedConnectionPool _transactedConnectionPool;
+ private readonly List _objectList;
+ private readonly ConcurrentStack _stackOld;
+ private readonly ConcurrentStack _stackNew;
+ private readonly ConcurrentQueue _pendingOpens;
+ ///
+ /// The private member which carries the set of authenticationcontexts for this pool (based on the user's identity).
+ ///
+ private readonly ConcurrentDictionary _pooledDbAuthenticationContexts;
private readonly int _cleanupWait;
private readonly DbConnectionPoolIdentity _identity;
-
private readonly DbConnectionFactory _connectionFactory;
private readonly DbConnectionPoolGroup _connectionPoolGroup;
private readonly DbConnectionPoolGroupOptions _connectionPoolGroupOptions;
- private DbConnectionPoolProviderInfo _connectionPoolProviderInfo;
-
- ///
- /// The private member which carries the set of authenticationcontexts for this pool (based on the user's identity).
- ///
- private readonly ConcurrentDictionary _pooledDbAuthenticationContexts;
+ private readonly DbConnectionPoolProviderInfo _connectionPoolProviderInfo;
private State _state;
-
- private readonly ConcurrentStack _stackOld = new ConcurrentStack();
- private readonly ConcurrentStack _stackNew = new ConcurrentStack();
-
- private readonly ConcurrentQueue _pendingOpens = new ConcurrentQueue();
private int _pendingOpensWaiting = 0;
-
- private readonly WaitCallback _poolCreateRequest;
-
private int _waitCount;
- private readonly PoolWaitHandles _waitHandles;
-
private Exception _resError;
- private volatile bool _errorOccurred;
-
private int _errorWait;
private Timer _errorTimer;
-
private Timer _cleanupTimer;
-
- private readonly TransactedConnectionPool _transactedConnectionPool;
-
- private readonly List _objectList;
private int _totalObjects;
- private static int _objectTypeCount; // EventSource counter
- internal readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);
+ private volatile bool _errorOccurred;
// only created by DbConnectionPoolGroup.GetConnectionPool
internal DbConnectionPool(
- DbConnectionFactory connectionFactory,
- DbConnectionPoolGroup connectionPoolGroup,
- DbConnectionPoolIdentity identity,
- DbConnectionPoolProviderInfo connectionPoolProviderInfo)
+ DbConnectionFactory connectionFactory,
+ DbConnectionPoolGroup connectionPoolGroup,
+ DbConnectionPoolIdentity identity,
+ DbConnectionPoolProviderInfo connectionPoolProviderInfo)
{
- Debug.Assert(null != connectionPoolGroup, "null connectionPoolGroup");
+ Debug.Assert(connectionPoolGroup != null, "null connectionPoolGroup");
- if ((null != identity) && identity.IsRestricted)
+ if ((identity != null) && identity.IsRestricted)
{
throw ADP.InternalError(ADP.InternalErrorCode.AttemptingToPoolOnRestrictedToken);
}
_state = State.Initializing;
+ _objectID = Interlocked.Increment(ref s_objectTypeCount);
+ _stackOld = new ConcurrentStack();
+ _stackNew = new ConcurrentStack();
+ _pendingOpens = new ConcurrentQueue();
lock (s_random)
{ // Random.Next is not thread-safe
@@ -430,73 +409,58 @@ internal DbConnectionPool(
_connectionPoolGroupOptions = connectionPoolGroup.PoolGroupOptions;
_connectionPoolProviderInfo = connectionPoolProviderInfo;
_identity = identity;
-
_waitHandles = new PoolWaitHandles();
-
_errorWait = ERROR_WAIT_DEFAULT;
- _errorTimer = null; // No error yet.
-
+ _errorTimer = null;
_objectList = new List(MaxPoolSize);
-
- _pooledDbAuthenticationContexts = new ConcurrentDictionary(concurrencyLevel: 4 * Environment.ProcessorCount /* default value in ConcurrentDictionary*/,
- capacity: 2);
-
- _transactedConnectionPool = new TransactedConnectionPool(this); // initialize irrespective of platform
-
+ _pooledDbAuthenticationContexts = new ConcurrentDictionary(
+ concurrencyLevel: 4 * Environment.ProcessorCount /* default value in ConcurrentDictionary*/,
+ capacity: 2
+ );
+ _transactedConnectionPool = new TransactedConnectionPool(this);
_poolCreateRequest = new WaitCallback(PoolCreateRequest); // used by CleanupCallback
_state = State.Running;
+
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Constructed.", ObjectID);
//_cleanupTimer & QueuePoolCreateRequest is delayed until DbConnectionPoolGroup calls
// StartBackgroundCallbacks after pool is actually in the collection
}
- private int CreationTimeout
- {
- get { return PoolGroupOptions.CreationTimeout; }
- }
+ private int CreationTimeout => PoolGroupOptions.CreationTimeout;
- internal int Count
- {
- get { return _totalObjects; }
- }
+ internal int Count => _totalObjects;
- internal DbConnectionFactory ConnectionFactory
- {
- get { return _connectionFactory; }
- }
+ internal DbConnectionFactory ConnectionFactory => _connectionFactory;
- internal bool ErrorOccurred
- {
- get { return _errorOccurred; }
- }
+ internal bool ErrorOccurred => _errorOccurred;
- private bool HasTransactionAffinity
- {
- get { return PoolGroupOptions.HasTransactionAffinity; }
- }
+ private bool HasTransactionAffinity => PoolGroupOptions.HasTransactionAffinity;
- internal TimeSpan LoadBalanceTimeout
- {
- get { return PoolGroupOptions.LoadBalanceTimeout; }
- }
+ internal TimeSpan LoadBalanceTimeout => PoolGroupOptions.LoadBalanceTimeout;
private bool NeedToReplenish
{
get
{
- if (State.Running != _state) // Don't allow connection create when not running.
+ if (_state != State.Running) // Don't allow connection create when not running.
+ {
return false;
+ }
int totalObjects = Count;
if (totalObjects >= MaxPoolSize)
+ {
return false;
+ }
if (totalObjects < MinPoolSize)
+ {
return true;
+ }
- int freeObjects = (_stackNew.Count + _stackOld.Count);
+ int freeObjects = _stackNew.Count + _stackOld.Count;
int waitingRequests = _waitCount;
bool needToReplenish = (freeObjects < waitingRequests) || ((freeObjects == waitingRequests) && (totalObjects > 1));
@@ -504,69 +468,30 @@ private bool NeedToReplenish
}
}
- internal DbConnectionPoolIdentity Identity
- {
- get { return _identity; }
- }
+ internal DbConnectionPoolIdentity Identity => _identity;
- internal bool IsRunning
- {
- get { return State.Running == _state; }
- }
+ internal bool IsRunning => State.Running == _state;
- private int MaxPoolSize
- {
- get { return PoolGroupOptions.MaxPoolSize; }
- }
+ private int MaxPoolSize => PoolGroupOptions.MaxPoolSize;
- private int MinPoolSize
- {
- get { return PoolGroupOptions.MinPoolSize; }
- }
+ private int MinPoolSize => PoolGroupOptions.MinPoolSize;
- internal int ObjectID
- {
- get
- {
- return _objectID;
- }
- }
+ internal int ObjectID => _objectID;
- internal DbConnectionPoolGroup PoolGroup
- {
- get { return _connectionPoolGroup; }
- }
+ internal DbConnectionPoolGroup PoolGroup => _connectionPoolGroup;
- internal DbConnectionPoolGroupOptions PoolGroupOptions
- {
- get { return _connectionPoolGroupOptions; }
- }
+ internal DbConnectionPoolGroupOptions PoolGroupOptions => _connectionPoolGroupOptions;
- internal DbConnectionPoolProviderInfo ProviderInfo
- {
- get { return _connectionPoolProviderInfo; }
- }
+ internal DbConnectionPoolProviderInfo ProviderInfo => _connectionPoolProviderInfo;
///
/// Return the pooled authentication contexts.
///
- internal ConcurrentDictionary AuthenticationContexts
- {
- get
- {
- return _pooledDbAuthenticationContexts;
- }
- }
+ internal ConcurrentDictionary AuthenticationContexts => _pooledDbAuthenticationContexts;
- internal bool UseLoadBalancing
- {
- get { return PoolGroupOptions.UseLoadBalancing; }
- }
+ internal bool UseLoadBalancing => PoolGroupOptions.UseLoadBalancing;
- private bool UsingIntegrateSecurity
- {
- get { return (null != _identity && DbConnectionPoolIdentity.NoIdentity != _identity); }
- }
+ private bool UsingIntegrateSecurity => _identity != null && DbConnectionPoolIdentity.s_noIdentity != _identity;
private void CleanupCallback(object state)
{
@@ -596,9 +521,8 @@ private void CleanupCallback(object state)
if (_waitHandles.PoolSemaphore.WaitOne(0))
{
// We obtained a objects from the semaphore.
- DbConnectionInternal obj;
- if (_stackOld.TryPop(out obj))
+ if (_stackOld.TryPop(out DbConnectionInternal obj))
{
Debug.Assert(obj != null, "null connection is not expected");
// If we obtained one from the old stack, destroy it.
@@ -655,10 +579,10 @@ private void CleanupCallback(object state)
{
for (; ; )
{
- DbConnectionInternal obj;
-
- if (!_stackNew.TryPop(out obj))
+ if (!_stackNew.TryPop(out DbConnectionInternal obj))
+ {
break;
+ }
Debug.Assert(obj != null, "null connection is not expected");
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, ChangeStacks={1}", ObjectID, obj.ObjectID);
@@ -688,7 +612,7 @@ internal void Clear()
{
obj = _objectList[i];
- if (null != obj)
+ if (obj != null)
{
obj.DoNotPoolThisConnection();
}
@@ -715,12 +639,7 @@ internal void Clear()
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Cleared.", ObjectID);
}
- private Timer CreateCleanupTimer() =>
- ADP.UnsafeCreateTimer(
- new TimerCallback(CleanupCallback),
- null,
- _cleanupWait,
- _cleanupWait);
+ private Timer CreateCleanupTimer() => new Timer(new TimerCallback(CleanupCallback), null, _cleanupWait, _cleanupWait);
private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
{
@@ -729,7 +648,7 @@ private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectio
try
{
newObj = _connectionFactory.CreatePooledConnection(this, owningObject, _connectionPoolGroup.ConnectionOptions, _connectionPoolGroup.PoolKey, userOptions);
- if (null == newObj)
+ if (newObj == null)
{
throw ADP.InternalError(ADP.InternalErrorCode.CreateObjectReturnedNull); // CreateObject succeeded, but null object
}
@@ -753,7 +672,7 @@ private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectio
// If the old connection belonged to another pool, we need to remove it from that
if (oldConnection != null)
{
- var oldConnectionPool = oldConnection.Pool;
+ DbConnectionPool oldConnectionPool = oldConnection.Pool;
if (oldConnectionPool != null && oldConnectionPool != this)
{
Debug.Assert(oldConnectionPool._state == State.ShuttingDown, "Old connections pool should be shutting down");
@@ -792,9 +711,10 @@ private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectio
// Make sure the timer starts even if ThreadAbort occurs after setting the ErrorEvent.
// timer allocation has to be done out of CER block
- Timer t = new Timer(new TimerCallback(this.ErrorCallback), null, Timeout.Infinite, Timeout.Infinite);
+ Timer t = new Timer(new TimerCallback(ErrorCallback), null, Timeout.Infinite, Timeout.Infinite);
bool timerIsNotDisposed;
+ RuntimeHelpers.PrepareConstrainedRegions();
try
{ }
finally
@@ -890,7 +810,7 @@ private void DeactivateObject(DbConnectionInternal obj)
// thread.
Transaction transaction = obj.EnlistedTransaction;
- if (null != transaction)
+ if (transaction != null)
{
// NOTE: we're not locking on _state, so it's possible that its
// value could change between the conditional check and here.
@@ -995,26 +915,26 @@ private void ErrorCallback(object state)
_waitHandles.ErrorEvent.Reset();
// the error state is cleaned, destroy the timer to avoid periodic invocation
- Timer t = _errorTimer;
+ Timer timer = _errorTimer;
_errorTimer = null;
- if (t != null)
- {
- t.Dispose(); // Cancel timer request.
- }
+ timer?.Dispose();
}
private Exception TryCloneCachedException()
// Cached exception can be of any type, so is not always cloneable.
// This functions clones SqlException
- // OleDb and Odbc connections are not passing throw this code
+ // OleDb and Odbc connections are not passing through this code
{
- if (_resError == null)
+ if (_resError is null)
+ {
return null;
+ }
- var sqlError = _resError as SqlClient.SqlException;
- if (sqlError != null)
+ if (_resError is SqlException sqlError)
+ {
return sqlError.InternalClone();
+ }
return _resError;
}
@@ -1027,8 +947,11 @@ private void WaitForPendingOpen()
{
bool started = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
try
{
+
+ RuntimeHelpers.PrepareConstrainedRegions();
try
{ }
finally
@@ -1062,6 +985,7 @@ private void WaitForPendingOpen()
bool timeout = false;
Exception caughtException = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
try
{
bool allowCreate = true;
@@ -1114,7 +1038,9 @@ internal bool TryGetConnection(DbConnection owningObject, TaskCompletionSource= MaxPoolSize && 0 != MaxPoolSize)
+ if (Count >= MaxPoolSize && MaxPoolSize != 0)
{
if (!ReclaimEmancipatedObjects())
{
@@ -1266,6 +1199,7 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj
{
if (_waitHandles.CreationSemaphore.WaitOne(unchecked((int)waitForMultipleObjectsTimeout)))
{
+ RuntimeHelpers.PrepareConstrainedRegions();
try
{
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Creating new connection.", ObjectID);
@@ -1302,15 +1236,15 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj
}
// Do not use this pooled connection if access token is about to expire soon before we can connect.
- if (null != obj && obj.IsAccessTokenExpired)
+ if (obj != null && obj.IsAccessTokenExpired)
{
DestroyObject(obj);
obj = null;
}
- } while (null == obj);
+ } while (obj == null);
}
- if (null != obj)
+ if (obj != null)
{
PrepareConnection(owningObject, obj, transaction);
}
@@ -1334,7 +1268,7 @@ private void PrepareConnection(DbConnection owningObject, DbConnectionInternal o
{
// if Activate throws an exception
// put it back in the pool or have it properly disposed of
- this.PutObject(obj, owningObject);
+ PutObject(obj, owningObject);
throw;
}
}
@@ -1365,9 +1299,8 @@ internal DbConnectionInternal ReplaceConnection(DbConnection owningObject, DbCon
private DbConnectionInternal GetFromGeneralPool()
{
- DbConnectionInternal obj = null;
- if (!_stackNew.TryPop(out obj))
+ if (!_stackNew.TryPop(out DbConnectionInternal obj))
{
if (!_stackOld.TryPop(out obj))
{
@@ -1388,12 +1321,12 @@ private DbConnectionInternal GetFromGeneralPool()
// following assert to fire, which really mucks up stress against
// checked bits.
- if (null != obj)
+ if (obj != null)
{
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Connection {1}, Popped from general pool.", ObjectID, obj.ObjectID);
SqlClientEventSource.Log.ExitFreeConnection();
}
- return (obj);
+ return obj;
}
private DbConnectionInternal GetFromTransactedPool(out Transaction transaction)
@@ -1401,11 +1334,11 @@ private DbConnectionInternal GetFromTransactedPool(out Transaction transaction)
transaction = ADP.GetCurrentTransaction();
DbConnectionInternal obj = null;
- if (null != transaction && null != _transactedConnectionPool)
+ if (transaction != null && _transactedConnectionPool != null)
{
obj = _transactedConnectionPool.GetTransactedObject(transaction);
- if (null != obj)
+ if (obj != null)
{
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Connection {1}, Popped from transacted pool.", ObjectID, obj.ObjectID);
SqlClientEventSource.Log.ExitFreeConnection();
@@ -1434,6 +1367,8 @@ private DbConnectionInternal GetFromTransactedPool(out Transaction transaction)
return obj;
}
+ [ResourceExposure(ResourceScope.None)] // SxS: this method does not expose resources
+ [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
private void PoolCreateRequest(object state)
{
// called by pooler to ensure pool requests are currently being satisfied -
@@ -1441,14 +1376,16 @@ private void PoolCreateRequest(object state)
long scopeID = SqlClientEventSource.Log.TryPoolerScopeEnterEvent(" {0}", ObjectID);
try
{
- if (State.Running == _state)
+ if (_state == State.Running)
{
// in case WaitForPendingOpen ever failed with no subsequent OpenAsync calls,
// start it back up again
if (!_pendingOpens.IsEmpty && _pendingOpensWaiting == 0)
{
- Thread waitOpenThread = new Thread(WaitForPendingOpen);
- waitOpenThread.IsBackground = true;
+ Thread waitOpenThread = new Thread(WaitForPendingOpen)
+ {
+ IsBackground = true
+ };
waitOpenThread.Start();
}
@@ -1471,8 +1408,11 @@ private void PoolCreateRequest(object state)
return;
}
int waitResult = BOGUS_HANDLE;
+
+ RuntimeHelpers.PrepareConstrainedRegions();
try
{
+ RuntimeHelpers.PrepareConstrainedRegions();
try
{ }
finally
@@ -1557,7 +1497,7 @@ private void PoolCreateRequest(object state)
internal void PutNewObject(DbConnectionInternal obj)
{
- Debug.Assert(null != obj, "why are we adding a null object to the pool?");
+ Debug.Assert(obj != null, "why are we adding a null object to the pool?");
// Debug.Assert(obj.CanBePooled, "non-poolable object in pool");
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Connection {1}, Pushing to general pool.", ObjectID, obj.ObjectID);
@@ -1568,7 +1508,7 @@ internal void PutNewObject(DbConnectionInternal obj)
internal void PutObject(DbConnectionInternal obj, object owningObject)
{
- Debug.Assert(null != obj, "null obj?");
+ Debug.Assert(obj != null, "null obj");
SqlClientEventSource.Log.SoftDisconnectRequest();
// Once a connection is closing (which is the state that we're in at
@@ -1593,7 +1533,7 @@ internal void PutObject(DbConnectionInternal obj, object owningObject)
internal void PutObjectFromTransactedPool(DbConnectionInternal obj)
{
- Debug.Assert(null != obj, "null pooledObject?");
+ Debug.Assert(obj != null, "null pooledObject?");
Debug.Assert(obj.EnlistedTransaction == null, "pooledObject is still enlisted?");
// called by the transacted connection pool , once it's removed the
@@ -1619,7 +1559,7 @@ internal void PutObjectFromTransactedPool(DbConnectionInternal obj)
private void QueuePoolCreateRequest()
{
- if (State.Running == _state)
+ if (_state == State.Running)
{
// Make sure we're at quota by posting a callback to the threadpool.
ThreadPool.QueueUserWorkItem(_poolCreateRequest);
@@ -1641,7 +1581,7 @@ private bool ReclaimEmancipatedObjects()
{
DbConnectionInternal obj = _objectList[i];
- if (null != obj)
+ if (obj != null)
{
bool locked = false;
@@ -1708,12 +1648,9 @@ internal void Shutdown()
_state = State.ShuttingDown;
// deactivate timer callbacks
- Timer t = _cleanupTimer;
+ Timer timer = _cleanupTimer;
_cleanupTimer = null;
- if (null != t)
- {
- t.Dispose();
- }
+ timer?.Dispose();
}
// TransactionEnded merely provides the plumbing for DbConnectionInternal to access the transacted pool
@@ -1722,8 +1659,8 @@ internal void Shutdown()
// other objects is unnecessary (hence the asymmetry of Ended but no Begin)
internal void TransactionEnded(Transaction transaction, DbConnectionInternal transactedObject)
{
- Debug.Assert(null != transaction, "null transaction?");
- Debug.Assert(null != transactedObject, "null transactedObject?");
+ Debug.Assert(transaction != null, "null transaction?");
+ Debug.Assert(transactedObject != null, "null transactedObject?");
// Note: connection may still be associated with transaction due to Explicit Unbinding requirement.
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Transaction {1}, Connection {2}, Transaction Completed", ObjectID, transaction.GetHashCode(), transactedObject.ObjectID);
@@ -1733,7 +1670,7 @@ internal void TransactionEnded(Transaction transaction, DbConnectionInternal tra
// the connection from it's list, then we put the connection back in
// general circulation.
TransactedConnectionPool transactedConnectionPool = _transactedConnectionPool;
- if (null != transactedConnectionPool)
+ if (transactedConnectionPool != null)
{
transactedConnectionPool.TransactionEnded(transaction, transactedObject);
}
@@ -1751,12 +1688,14 @@ private DbConnectionInternal UserCreateRequest(DbConnection owningObject, DbConn
}
else
{
- if ((oldConnection != null) || (Count < MaxPoolSize) || (0 == MaxPoolSize))
+ if ((oldConnection != null) || (Count < MaxPoolSize) || (MaxPoolSize == 0))
{
// If we have an odd number of total objects, reclaim any dead objects.
// If we did not find any objects to reclaim, create a new one.
if ((oldConnection != null) || (Count & 0x1) == 0x1 || !ReclaimEmancipatedObjects())
+ {
obj = CreateObject(owningObject, userOptions, oldConnection);
+ }
}
return obj;
}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
index 8391d18c6b..5c9b006852 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
@@ -125,6 +125,12 @@
Microsoft\Data\ProviderBase\DbConnectionPoolOptions.cs
+
+ Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.cs
+
+
+ Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.Windows.cs
+
Microsoft\Data\ProviderBase\DbConnectionPoolGroupProviderInfo.cs
@@ -523,6 +529,7 @@
+
@@ -544,7 +551,6 @@
-
@@ -642,4 +648,4 @@
-
\ No newline at end of file
+
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbBuffer.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbBuffer.cs
index 30a3bc7b99..90f3ff0e34 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbBuffer.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbBuffer.cs
@@ -20,369 +20,33 @@ internal abstract class DbBuffer : SafeHandle
private readonly int _bufferLength;
- private DbBuffer(int initialSize, bool zeroBuffer) : base(IntPtr.Zero, true)
+ internal DbBuffer(int initialSize) : base(IntPtr.Zero, true)
{
- if (0 < initialSize)
+ if (initialSize > 0)
{
- int flags = ((zeroBuffer) ? LMEM_ZEROINIT : LMEM_FIXED);
-
_bufferLength = initialSize;
RuntimeHelpers.PrepareConstrainedRegions();
try
- { }
+ {
+ }
finally
{
- base.handle = SafeNativeMethods.LocalAlloc(flags, (IntPtr)initialSize);
+ handle = SafeNativeMethods.LocalAlloc(LMEM_ZEROINIT, new IntPtr(initialSize));
}
- if (IntPtr.Zero == base.handle)
+ if (handle == IntPtr.Zero)
{
throw new OutOfMemoryException();
}
}
}
- protected DbBuffer(int initialSize) : this(initialSize, true)
- {
- }
-
- protected DbBuffer(IntPtr invalidHandleValue, bool ownsHandle) : base(invalidHandleValue, ownsHandle)
- {
- }
-
- private int BaseOffset { get { return 0; } }
-
- public override bool IsInvalid
- {
- get
- {
- return (IntPtr.Zero == base.handle);
- }
- }
-
- internal int Length
- {
- get
- {
- return _bufferLength;
- }
- }
-
- internal string PtrToStringUni(int offset)
- {
- offset += BaseOffset;
- Validate(offset, 2);
- Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment");
-
- string value = null;
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
- int length = UnsafeNativeMethods.lstrlenW(ptr);
- Validate(offset, (2 * (length + 1)));
- value = Marshal.PtrToStringUni(ptr, length);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
-
- return value;
- }
-
- internal String PtrToStringUni(int offset, int length)
- {
- offset += BaseOffset;
- Validate(offset, 2 * length);
- Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment");
-
- string value = null;
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
- value = Marshal.PtrToStringUni(ptr, length);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- return value;
- }
-
- internal byte ReadByte(int offset)
- {
- offset += BaseOffset;
- ValidateCheck(offset, 1);
- Debug.Assert(0 == offset % 4, "invalid alignment");
-
- byte value;
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = DangerousGetHandle();
- value = Marshal.ReadByte(ptr, offset);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- return value;
- }
-
- internal byte[] ReadBytes(int offset, int length)
- {
- byte[] value = new byte[length];
- return ReadBytes(offset, value, 0, length);
- }
-
- internal byte[] ReadBytes(int offset, byte[] destination, int startIndex, int length)
- {
- offset += BaseOffset;
- Validate(offset, length);
- Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment");
- Debug.Assert(null != destination, "null destination");
- Debug.Assert(startIndex + length <= destination.Length, "destination too small");
-
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
- Marshal.Copy(ptr, destination, startIndex, length);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- return destination;
- }
-
- internal Char ReadChar(int offset)
- {
- short value = ReadInt16(offset);
- return unchecked((char)value);
- }
-
- internal char[] ReadChars(int offset, char[] destination, int startIndex, int length)
- {
- offset += BaseOffset;
- Validate(offset, 2 * length);
- Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment");
- Debug.Assert(null != destination, "null destination");
- Debug.Assert(startIndex + length <= destination.Length, "destination too small");
-
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
- Marshal.Copy(ptr, destination, startIndex, length);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- return destination;
- }
-
- internal Double ReadDouble(int offset)
- {
- Int64 value = ReadInt64(offset);
- return BitConverter.Int64BitsToDouble(value);
- }
-
- internal Int16 ReadInt16(int offset)
- {
- offset += BaseOffset;
- ValidateCheck(offset, 2);
- Debug.Assert(0 == offset % 2, "invalid alignment");
-
- short value;
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = DangerousGetHandle();
- value = Marshal.ReadInt16(ptr, offset);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- return value;
- }
-
- internal void ReadInt16Array(int offset, short[] destination, int startIndex, int length)
- {
- offset += BaseOffset;
- Validate(offset, 2 * length);
- Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment");
- Debug.Assert(null != destination, "null destination");
- Debug.Assert(startIndex + length <= destination.Length, "destination too small");
-
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
- Marshal.Copy(ptr, destination, startIndex, length);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- }
-
- internal Int32 ReadInt32(int offset)
- {
- offset += BaseOffset;
- ValidateCheck(offset, 4);
- Debug.Assert(0 == offset % 4, "invalid alignment");
-
- int value;
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = DangerousGetHandle();
- value = Marshal.ReadInt32(ptr, offset);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- return value;
- }
-
- internal void ReadInt32Array(int offset, int[] destination, int startIndex, int length)
- {
- offset += BaseOffset;
- Validate(offset, 4 * length);
- Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment");
- Debug.Assert(null != destination, "null destination");
- Debug.Assert(startIndex + length <= destination.Length, "destination too small");
-
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
- Marshal.Copy(ptr, destination, startIndex, length);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- }
-
- internal Int64 ReadInt64(int offset)
- {
- offset += BaseOffset;
- ValidateCheck(offset, 8);
- Debug.Assert(0 == offset % IntPtr.Size, "invalid alignment");
+ private int BaseOffset => 0;
- long value;
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
+ public override bool IsInvalid => handle == IntPtr.Zero;
- IntPtr ptr = DangerousGetHandle();
- value = Marshal.ReadInt64(ptr, offset);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- return value;
- }
+ internal int Length => _bufferLength;
- internal IntPtr ReadIntPtr(int offset)
- {
- offset += BaseOffset;
- ValidateCheck(offset, IntPtr.Size);
- Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment");
-
- IntPtr value;
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = DangerousGetHandle();
- value = Marshal.ReadIntPtr(ptr, offset);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- return value;
- }
-
- internal unsafe Single ReadSingle(int offset)
- {
- Int32 value = ReadInt32(offset);
- return *(Single*)&value;
- }
-
- override protected bool ReleaseHandle()
+ protected override bool ReleaseHandle()
{
// NOTE: The SafeHandle class guarantees this will be called exactly once.
IntPtr ptr = base.handle;
@@ -394,236 +58,6 @@ override protected bool ReleaseHandle()
return true;
}
- private void StructureToPtr(int offset, object structure)
- {
- Debug.Assert(null != structure, "null structure");
- offset += BaseOffset;
- ValidateCheck(offset, Marshal.SizeOf(structure.GetType()));
- Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment");
-
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
- Marshal.StructureToPtr(structure, ptr, false/*fDeleteOld*/);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- }
-
- internal void WriteByte(int offset, byte value)
- {
- offset += BaseOffset;
- ValidateCheck(offset, 1);
- Debug.Assert(0 == offset % 4, "invalid alignment");
-
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = DangerousGetHandle();
- Marshal.WriteByte(ptr, offset, value);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- }
-
- internal void WriteBytes(int offset, byte[] source, int startIndex, int length)
- {
- offset += BaseOffset;
- Validate(offset, length);
- Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment");
- Debug.Assert(null != source, "null source");
- Debug.Assert(startIndex + length <= source.Length, "source too small");
-
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
- Marshal.Copy(source, startIndex, ptr, length);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- }
-
- internal void WriteCharArray(int offset, char[] source, int startIndex, int length)
- {
- offset += BaseOffset;
- Validate(offset, 2 * length);
- Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment");
- Debug.Assert(null != source, "null source");
- Debug.Assert(startIndex + length <= source.Length, "source too small");
-
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
- Marshal.Copy(source, startIndex, ptr, length);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- }
-
- internal void WriteDouble(int offset, Double value)
- {
- WriteInt64(offset, BitConverter.DoubleToInt64Bits(value));
- }
-
- internal void WriteInt16(int offset, short value)
- {
- offset += BaseOffset;
- ValidateCheck(offset, 2);
- Debug.Assert(0 == offset % 2, "invalid alignment");
-
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = DangerousGetHandle();
- Marshal.WriteInt16(ptr, offset, value);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- }
-
- internal void WriteInt16Array(int offset, short[] source, int startIndex, int length)
- {
- offset += BaseOffset;
- Validate(offset, 2 * length);
- Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment");
- Debug.Assert(null != source, "null source");
- Debug.Assert(startIndex + length <= source.Length, "source too small");
-
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
- Marshal.Copy(source, startIndex, ptr, length);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- }
-
- internal void WriteInt32(int offset, int value)
- {
- offset += BaseOffset;
- ValidateCheck(offset, 4);
- Debug.Assert(0 == offset % 4, "invalid alignment");
-
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = DangerousGetHandle();
- Marshal.WriteInt32(ptr, offset, value);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- }
-
- internal void WriteInt32Array(int offset, int[] source, int startIndex, int length)
- {
- offset += BaseOffset;
- Validate(offset, 4 * length);
- Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment");
- Debug.Assert(null != source, "null source");
- Debug.Assert(startIndex + length <= source.Length, "source too small");
-
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
- Marshal.Copy(source, startIndex, ptr, length);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- }
-
- internal void WriteInt64(int offset, long value)
- {
- offset += BaseOffset;
- ValidateCheck(offset, 8);
- Debug.Assert(0 == offset % IntPtr.Size, "invalid alignment");
-
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = DangerousGetHandle();
- Marshal.WriteInt64(ptr, offset, value);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- }
-
internal void WriteIntPtr(int offset, IntPtr value)
{
offset += BaseOffset;
@@ -648,155 +82,9 @@ internal void WriteIntPtr(int offset, IntPtr value)
}
}
- internal unsafe void WriteSingle(int offset, Single value)
- {
- WriteInt32(offset, *(Int32*)&value);
- }
-
- internal void ZeroMemory()
- {
- bool mustRelease = false;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- DangerousAddRef(ref mustRelease);
-
- IntPtr ptr = DangerousGetHandle();
- SafeNativeMethods.ZeroMemory(ptr, (IntPtr)Length);
- }
- finally
- {
- if (mustRelease)
- {
- DangerousRelease();
- }
- }
- }
-
- internal Guid ReadGuid(int offset)
- {
- // faster than Marshal.PtrToStructure(offset, typeof(Guid))
- byte[] buffer = new byte[16];
- ReadBytes(offset, buffer, 0, 16);
- return new Guid(buffer);
- }
- internal void WriteGuid(int offset, Guid value)
- {
- // faster than Marshal.Copy(value.GetByteArray()
- StructureToPtr(offset, value);
- }
- internal DateTime ReadDate(int offset)
- {
- short[] buffer = new short[3];
- ReadInt16Array(offset, buffer, 0, 3);
- return new DateTime(
- unchecked((ushort)buffer[0]), // Year
- unchecked((ushort)buffer[1]), // Month
- unchecked((ushort)buffer[2])); // Day
- }
- internal void WriteDate(int offset, DateTime value)
- {
- short[] buffer = new short[3] {
- unchecked((short)value.Year),
- unchecked((short)value.Month),
- unchecked((short)value.Day),
- };
- WriteInt16Array(offset, buffer, 0, 3);
- }
-
- internal TimeSpan ReadTime(int offset)
- {
- short[] buffer = new short[3];
- ReadInt16Array(offset, buffer, 0, 3);
- return new TimeSpan(
- unchecked((ushort)buffer[0]), // Hours
- unchecked((ushort)buffer[1]), // Minutes
- unchecked((ushort)buffer[2])); // Seconds
- }
- internal void WriteTime(int offset, TimeSpan value)
- {
- short[] buffer = new short[3] {
- unchecked((short)value.Hours),
- unchecked((short)value.Minutes),
- unchecked((short)value.Seconds),
- };
- WriteInt16Array(offset, buffer, 0, 3);
- }
-
- internal DateTime ReadDateTime(int offset)
- {
- short[] buffer = new short[6];
- ReadInt16Array(offset, buffer, 0, 6);
- int ticks = ReadInt32(offset + 12);
- DateTime value = new DateTime(
- unchecked((ushort)buffer[0]), // Year
- unchecked((ushort)buffer[1]), // Month
- unchecked((ushort)buffer[2]), // Day
- unchecked((ushort)buffer[3]), // Hours
- unchecked((ushort)buffer[4]), // Minutes
- unchecked((ushort)buffer[5])); // Seconds
- return value.AddTicks(ticks / 100);
- }
- internal void WriteDateTime(int offset, DateTime value)
- {
- int ticks = (int)(value.Ticks % 10000000L) * 100;
- short[] buffer = new short[6] {
- unchecked((short)value.Year),
- unchecked((short)value.Month),
- unchecked((short)value.Day),
- unchecked((short)value.Hour),
- unchecked((short)value.Minute),
- unchecked((short)value.Second),
- };
- WriteInt16Array(offset, buffer, 0, 6);
- WriteInt32(offset + 12, ticks);
- }
-
- internal Decimal ReadNumeric(int offset)
- {
- byte[] bits = new byte[20];
- ReadBytes(offset, bits, 1, 19);
-
- int[] buffer = new int[4];
- buffer[3] = ((int)bits[2]) << 16; // scale
- if (0 == bits[3])
- {
- buffer[3] |= unchecked((int)0x80000000); //sign
- }
- buffer[0] = BitConverter.ToInt32(bits, 4); // low
- buffer[1] = BitConverter.ToInt32(bits, 8); // mid
- buffer[2] = BitConverter.ToInt32(bits, 12); // high
- if (0 != BitConverter.ToInt32(bits, 16))
- {
- throw ADP.NumericToDecimalOverflow();
- }
- return new Decimal(buffer);
- }
-
- internal void WriteNumeric(int offset, Decimal value, byte precision)
- {
- int[] tmp = Decimal.GetBits(value);
- byte[] buffer = new byte[20];
-
- buffer[1] = precision;
- Buffer.BlockCopy(tmp, 14, buffer, 2, 2); // copy sign and scale
- buffer[3] = (Byte)((0 == buffer[3]) ? 1 : 0); // flip sign for native
- Buffer.BlockCopy(tmp, 0, buffer, 4, 12);
- buffer[16] = 0;
- buffer[17] = 0;
- buffer[18] = 0;
- buffer[19] = 0;
- WriteBytes(offset, buffer, 1, 19);
- }
-
- [ConditionalAttribute("DEBUG")]
+ [Conditional("DEBUG")]
protected void ValidateCheck(int offset, int count)
- {
- Validate(offset, count);
- }
-
- protected void Validate(int offset, int count)
{
if ((offset < 0) || (count < 0) || (Length < checked(offset + count)))
{
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs
index 8d04056add..453621a396 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs
@@ -2,27 +2,25 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Data.Common;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Transactions;
+using Microsoft.Data.Common;
+using Microsoft.Data.SqlClient;
+
namespace Microsoft.Data.ProviderBase
{
-
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Data.Common;
- using System.Diagnostics;
- using System.Diagnostics.CodeAnalysis;
- using System.Runtime.CompilerServices;
- using System.Runtime.ConstrainedExecution;
- using System.Runtime.InteropServices;
- using System.Runtime.Versioning;
- using System.Threading;
- using System.Threading.Tasks;
- using Microsoft.Data.Common;
- using Microsoft.Data.SqlClient;
-
- using SysTx = System.Transactions;
-
- sealed internal class DbConnectionPool
+ internal sealed partial class DbConnectionPool
{
private enum State
{
@@ -34,24 +32,20 @@ private enum State
// This class is a way to stash our cloned Tx key for later disposal when it's no longer needed.
// We can't get at the key in the dictionary without enumerating entries, so we stash an extra
// copy as part of the value.
- sealed private class TransactedConnectionList : List
+ private sealed class TransactedConnectionList : List
{
- private SysTx.Transaction _transaction;
- internal TransactedConnectionList(int initialAllocation, SysTx.Transaction tx) : base(initialAllocation)
+ private readonly Transaction _transaction;
+
+ internal TransactedConnectionList(int initialAllocation, Transaction tx)
+ : base(initialAllocation)
{
_transaction = tx;
}
- internal void Dispose()
- {
- if (null != _transaction)
- {
- _transaction.Dispose();
- }
- }
+ internal void Dispose() => _transaction?.Dispose();
}
- sealed class PendingGetConnection
+ private sealed class PendingGetConnection
{
public PendingGetConnection(long dueTime, DbConnection owner, TaskCompletionSource completion, DbConnectionOptions userOptions)
{
@@ -60,49 +54,37 @@ public PendingGetConnection(long dueTime, DbConnection owner, TaskCompletionSour
Completion = completion;
UserOptions = userOptions;
}
+
public long DueTime { get; private set; }
public DbConnection Owner { get; private set; }
public TaskCompletionSource Completion { get; private set; }
public DbConnectionOptions UserOptions { get; private set; }
}
- sealed private class TransactedConnectionPool
+ private sealed class TransactedConnectionPool
{
+ private static int s_objectTypeCount;
- Dictionary _transactedCxns;
-
- DbConnectionPool _pool;
-
- private static int _objectTypeCount; // EventSource Counter
- internal readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);
+ private readonly Dictionary _transactedCxns;
+ private readonly DbConnectionPool _pool;
+ private readonly int _objectID;
internal TransactedConnectionPool(DbConnectionPool pool)
{
- Debug.Assert(null != pool, "null pool?");
+ Debug.Assert(pool != null, "null pool?");
+ _objectID = Interlocked.Increment(ref s_objectTypeCount);
_pool = pool;
- _transactedCxns = new Dictionary();
+ _transactedCxns = new Dictionary();
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Constructed for connection pool {1}", ObjectID, _pool.ObjectID);
}
- internal int ObjectID
- {
- get
- {
- return _objectID;
- }
- }
+ internal int ObjectID => _objectID;
- internal DbConnectionPool Pool
- {
- get
- {
- return _pool;
- }
- }
+ internal DbConnectionPool Pool => _pool;
- internal DbConnectionInternal GetTransactedObject(SysTx.Transaction transaction)
+ internal DbConnectionInternal GetTransactedObject(Transaction transaction)
{
- Debug.Assert(null != transaction, "null transaction?");
+ Debug.Assert(transaction != null, "null transaction?");
DbConnectionInternal transactedObject = null;
@@ -138,17 +120,17 @@ internal DbConnectionInternal GetTransactedObject(SysTx.Transaction transaction)
}
}
- if (null != transactedObject)
+ if (transactedObject != null)
{
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Transaction {1}, Connection {2}, Popped.", ObjectID, transaction.GetHashCode(), transactedObject.ObjectID);
}
return transactedObject;
}
- internal void PutTransactedObject(SysTx.Transaction transaction, DbConnectionInternal transactedObject)
+ internal void PutTransactedObject(Transaction transaction, DbConnectionInternal transactedObject)
{
- Debug.Assert(null != transaction, "null transaction?");
- Debug.Assert(null != transactedObject, "null transactedObject?");
+ Debug.Assert(transaction != null, "null transaction?");
+ Debug.Assert(transactedObject != null, "null transactedObject?");
TransactedConnectionList connections;
bool txnFound = false;
@@ -179,7 +161,7 @@ internal void PutTransactedObject(SysTx.Transaction transaction, DbConnectionInt
{
// create the transacted pool, making sure to clone the associated transaction
// for use as a key in our internal dictionary of transactions and connections
- SysTx.Transaction transactionClone = null;
+ Transaction transactionClone = null;
TransactedConnectionList newConnections = null;
try
@@ -220,7 +202,7 @@ internal void PutTransactedObject(SysTx.Transaction transaction, DbConnectionInt
}
finally
{
- if (null != transactionClone)
+ if (transactionClone != null)
{
if (newConnections != null)
{
@@ -243,10 +225,9 @@ internal void PutTransactedObject(SysTx.Transaction transaction, DbConnectionInt
}
- internal void TransactionEnded(SysTx.Transaction transaction, DbConnectionInternal transactedObject)
+ internal void TransactionEnded(Transaction transaction, DbConnectionInternal transactedObject)
{
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Transaction {1}, Connection {2}, Transaction Completed", ObjectID, transaction.GetHashCode(), transactedObject.ObjectID);
- TransactedConnectionList connections;
int entry = -1;
// NOTE: because TransactionEnded is an asynchronous notification, there's no guarantee
@@ -259,7 +240,7 @@ internal void TransactionEnded(SysTx.Transaction transaction, DbConnectionIntern
lock (_transactedCxns)
{
- if (_transactedCxns.TryGetValue(transaction, out connections))
+ if (_transactedCxns.TryGetValue(transaction, out TransactedConnectionList connections))
{
Debug.Assert(connections != null);
@@ -295,7 +276,6 @@ internal void TransactionEnded(SysTx.Transaction transaction, DbConnectionIntern
}
else
{
- //Debug.Assert ( false, "TransactionCompletedEvent fired before PutTransactedObject put the connection in the transacted pool." );
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Transaction {1}, Connection {2}, Transacted pool not yet created prior to transaction completing. Connection may be leaked.", ObjectID, transaction.GetHashCode(), transactedObject.ObjectID);
}
}
@@ -313,7 +293,6 @@ internal void TransactionEnded(SysTx.Transaction transaction, DbConnectionIntern
private sealed class PoolWaitHandles : DbBuffer
{
-
private readonly Semaphore _poolSemaphore;
private readonly ManualResetEvent _errorEvent;
@@ -350,9 +329,9 @@ internal PoolWaitHandles() : base(3 * IntPtr.Size)
_errorHandle.DangerousAddRef(ref mustRelease2);
_creationHandle.DangerousAddRef(ref mustRelease3);
- Debug.Assert(0 == SEMAPHORE_HANDLE, "SEMAPHORE_HANDLE");
- Debug.Assert(1 == ERROR_HANDLE, "ERROR_HANDLE");
- Debug.Assert(2 == CREATION_HANDLE, "CREATION_HANDLE");
+ Debug.Assert(SEMAPHORE_HANDLE == 0, "SEMAPHORE_HANDLE must be 0");
+ Debug.Assert(ERROR_HANDLE == 1, "ERROR_HANDLE must be 1");
+ Debug.Assert(CREATION_HANDLE == 2, "CREATION_HANDLE must be 2");
WriteIntPtr(SEMAPHORE_HANDLE * IntPtr.Size, _poolHandle.DangerousGetHandle());
WriteIntPtr(ERROR_HANDLE * IntPtr.Size, _errorHandle.DangerousGetHandle());
@@ -400,15 +379,15 @@ protected override bool ReleaseHandle()
{
// NOTE: The SafeHandle class guarantees this will be called exactly once.
// we know we can touch these other managed objects because of our original DangerousAddRef
- if (0 != (1 & _releaseFlags))
+ if ((1 & _releaseFlags) != 0)
{
_poolHandle.DangerousRelease();
}
- if (0 != (2 & _releaseFlags))
+ if ((2 & _releaseFlags) != 0)
{
_errorHandle.DangerousRelease();
}
- if (0 != (4 & _releaseFlags))
+ if ((4 & _releaseFlags) != 0)
{
_creationHandle.DangerousRelease();
}
@@ -416,88 +395,80 @@ protected override bool ReleaseHandle()
}
}
- private const int MAX_Q_SIZE = (int)0x00100000;
+ private const int MAX_Q_SIZE = 0x00100000;
// The order of these is important; we want the WaitAny call to be signaled
// for a free object before a creation signal. Only the index first signaled
// object is returned from the WaitAny call.
- private const int SEMAPHORE_HANDLE = (int)0x0;
- private const int ERROR_HANDLE = (int)0x1;
- private const int CREATION_HANDLE = (int)0x2;
- private const int BOGUS_HANDLE = (int)0x3;
+ private const int SEMAPHORE_HANDLE = 0x0;
+ private const int ERROR_HANDLE = 0x1;
+ private const int CREATION_HANDLE = 0x2;
+ private const int BOGUS_HANDLE = 0x3;
private const int WAIT_OBJECT_0 = 0;
- private const int WAIT_TIMEOUT = (int)0x102;
- private const int WAIT_ABANDONED = (int)0x80;
+ private const int WAIT_TIMEOUT = 0x102;
+ private const int WAIT_ABANDONED = 0x80;
private const int WAIT_FAILED = -1;
private const int ERROR_WAIT_DEFAULT = 5 * 1000; // 5 seconds
// we do want a testable, repeatable set of generated random numbers
- private static readonly Random _random = new Random(5101977); // Value obtained from Dave Driver
+ private static readonly Random s_random = new Random(5101977); // Value obtained from Dave Driver
+ private static int s_objectTypeCount;
+ private readonly int _objectID;
+ private readonly WaitCallback _poolCreateRequest;
+ private readonly PoolWaitHandles _waitHandles;
+ private readonly TransactedConnectionPool _transactedConnectionPool;
+ private readonly List _objectList;
+ private readonly ConcurrentStack _stackOld;
+ private readonly ConcurrentStack _stackNew;
+ private readonly ConcurrentQueue _pendingOpens;
+ ///
+ /// The private member which carries the set of authenticationcontexts for this pool (based on the user's identity).
+ ///
+ private readonly ConcurrentDictionary _pooledDbAuthenticationContexts;
private readonly int _cleanupWait;
private readonly DbConnectionPoolIdentity _identity;
-
private readonly DbConnectionFactory _connectionFactory;
private readonly DbConnectionPoolGroup _connectionPoolGroup;
private readonly DbConnectionPoolGroupOptions _connectionPoolGroupOptions;
- private DbConnectionPoolProviderInfo _connectionPoolProviderInfo;
-
- ///
- /// The private member which carries the set of authenticationcontexts for this pool (based on the user's identity).
- ///
- private readonly ConcurrentDictionary _pooledDbAuthenticationContexts;
+ private readonly DbConnectionPoolProviderInfo _connectionPoolProviderInfo;
private State _state;
-
- private readonly ConcurrentStack _stackOld = new ConcurrentStack();
- private readonly ConcurrentStack _stackNew = new ConcurrentStack();
-
- private readonly ConcurrentQueue _pendingOpens = new ConcurrentQueue();
private int _pendingOpensWaiting = 0;
-
- private readonly WaitCallback _poolCreateRequest;
-
private int _waitCount;
- private readonly PoolWaitHandles _waitHandles;
-
private Exception _resError;
- private volatile bool _errorOccurred;
-
private int _errorWait;
private Timer _errorTimer;
-
private Timer _cleanupTimer;
-
- private readonly TransactedConnectionPool _transactedConnectionPool;
-
- private readonly List _objectList;
private int _totalObjects;
- private static int _objectTypeCount; // EventSource counter
- internal readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);
+ private volatile bool _errorOccurred;
// only created by DbConnectionPoolGroup.GetConnectionPool
internal DbConnectionPool(
- DbConnectionFactory connectionFactory,
- DbConnectionPoolGroup connectionPoolGroup,
- DbConnectionPoolIdentity identity,
- DbConnectionPoolProviderInfo connectionPoolProviderInfo)
+ DbConnectionFactory connectionFactory,
+ DbConnectionPoolGroup connectionPoolGroup,
+ DbConnectionPoolIdentity identity,
+ DbConnectionPoolProviderInfo connectionPoolProviderInfo)
{
- Debug.Assert(ADP.IsWindowsNT, "Attempting to construct a connection pool on Win9x?");
- Debug.Assert(null != connectionPoolGroup, "null connectionPoolGroup");
+ Debug.Assert(connectionPoolGroup != null, "null connectionPoolGroup");
- if ((null != identity) && identity.IsRestricted)
+ if ((identity != null) && identity.IsRestricted)
{
throw ADP.InternalError(ADP.InternalErrorCode.AttemptingToPoolOnRestrictedToken);
}
_state = State.Initializing;
+ _objectID = Interlocked.Increment(ref s_objectTypeCount);
+ _stackOld = new ConcurrentStack();
+ _stackNew = new ConcurrentStack();
+ _pendingOpens = new ConcurrentQueue();
- lock (_random)
+ lock (s_random)
{ // Random.Next is not thread-safe
- _cleanupWait = _random.Next(12, 24) * 10 * 1000; // 2-4 minutes in 10 sec intervals, WebData 103603
+ _cleanupWait = s_random.Next(12, 24) * 10 * 1000; // 2-4 minutes in 10 sec intervals
}
_connectionFactory = connectionFactory;
@@ -505,76 +476,58 @@ internal DbConnectionPool(
_connectionPoolGroupOptions = connectionPoolGroup.PoolGroupOptions;
_connectionPoolProviderInfo = connectionPoolProviderInfo;
_identity = identity;
-
_waitHandles = new PoolWaitHandles();
-
_errorWait = ERROR_WAIT_DEFAULT;
- _errorTimer = null; // No error yet.
-
+ _errorTimer = null;
_objectList = new List(MaxPoolSize);
-
- _pooledDbAuthenticationContexts = new ConcurrentDictionary(concurrencyLevel: 4 * Environment.ProcessorCount /* default value in ConcurrentDictionary*/,
- capacity: 2);
-
- if (ADP.IsPlatformNT5)
- {
- _transactedConnectionPool = new TransactedConnectionPool(this);
- }
-
+ _pooledDbAuthenticationContexts = new ConcurrentDictionary(
+ concurrencyLevel: 4 * Environment.ProcessorCount /* default value in ConcurrentDictionary*/,
+ capacity: 2
+ );
+ _transactedConnectionPool = new TransactedConnectionPool(this);
_poolCreateRequest = new WaitCallback(PoolCreateRequest); // used by CleanupCallback
_state = State.Running;
+
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Constructed.", ObjectID);
//_cleanupTimer & QueuePoolCreateRequest is delayed until DbConnectionPoolGroup calls
// StartBackgroundCallbacks after pool is actually in the collection
}
- private int CreationTimeout
- {
- get { return PoolGroupOptions.CreationTimeout; }
- }
+ private int CreationTimeout => PoolGroupOptions.CreationTimeout;
- internal int Count
- {
- get { return _totalObjects; }
- }
+ internal int Count => _totalObjects;
- internal DbConnectionFactory ConnectionFactory
- {
- get { return _connectionFactory; }
- }
+ internal DbConnectionFactory ConnectionFactory => _connectionFactory;
- internal bool ErrorOccurred
- {
- get { return _errorOccurred; }
- }
+ internal bool ErrorOccurred => _errorOccurred;
- private bool HasTransactionAffinity
- {
- get { return PoolGroupOptions.HasTransactionAffinity; }
- }
+ private bool HasTransactionAffinity => PoolGroupOptions.HasTransactionAffinity;
- internal TimeSpan LoadBalanceTimeout
- {
- get { return PoolGroupOptions.LoadBalanceTimeout; }
- }
+ internal TimeSpan LoadBalanceTimeout => PoolGroupOptions.LoadBalanceTimeout;
private bool NeedToReplenish
{
get
{
- if (State.Running != _state) // SQL BU DT 364595 - don't allow connection create when not running.
+ if (_state != State.Running) // Don't allow connection create when not running.
+ {
return false;
+ }
int totalObjects = Count;
if (totalObjects >= MaxPoolSize)
+ {
return false;
+ }
if (totalObjects < MinPoolSize)
+ {
return true;
+ }
- int freeObjects = (_stackNew.Count + _stackOld.Count);
+ int freeObjects = _stackNew.Count + _stackOld.Count;
int waitingRequests = _waitCount;
bool needToReplenish = (freeObjects < waitingRequests) || ((freeObjects == waitingRequests) && (totalObjects > 1));
@@ -582,76 +535,34 @@ private bool NeedToReplenish
}
}
- internal DbConnectionPoolIdentity Identity
- {
- get { return _identity; }
- }
+ internal DbConnectionPoolIdentity Identity => _identity;
- internal bool IsRunning
- {
- get { return State.Running == _state; }
- }
+ internal bool IsRunning => State.Running == _state;
- private int MaxPoolSize
- {
- get { return PoolGroupOptions.MaxPoolSize; }
- }
+ private int MaxPoolSize => PoolGroupOptions.MaxPoolSize;
- private int MinPoolSize
- {
- get { return PoolGroupOptions.MinPoolSize; }
- }
+ private int MinPoolSize => PoolGroupOptions.MinPoolSize;
- internal int ObjectID
- {
- get
- {
- return _objectID;
- }
- }
+ internal int ObjectID => _objectID;
- internal DbConnectionPoolCounters PerformanceCounters
- {
- get { return _connectionFactory.PerformanceCounters; }
- }
+ internal DbConnectionPoolCounters PerformanceCounters => _connectionFactory.PerformanceCounters;
- internal DbConnectionPoolGroup PoolGroup
- {
- get { return _connectionPoolGroup; }
- }
+ internal DbConnectionPoolGroup PoolGroup => _connectionPoolGroup;
- internal DbConnectionPoolGroupOptions PoolGroupOptions
- {
- get { return _connectionPoolGroupOptions; }
- }
+ internal DbConnectionPoolGroupOptions PoolGroupOptions => _connectionPoolGroupOptions;
- internal DbConnectionPoolProviderInfo ProviderInfo
- {
- get { return _connectionPoolProviderInfo; }
- }
+ internal DbConnectionPoolProviderInfo ProviderInfo => _connectionPoolProviderInfo;
///
/// Return the pooled authentication contexts.
///
- internal ConcurrentDictionary AuthenticationContexts
- {
- get
- {
- return _pooledDbAuthenticationContexts;
- }
- }
+ internal ConcurrentDictionary AuthenticationContexts => _pooledDbAuthenticationContexts;
- internal bool UseLoadBalancing
- {
- get { return PoolGroupOptions.UseLoadBalancing; }
- }
+ internal bool UseLoadBalancing => PoolGroupOptions.UseLoadBalancing;
- private bool UsingIntegrateSecurity
- {
- get { return (null != _identity && DbConnectionPoolIdentity.NoIdentity != _identity); }
- }
+ private bool UsingIntegrateSecurity => _identity != null && DbConnectionPoolIdentity.s_noIdentity != _identity;
- private void CleanupCallback(Object state)
+ private void CleanupCallback(object state)
{
// Called when the cleanup-timer ticks over.
@@ -680,9 +591,8 @@ private void CleanupCallback(Object state)
if (_waitHandles.PoolSemaphore.WaitOne(0, false) /* != WAIT_TIMEOUT */)
{
// We obtained a objects from the semaphore.
- DbConnectionInternal obj;
- if (_stackOld.TryPop(out obj))
+ if (_stackOld.TryPop(out DbConnectionInternal obj))
{
Debug.Assert(obj != null, "null connection is not expected");
// If we obtained one from the old stack, destroy it.
@@ -739,10 +649,10 @@ private void CleanupCallback(Object state)
{
for (; ; )
{
- DbConnectionInternal obj;
-
- if (!_stackNew.TryPop(out obj))
+ if (!_stackNew.TryPop(out DbConnectionInternal obj))
+ {
break;
+ }
Debug.Assert(obj != null, "null connection is not expected");
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, ChangeStacks={1}", ObjectID, obj.ObjectID);
@@ -772,7 +682,7 @@ internal void Clear()
{
obj = _objectList[i];
- if (null != obj)
+ if (obj != null)
{
obj.DoNotPoolThisConnection();
}
@@ -799,10 +709,7 @@ internal void Clear()
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Cleared.", ObjectID);
}
- private Timer CreateCleanupTimer()
- {
- return (new Timer(new TimerCallback(this.CleanupCallback), null, _cleanupWait, _cleanupWait));
- }
+ private Timer CreateCleanupTimer() => new Timer(new TimerCallback(CleanupCallback), null, _cleanupWait, _cleanupWait);
private bool IsBlockingPeriodEnabled()
{
@@ -812,35 +719,24 @@ private bool IsBlockingPeriodEnabled()
return true;
}
- var policy = poolGroupConnectionOptions.PoolBlockingPeriod;
-
- switch (policy)
+ switch (poolGroupConnectionOptions.PoolBlockingPeriod)
{
case PoolBlockingPeriod.Auto:
+ if (ADP.IsAzureSqlServerEndpoint(poolGroupConnectionOptions.DataSource))
{
- if (ADP.IsAzureSqlServerEndpoint(poolGroupConnectionOptions.DataSource))
- {
- return false; // in Azure it will be Disabled
- }
- else
- {
- return true; // in Non Azure, it will be Enabled
- }
+ return false; // in Azure it will be Disabled
}
- case PoolBlockingPeriod.AlwaysBlock:
+ else
{
- return true; //Enabled
+ return true; // in Non Azure, it will be Enabled
}
+ case PoolBlockingPeriod.AlwaysBlock:
+ return true;
case PoolBlockingPeriod.NeverBlock:
- {
- return false; //Disabled
- }
+ return false;
default:
- {
- //we should never get into this path.
- Debug.Fail("Unknown PoolBlockingPeriod. Please specify explicit results in above switch case statement.");
- return true;
- }
+ Debug.Fail("Unknown PoolBlockingPeriod. Please specify explicit results in above switch case statement.");
+ return true;
}
}
@@ -851,7 +747,7 @@ private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectio
try
{
newObj = _connectionFactory.CreatePooledConnection(this, owningObject, _connectionPoolGroup.ConnectionOptions, _connectionPoolGroup.PoolKey, userOptions);
- if (null == newObj)
+ if (newObj == null)
{
throw ADP.InternalError(ADP.InternalErrorCode.CreateObjectReturnedNull); // CreateObject succeeded, but null object
}
@@ -875,7 +771,7 @@ private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectio
// If the old connection belonged to another pool, we need to remove it from that
if (oldConnection != null)
{
- var oldConnectionPool = oldConnection.Pool;
+ DbConnectionPool oldConnectionPool = oldConnection.Pool;
if (oldConnectionPool != null && oldConnectionPool != this)
{
Debug.Assert(oldConnectionPool._state == State.ShuttingDown, "Old connections pool should be shutting down");
@@ -893,7 +789,6 @@ private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectio
}
catch (Exception e)
{
- // UNDONE - should not be catching all exceptions!!!
if (!ADP.IsCatchableExceptionType(e))
{
throw;
@@ -917,10 +812,11 @@ private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectio
// Failed to create instance
_resError = e;
- // VSTFDEVDIV 479561: Make sure the timer starts even if ThreadAbort occurs after setting the ErrorEvent.
+ // Make sure the timer starts even if ThreadAbort occurs after setting the ErrorEvent.
// timer allocation has to be done out of CER block
- Timer t = new Timer(new TimerCallback(this.ErrorCallback), null, Timeout.Infinite, Timeout.Infinite);
+ Timer t = new Timer(new TimerCallback(ErrorCallback), null, Timeout.Infinite, Timeout.Infinite);
+
bool timerIsNotDisposed;
RuntimeHelpers.PrepareConstrainedRegions();
try
@@ -955,7 +851,7 @@ private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectio
private void DeactivateObject(DbConnectionInternal obj)
{
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Connection {1}, Deactivating.", ObjectID, obj.ObjectID);
- obj.DeactivateConnection(); // we presume this operation is safe outside of a lock...
+ obj.DeactivateConnection();
bool returnToGeneralPool = false;
bool destroyObject = false;
@@ -1014,8 +910,8 @@ private void DeactivateObject(DbConnectionInternal obj)
// the transaction asynchronously completing on a second
// thread.
- SysTx.Transaction transaction = obj.EnlistedTransaction;
- if (null != transaction)
+ Transaction transaction = obj.EnlistedTransaction;
+ if (transaction != null)
{
// NOTE: we're not locking on _state, so it's possible that its
// value could change between the conditional check and here.
@@ -1069,9 +965,6 @@ private void DeactivateObject(DbConnectionInternal obj)
}
else if (destroyObject)
{
- // VSTFDEVDIV# 479556 - connections that have been marked as no longer
- // poolable (e.g. exceeded their connection lifetime) are not, in fact,
- // returned to the general pool
DestroyObject(obj);
QueuePoolCreateRequest();
}
@@ -1081,8 +974,6 @@ private void DeactivateObject(DbConnectionInternal obj)
// ensure that the connection was processed
Debug.Assert(rootTxn == true || returnToGeneralPool == true || destroyObject == true);
-
- // TODO: BID trace processing state?
}
internal void DestroyObject(DbConnectionInternal obj)
@@ -1118,39 +1009,39 @@ internal void DestroyObject(DbConnectionInternal obj)
}
}
- private void ErrorCallback(Object state)
+ private void ErrorCallback(object state)
{
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Resetting Error handling.", ObjectID);
_errorOccurred = false;
_waitHandles.ErrorEvent.Reset();
// the error state is cleaned, destroy the timer to avoid periodic invocation
- Timer t = _errorTimer;
+ Timer timer = _errorTimer;
_errorTimer = null;
- if (t != null)
- {
- t.Dispose(); // Cancel timer request.
- }
+ timer?.Dispose();
}
private Exception TryCloneCachedException()
// Cached exception can be of any type, so is not always cloneable.
// This functions clones SqlException
- // OleDb and Odbc connections are not passing throw this code
+ // OleDb and Odbc connections are not passing through this code
{
- if (_resError == null)
+ if (_resError is null)
+ {
return null;
- if (_resError.GetType() == typeof(SqlClient.SqlException))
- return ((SqlClient.SqlException)_resError).InternalClone();
+ }
+
+ if (_resError is SqlException sqlError)
+ {
+ return sqlError.InternalClone();
+ }
+
return _resError;
}
- void WaitForPendingOpen()
+ private void WaitForPendingOpen()
{
-
- Debug.Assert(!Thread.CurrentThread.IsThreadPoolThread, "This thread may block for a long time. Threadpool threads should not be used.");
-
PendingGetConnection next;
do
@@ -1176,7 +1067,6 @@ void WaitForPendingOpen()
while (_pendingOpens.TryDequeue(out next))
{
-
if (next.Completion.Task.IsCompleted)
{
continue;
@@ -1222,22 +1112,28 @@ void WaitForPendingOpen()
}
#endif //DEBUG
}
- catch (System.OutOfMemoryException)
+ catch (OutOfMemoryException)
{
if (connection != null)
- { connection.DoomThisConnection(); }
+ {
+ connection.DoomThisConnection();
+ }
throw;
}
- catch (System.StackOverflowException)
+ catch (StackOverflowException)
{
if (connection != null)
- { connection.DoomThisConnection(); }
+ {
+ connection.DoomThisConnection();
+ }
throw;
}
- catch (System.Threading.ThreadAbortException)
+ catch (ThreadAbortException)
{
if (connection != null)
- { connection.DoomThisConnection(); }
+ {
+ connection.DoomThisConnection();
+ }
throw;
}
catch (Exception e)
@@ -1271,13 +1167,11 @@ void WaitForPendingOpen()
Interlocked.Exchange(ref _pendingOpensWaiting, 0);
}
}
-
} while (_pendingOpens.TryPeek(out next));
}
internal bool TryGetConnection(DbConnection owningObject, TaskCompletionSource retry, DbConnectionOptions userOptions, out DbConnectionInternal connection)
{
-
uint waitForMultipleObjectsTimeout = 0;
bool allowCreate = false;
@@ -1285,9 +1179,11 @@ internal bool TryGetConnection(DbConnection owningObject, TaskCompletionSource {0}, Getting connection.", ObjectID);
@@ -1348,7 +1245,7 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj
obj = GetFromTransactedPool(out transaction);
}
- if (null == obj)
+ if (obj == null)
{
Interlocked.Increment(ref _waitCount);
uint waitHandleCount = allowCreate ? 3u : 2u;
@@ -1374,7 +1271,7 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj
}
finally
{
- waitResult = SafeNativeMethods.WaitForMultipleObjectsEx(waitHandleCount, _waitHandles.DangerousGetHandle(), false, waitForMultipleObjectsTimeout, false);
+ waitResult = Common.SafeNativeMethods.WaitForMultipleObjectsEx(waitHandleCount, _waitHandles.DangerousGetHandle(), false, waitForMultipleObjectsTimeout, false);
// VSTFDEVDIV 479551 - call GetHRForLastWin32Error immediately after after the native call
if (waitResult == WAIT_FAILED)
@@ -1398,7 +1295,6 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj
return false;
case ERROR_HANDLE:
-
// Throw the error that PoolCreateRequest stashed.
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Errors are set.", ObjectID);
Interlocked.Decrement(ref _waitCount);
@@ -1412,7 +1308,7 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj
}
catch
{
- if (null == obj)
+ if (obj == null)
{
Interlocked.Decrement(ref _waitCount);
}
@@ -1420,24 +1316,21 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj
}
finally
{
- // SQLBUDT #386664 - ensure that we release this waiter, regardless
+ // Ensure that we release this waiter, regardless
// of any exceptions that may be thrown.
- if (null != obj)
+ if (obj != null)
{
Interlocked.Decrement(ref _waitCount);
}
}
- if (null == obj)
+ if (obj == null)
{
// If we were not able to create an object, check to see if
// we reached MaxPoolSize. If so, we will no longer wait on
// the CreationHandle, but instead wait for a free object or
// the timeout.
-
- // BUG - if we receive the CreationHandle midway into the wait
- // period and re-wait, we will be waiting on the full period
- if (Count >= MaxPoolSize && 0 != MaxPoolSize)
+ if (Count >= MaxPoolSize && MaxPoolSize != 0)
{
if (!ReclaimEmancipatedObjects())
{
@@ -1495,17 +1388,17 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj
Marshal.ThrowExceptionForHR(waitForMultipleObjectsExHR);
goto default; // if ThrowExceptionForHR didn't throw for some reason
- case (WAIT_ABANDONED + SEMAPHORE_HANDLE):
+ case WAIT_ABANDONED + SEMAPHORE_HANDLE:
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Semaphore handle abandonded.", ObjectID);
Interlocked.Decrement(ref _waitCount);
throw new AbandonedMutexException(SEMAPHORE_HANDLE, _waitHandles.PoolSemaphore);
- case (WAIT_ABANDONED + ERROR_HANDLE):
+ case WAIT_ABANDONED + ERROR_HANDLE:
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Error handle abandonded.", ObjectID);
Interlocked.Decrement(ref _waitCount);
throw new AbandonedMutexException(ERROR_HANDLE, _waitHandles.ErrorEvent);
- case (WAIT_ABANDONED + CREATION_HANDLE):
+ case WAIT_ABANDONED + CREATION_HANDLE:
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Creation handle abandoned.", ObjectID);
Interlocked.Decrement(ref _waitCount);
throw new AbandonedMutexException(CREATION_HANDLE, _waitHandles.CreationSemaphore);
@@ -1520,8 +1413,8 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj
{
if (CREATION_HANDLE == waitResult)
{
- int result = SafeNativeMethods.ReleaseSemaphore(_waitHandles.CreationHandle.DangerousGetHandle(), 1, IntPtr.Zero);
- if (0 == result)
+ int result = Common.SafeNativeMethods.ReleaseSemaphore(_waitHandles.CreationHandle.DangerousGetHandle(), 1, IntPtr.Zero);
+ if (result == 0)
{ // failure case
releaseSemaphoreResult = Marshal.GetHRForLastWin32Error();
}
@@ -1531,21 +1424,21 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj
_waitHandles.DangerousRelease();
}
}
- if (0 != releaseSemaphoreResult)
+ if (releaseSemaphoreResult != 0)
{
Marshal.ThrowExceptionForHR(releaseSemaphoreResult); // will only throw if (hresult < 0)
}
// Do not use this pooled connection if access token is about to expire soon before we can connect.
- if (null != obj && obj.IsAccessTokenExpired)
+ if (obj != null && obj.IsAccessTokenExpired)
{
DestroyObject(obj);
obj = null;
}
- } while (null == obj);
+ } while (obj == null);
}
- if (null != obj)
+ if (obj != null)
{
PrepareConnection(owningObject, obj, transaction);
}
@@ -1554,7 +1447,7 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj
return true;
}
- private void PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, SysTx.Transaction transaction)
+ private void PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, Transaction transaction)
{
lock (obj)
{ // Protect against Clear and ReclaimEmancipatedObjects, which call IsEmancipated, which is affected by PrePush and PostPop
@@ -1568,7 +1461,7 @@ private void PrepareConnection(DbConnection owningObject, DbConnectionInternal o
{
// if Activate throws an exception
// put it back in the pool or have it properly disposed of
- this.PutObject(obj, owningObject);
+ PutObject(obj, owningObject);
throw;
}
}
@@ -1599,9 +1492,8 @@ internal DbConnectionInternal ReplaceConnection(DbConnection owningObject, DbCon
private DbConnectionInternal GetFromGeneralPool()
{
- DbConnectionInternal obj = null;
- if (!_stackNew.TryPop(out obj))
+ if (!_stackNew.TryPop(out DbConnectionInternal obj))
{
if (!_stackOld.TryPop(out obj))
{
@@ -1617,30 +1509,29 @@ private DbConnectionInternal GetFromGeneralPool()
Debug.Assert(obj != null, "null connection is not expected");
}
- // SQLBUDT #356870 -- When another thread is clearing this pool,
+ // When another thread is clearing this pool,
// it will remove all connections in this pool which causes the
// following assert to fire, which really mucks up stress against
- // checked bits. The assert is benign, so we're commenting it out.
- //Debug.Assert(obj != null, "GetFromGeneralPool called with nothing in the pool!");
+ // checked bits.
- if (null != obj)
+ if (obj != null)
{
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Connection {1}, Popped from general pool.", ObjectID, obj.ObjectID);
PerformanceCounters.NumberOfFreeConnections.Decrement();
}
- return (obj);
+ return obj;
}
- private DbConnectionInternal GetFromTransactedPool(out SysTx.Transaction transaction)
+ private DbConnectionInternal GetFromTransactedPool(out Transaction transaction)
{
transaction = ADP.GetCurrentTransaction();
DbConnectionInternal obj = null;
- if (null != transaction && null != _transactedConnectionPool)
+ if (transaction != null && _transactedConnectionPool != null)
{
obj = _transactedConnectionPool.GetTransactedObject(transaction);
- if (null != obj)
+ if (obj != null)
{
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Connection {1}, Popped from transacted pool.", ObjectID, obj.ObjectID);
PerformanceCounters.NumberOfFreeConnections.Decrement();
@@ -1678,15 +1569,16 @@ private void PoolCreateRequest(object state)
long scopeID = SqlClientEventSource.Log.TryPoolerScopeEnterEvent(" {0}", ObjectID);
try
{
- if (State.Running == _state)
+ if (_state == State.Running)
{
-
// in case WaitForPendingOpen ever failed with no subsequent OpenAsync calls,
// start it back up again
if (!_pendingOpens.IsEmpty && _pendingOpensWaiting == 0)
{
- Thread waitOpenThread = new Thread(WaitForPendingOpen);
- waitOpenThread.IsBackground = true;
+ Thread waitOpenThread = new Thread(WaitForPendingOpen)
+ {
+ IsBackground = true
+ };
waitOpenThread.Start();
}
@@ -1724,7 +1616,7 @@ private void PoolCreateRequest(object state)
{ }
finally
{
- waitResult = SafeNativeMethods.WaitForSingleObjectEx(_waitHandles.CreationHandle.DangerousGetHandle(), timeout, false);
+ waitResult = Common.SafeNativeMethods.WaitForSingleObjectEx(_waitHandles.CreationHandle.DangerousGetHandle(), timeout, false);
}
if (WAIT_OBJECT_0 == waitResult)
{
@@ -1740,7 +1632,7 @@ private void PoolCreateRequest(object state)
// We do not need to check error flag here, since we know if
// CreateObject returned null, we are in error case.
- if (null != newObj)
+ if (newObj != null)
{
PutNewObject(newObj);
}
@@ -1759,13 +1651,11 @@ private void PoolCreateRequest(object state)
}
else
{
- // trace waitResult and ignore the failure
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, PoolCreateRequest called WaitForSingleObject failed {1}", ObjectID, waitResult);
}
}
catch (Exception e)
{
- // UNDONE - should not be catching all exceptions!!!
if (!ADP.IsCatchableExceptionType(e))
{
throw;
@@ -1781,7 +1671,7 @@ private void PoolCreateRequest(object state)
if (WAIT_OBJECT_0 == waitResult)
{
// reuse waitResult and ignore its value
- waitResult = SafeNativeMethods.ReleaseSemaphore(_waitHandles.CreationHandle.DangerousGetHandle(), 1, IntPtr.Zero);
+ waitResult = Common.SafeNativeMethods.ReleaseSemaphore(_waitHandles.CreationHandle.DangerousGetHandle(), 1, IntPtr.Zero);
}
if (mustRelease)
{
@@ -1800,12 +1690,7 @@ private void PoolCreateRequest(object state)
internal void PutNewObject(DbConnectionInternal obj)
{
- Debug.Assert(null != obj, "why are we adding a null object to the pool?");
-
- // VSTFDEVDIV 742887 - When another thread is clearing this pool, it
- // will set _cannotBePooled for all connections in this pool without prejudice which
- // causes the following assert to fire, which really mucks up stress
- // against checked bits.
+ Debug.Assert(obj != null, "why are we adding a null object to the pool?");
// Debug.Assert(obj.CanBePooled, "non-poolable object in pool");
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Connection {1}, Pushing to general pool.", ObjectID, obj.ObjectID);
@@ -1817,7 +1702,7 @@ internal void PutNewObject(DbConnectionInternal obj)
internal void PutObject(DbConnectionInternal obj, object owningObject)
{
- Debug.Assert(null != obj, "null obj?");
+ Debug.Assert(obj != null, "null obj");
PerformanceCounters.SoftDisconnectsPerSecond.Increment();
@@ -1836,8 +1721,6 @@ internal void PutObject(DbConnectionInternal obj, object owningObject)
// means, is that we're now responsible for this connection:
// it won't get reclaimed if it gets lost.
obj.PrePush(owningObject);
-
- // TODO: Consider using a Cer to ensure that we mark the object for reclaimation in the event something bad happens?
}
DeactivateObject(obj);
@@ -1845,7 +1728,7 @@ internal void PutObject(DbConnectionInternal obj, object owningObject)
internal void PutObjectFromTransactedPool(DbConnectionInternal obj)
{
- Debug.Assert(null != obj, "null pooledObject?");
+ Debug.Assert(obj != null, "null pooledObject?");
Debug.Assert(obj.EnlistedTransaction == null, "pooledObject is still enlisted?");
// called by the transacted connection pool , once it's removed the
@@ -1871,7 +1754,7 @@ internal void PutObjectFromTransactedPool(DbConnectionInternal obj)
private void QueuePoolCreateRequest()
{
- if (State.Running == _state)
+ if (_state == State.Running)
{
// Make sure we're at quota by posting a callback to the threadpool.
ThreadPool.QueueUserWorkItem(_poolCreateRequest);
@@ -1893,7 +1776,7 @@ private bool ReclaimEmancipatedObjects()
{
DbConnectionInternal obj = _objectList[i];
- if (null != obj)
+ if (obj != null)
{
bool locked = false;
@@ -1948,7 +1831,6 @@ internal void Startup()
{
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, CleanupWait={1}", ObjectID, _cleanupWait);
_cleanupTimer = CreateCleanupTimer();
-
if (NeedToReplenish)
{
QueuePoolCreateRequest();
@@ -1961,24 +1843,21 @@ internal void Shutdown()
_state = State.ShuttingDown;
// deactivate timer callbacks
- Timer t = _cleanupTimer;
+ Timer timer = _cleanupTimer;
_cleanupTimer = null;
- if (null != t)
- {
- t.Dispose();
- }
+ timer?.Dispose();
}
// TransactionEnded merely provides the plumbing for DbConnectionInternal to access the transacted pool
// that is implemented inside DbConnectionPool. This method's counterpart (PutTransactedObject) should
// only be called from DbConnectionPool.DeactivateObject and thus the plumbing to provide access to
// other objects is unnecessary (hence the asymmetry of Ended but no Begin)
- internal void TransactionEnded(SysTx.Transaction transaction, DbConnectionInternal transactedObject)
+ internal void TransactionEnded(Transaction transaction, DbConnectionInternal transactedObject)
{
- Debug.Assert(null != transaction, "null transaction?");
- Debug.Assert(null != transactedObject, "null transactedObject?");
+ Debug.Assert(transaction != null, "null transaction?");
+ Debug.Assert(transactedObject != null, "null transactedObject?");
- // Note: connection may still be associated with transaction due to Explicit Unbinding requirement.
+ // Note: connection may still be associated with transaction due to Explicit Unbinding requirement.
SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Transaction {1}, Connection {2}, Transaction Completed", ObjectID, transaction.GetHashCode(), transactedObject.ObjectID);
// called by the internal connection when it get's told that the
@@ -1986,7 +1865,7 @@ internal void TransactionEnded(SysTx.Transaction transaction, DbConnectionIntern
// the connection from it's list, then we put the connection back in
// general circulation.
TransactedConnectionPool transactedConnectionPool = _transactedConnectionPool;
- if (null != transactedConnectionPool)
+ if (transactedConnectionPool != null)
{
transactedConnectionPool.TransactionEnded(transaction, transactedObject);
}
@@ -2004,14 +1883,14 @@ private DbConnectionInternal UserCreateRequest(DbConnection owningObject, DbConn
}
else
{
- if ((oldConnection != null) || (Count < MaxPoolSize) || (0 == MaxPoolSize))
+ if ((oldConnection != null) || (Count < MaxPoolSize) || (MaxPoolSize == 0))
{
// If we have an odd number of total objects, reclaim any dead objects.
// If we did not find any objects to reclaim, create a new one.
-
- // TODO: Consider implement a control knob here; why do we only check for dead objects ever other time? why not every 10th time or every time?
if ((oldConnection != null) || (Count & 0x1) == 0x1 || !ReclaimEmancipatedObjects())
+ {
obj = CreateObject(owningObject, userOptions, oldConnection);
+ }
}
return obj;
}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPoolGroup.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPoolGroup.cs
index 6aa0847667..6a87505f4c 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPoolGroup.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPoolGroup.cs
@@ -191,7 +191,7 @@ internal DbConnectionPool GetConnectionPool(DbConnectionFactory connectionFactor
{
Debug.Assert(ADP.IsWindowsNT, "should not be pooling on Win9x");
- DbConnectionPoolIdentity currentIdentity = DbConnectionPoolIdentity.NoIdentity;
+ DbConnectionPoolIdentity currentIdentity = DbConnectionPoolIdentity.s_noIdentity;
if (_poolGroupOptions.PoolByIdentity)
{
// if we're pooling by identity (because integrated security is
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs
deleted file mode 100644
index 341569145d..0000000000
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs
+++ /dev/null
@@ -1,240 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace Microsoft.Data.ProviderBase
-{
-
- using System;
- using System.Runtime.CompilerServices;
- using System.Runtime.InteropServices;
- using System.Runtime.Versioning;
- using System.Security.Permissions;
- using System.Security.Principal;
- using Microsoft.Data.Common;
-
- [Serializable] // Serializable so SqlDependencyProcessDispatcher can marshall cross domain to SqlDependency.
- sealed internal class DbConnectionPoolIdentity
- {
- private const int E_NotImpersonationToken = unchecked((int)0x8007051D);
- private const int Win32_CheckTokenMembership = 1;
- private const int Win32_GetTokenInformation_1 = 2;
- private const int Win32_GetTokenInformation_2 = 3;
- private const int Win32_ConvertSidToStringSidW = 4;
- private const int Win32_CreateWellKnownSid = 5;
-
- static public readonly DbConnectionPoolIdentity NoIdentity = new DbConnectionPoolIdentity(String.Empty, false, true);
- static private readonly byte[] NetworkSid = (ADP.IsWindowsNT ? CreateWellKnownSid(WellKnownSidType.NetworkSid) : null);
- static private DbConnectionPoolIdentity _lastIdentity = null;
-
- private readonly string _sidString;
- private readonly bool _isRestricted;
- private readonly bool _isNetwork;
- private readonly int _hashCode;
-
- private DbConnectionPoolIdentity(string sidString, bool isRestricted, bool isNetwork)
- {
- _sidString = sidString;
- _isRestricted = isRestricted;
- _isNetwork = isNetwork;
- _hashCode = sidString == null ? 0 : sidString.GetHashCode();
- }
-
- internal bool IsRestricted
- {
- get { return _isRestricted; }
- }
-
- internal bool IsNetwork
- {
- get { return _isNetwork; }
- }
-
- static private byte[] CreateWellKnownSid(WellKnownSidType sidType)
- {
- // Passing an array as big as it can ever be is a small price to pay for
- // not having to P/Invoke twice (once to get the buffer, once to get the data)
-
- uint length = (uint)SecurityIdentifier.MaxBinaryLength;
- byte[] resultSid = new byte[length];
-
- // NOTE - We copied this code from System.Security.Principal.Win32.CreateWellKnownSid...
-
- if (0 == UnsafeNativeMethods.CreateWellKnownSid((int)sidType, null, resultSid, ref length))
- {
- IntegratedSecurityError(Win32_CreateWellKnownSid);
- }
- return resultSid;
- }
-
- override public bool Equals(object value)
- {
- bool result = ((this == NoIdentity) || (this == value));
- if (!result && (null != value))
- {
- DbConnectionPoolIdentity that = ((DbConnectionPoolIdentity)value);
- result = ((this._sidString == that._sidString) && (this._isRestricted == that._isRestricted) && (this._isNetwork == that._isNetwork));
- }
- return result;
- }
-
- [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.ControlPrincipal)]
- static internal WindowsIdentity GetCurrentWindowsIdentity()
- {
- return WindowsIdentity.GetCurrent();
- }
-
- [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)]
- static private IntPtr GetWindowsIdentityToken(WindowsIdentity identity)
- {
- return identity.Token;
- }
-
- [ResourceExposure(ResourceScope.None)] // SxS: this method does not create named objects
- [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
- static internal DbConnectionPoolIdentity GetCurrent()
- {
-
- // DEVNOTE: GetTokenInfo and EqualSID do not work on 9x. WindowsIdentity does not
- // work either on 9x. In fact, after checking with native there is no way
- // to validate the user on 9x, so simply don't. It is a known issue in
- // native, and we will handle this the same way.
-
- if (!ADP.IsWindowsNT)
- {
- return NoIdentity;
- }
-
- WindowsIdentity identity = GetCurrentWindowsIdentity();
- IntPtr token = GetWindowsIdentityToken(identity); // Free'd by WindowsIdentity.
- uint bufferLength = 2048; // Suggested default given by Greg Fee.
- uint lengthNeeded = 0;
-
- IntPtr tokenStruct = IntPtr.Zero;
- IntPtr SID;
- IntPtr sidStringBuffer = IntPtr.Zero;
- bool isNetwork;
-
- // Win32NativeMethods.IsTokenRestricted will raise exception if the native call fails
- bool isRestricted = Win32NativeMethods.IsTokenRestrictedWrapper(token);
-
- DbConnectionPoolIdentity current = null;
-
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- if (!UnsafeNativeMethods.CheckTokenMembership(token, NetworkSid, out isNetwork))
- {
- // will always fail with 0x8007051D if token is not an impersonation token
- IntegratedSecurityError(Win32_CheckTokenMembership);
- }
-
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- { }
- finally
- {
- // allocating memory and assigning to tokenStruct must happen
- tokenStruct = SafeNativeMethods.LocalAlloc(DbBuffer.LMEM_FIXED, (IntPtr)bufferLength);
- }
- if (IntPtr.Zero == tokenStruct)
- {
- throw new OutOfMemoryException();
- }
- if (!UnsafeNativeMethods.GetTokenInformation(token, 1, tokenStruct, bufferLength, ref lengthNeeded))
- {
- if (lengthNeeded > bufferLength)
- {
- bufferLength = lengthNeeded;
-
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- { }
- finally
- {
- // freeing token struct and setting tokenstruct to null must happen together
- // allocating memory and assigning to tokenStruct must happen
- SafeNativeMethods.LocalFree(tokenStruct);
- tokenStruct = IntPtr.Zero; // protect against LocalAlloc throwing an exception
- tokenStruct = SafeNativeMethods.LocalAlloc(DbBuffer.LMEM_FIXED, (IntPtr)bufferLength);
- }
- if (IntPtr.Zero == tokenStruct)
- {
- throw new OutOfMemoryException();
- }
-
- if (!UnsafeNativeMethods.GetTokenInformation(token, 1, tokenStruct, bufferLength, ref lengthNeeded))
- {
- IntegratedSecurityError(Win32_GetTokenInformation_1);
- }
- }
- else
- {
- IntegratedSecurityError(Win32_GetTokenInformation_2);
- }
- }
-
- identity.Dispose(); // Keep identity variable alive until after GetTokenInformation calls.
-
-
- SID = Marshal.ReadIntPtr(tokenStruct, 0);
-
- if (!UnsafeNativeMethods.ConvertSidToStringSidW(SID, out sidStringBuffer))
- {
- IntegratedSecurityError(Win32_ConvertSidToStringSidW);
- }
-
- if (IntPtr.Zero == sidStringBuffer)
- {
- throw ADP.InternalError(ADP.InternalErrorCode.ConvertSidToStringSidWReturnedNull);
- }
-
- string sidString = Marshal.PtrToStringUni(sidStringBuffer);
-
- var lastIdentity = _lastIdentity;
- if ((lastIdentity != null) && (lastIdentity._sidString == sidString) && (lastIdentity._isRestricted == isRestricted) && (lastIdentity._isNetwork == isNetwork))
- {
- current = lastIdentity;
- }
- else
- {
- current = new DbConnectionPoolIdentity(sidString, isRestricted, isNetwork);
- }
- }
- finally
- {
- // Marshal.FreeHGlobal does not have a ReliabilityContract
- if (IntPtr.Zero != tokenStruct)
- {
- SafeNativeMethods.LocalFree(tokenStruct);
- tokenStruct = IntPtr.Zero;
- }
- if (IntPtr.Zero != sidStringBuffer)
- {
- SafeNativeMethods.LocalFree(sidStringBuffer);
- sidStringBuffer = IntPtr.Zero;
- }
- }
- _lastIdentity = current;
- return current;
- }
-
- override public int GetHashCode()
- {
- return _hashCode;
- }
-
- static private void IntegratedSecurityError(int caller)
- {
- // passing 1,2,3,4,5 instead of true/false so that with a debugger
- // we could determine more easily which Win32 method call failed
- int lastError = Marshal.GetHRForLastWin32Error();
- if ((Win32_CheckTokenMembership != caller) || (E_NotImpersonationToken != lastError))
- {
- Marshal.ThrowExceptionForHR(lastError); // will only throw if (hresult < 0)
- }
- }
-
- }
-}
-
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs
index 919f8f2c4d..3f2f35e83d 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs
@@ -2067,7 +2067,7 @@ private bool TryOpen(TaskCompletionSource retry, SqlConnec
if (_impersonateIdentity != null)
{
- using (WindowsIdentity identity = DbConnectionPoolIdentity.GetCurrentWindowsIdentity())
+ using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
{
if (_impersonateIdentity.User == identity.User)
{
@@ -2086,7 +2086,7 @@ private bool TryOpen(TaskCompletionSource retry, SqlConnec
{
if (this.UsesIntegratedSecurity(connectionOptions) || this.UsesCertificate(connectionOptions) || this.UsesActiveDirectoryIntegrated(connectionOptions))
{
- _lastIdentity = DbConnectionPoolIdentity.GetCurrentWindowsIdentity();
+ _lastIdentity = WindowsIdentity.GetCurrent();
}
else
{
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDependencyListener.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDependencyListener.cs
index 23dba04f58..20ca518552 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDependencyListener.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDependencyListener.cs
@@ -131,7 +131,7 @@ internal SqlConnectionContainer(SqlConnectionContainerHashHelper hashHelper, str
// For now, DbConnectionPoolIdentity does not cache WindowsIdentity.
// That means for every container creation, we create a WindowsIdentity twice.
// We may want to improve this.
- _windowsIdentity = DbConnectionPoolIdentity.GetCurrentWindowsIdentity();
+ _windowsIdentity = WindowsIdentity.GetCurrent();
}
_escapedQueueName = SqlConnection.FixupDatabaseTransactionName(_queue); // Properly escape to prevent SQL Injection.
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObjectFactory.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObjectFactory.cs
new file mode 100644
index 0000000000..16c7c58950
--- /dev/null
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObjectFactory.cs
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.Data.SqlClient
+{
+ internal sealed class TdsParserStateObjectFactory
+ {
+ public static bool UseManagedSNI => true;
+ }
+}
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs
similarity index 58%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs
index 95769c3e6c..3e6c4450fa 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs
@@ -2,10 +2,14 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Runtime.Versioning;
+
namespace Microsoft.Data.ProviderBase
{
- partial class DbConnectionPoolIdentity
+ internal sealed partial class DbConnectionPoolIdentity
{
+ [ResourceExposure(ResourceScope.None)] // SxS: this method does not create named objects
+ [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
internal static DbConnectionPoolIdentity GetCurrent()
{
return GetCurrentManaged();
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs
similarity index 84%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs
index 93d2b0f329..3b2f45baab 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs
@@ -3,15 +3,18 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Runtime.Versioning;
using System.Security.Principal;
using Microsoft.Data.SqlClient;
namespace Microsoft.Data.ProviderBase
{
- partial class DbConnectionPoolIdentity
+ internal sealed partial class DbConnectionPoolIdentity
{
- private static DbConnectionPoolIdentity s_lastIdentity = null;
+ private static DbConnectionPoolIdentity s_lastIdentity;
+ [ResourceExposure(ResourceScope.None)] // SxS: this method does not create named objects
+ [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
internal static DbConnectionPoolIdentity GetCurrent()
{
return TdsParserStateObjectFactory.UseManagedSNI ? GetCurrentManaged() : GetCurrentNative();
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs
similarity index 57%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs
index f1b985a6de..99c1335325 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs
@@ -2,11 +2,14 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
+
namespace Microsoft.Data.ProviderBase
{
- sealed internal partial class DbConnectionPoolIdentity
+ [Serializable] // Serializable so SqlDependencyProcessDispatcher can marshall cross domain to SqlDependency.
+ internal sealed partial class DbConnectionPoolIdentity
{
- public static readonly DbConnectionPoolIdentity NoIdentity = new DbConnectionPoolIdentity(string.Empty, false, true);
+ public static readonly DbConnectionPoolIdentity s_noIdentity = new DbConnectionPoolIdentity(string.Empty, false, true);
private readonly string _sidString;
private readonly bool _isRestricted;
@@ -18,22 +21,21 @@ private DbConnectionPoolIdentity(string sidString, bool isRestricted, bool isNet
_sidString = sidString;
_isRestricted = isRestricted;
_isNetwork = isNetwork;
- _hashCode = sidString == null ? 0 : sidString.GetHashCode();
- }
-
- internal bool IsRestricted
- {
- get { return _isRestricted; }
+ _hashCode = sidString?.GetHashCode() ?? 0;
}
+ internal bool IsRestricted => _isRestricted;
- override public bool Equals(object value)
+ public override bool Equals(object value)
{
- bool result = ((this == NoIdentity) || (this == value));
- if (!result && (null != value))
+ bool result = ReferenceEquals(this, s_noIdentity) || ReferenceEquals(this, value);
+ if (!result && (!(value is null)))
{
- DbConnectionPoolIdentity that = ((DbConnectionPoolIdentity)value);
- result = ((_sidString == that._sidString) && (_isRestricted == that._isRestricted) && (_isNetwork == that._isNetwork));
+ DbConnectionPoolIdentity that = (DbConnectionPoolIdentity)value;
+ result =
+ string.Equals(_sidString,that._sidString,System.StringComparison.Ordinal) &&
+ (_isRestricted == that._isRestricted) &&
+ (_isNetwork == that._isNetwork);
}
return result;
}