public ConnectionPool FindOrCreatePool(DefaultPoolControl ctrl) { Debug.Assert(ctrl != null, "Unexpected DefaultPoolControl null!"); // Should not be calling this FindOrCreatePool if using integrated security. Debug.Assert(!ctrl.IntegratedSecurity, "Using integrated security and wrong FindOrCreatePool called"); String poolKey = ctrl.Key; ConnectionPool pool = FindPool(poolKey); if (pool == null) { try { lock (_map.SyncRoot) { // Did somebody else created it while we were waiting? pool = FindPool(poolKey); if (pool == null) { // Create a new pool, shove it into the map: pool = new ConnectionPool(ctrl); _map[poolKey] = pool; } } } catch { // MDAC 80973 throw; } } return(pool); }
public ConnectionPool(DefaultPoolControl ctrl) { _state = State.Initializing; _ctrl = ctrl; _poolCounter = new Counter(); _stackOld = new InterlockedStack(); _stackNew = new InterlockedStack(); _waitHandles = new ObjectPoolWaitHandle[3]; _waitHandles[SEMAPHORE_HANDLE] = CreateWaitHandle(SafeNativeMethods.CreateSemaphore(ADP.PtrZero, 0, MAX_Q_SIZE, ADP.PtrZero), false); _waitHandles[ERROR_HANDLE] = CreateWaitHandle(SafeNativeMethods.CreateEvent(ADP.PtrZero, 1, 0, ADP.PtrZero), false); _creationMutex = new Mutex(); _waitHandles[CREATION_HANDLE] = CreateWaitHandle(_creationMutex.Handle, true); _errorWait = ERROR_WAIT_DEFAULT; _cleanupWait = 0; // Set in CreateCleanupTimer _errorTimer = null; // No error yet. _connections = new ArrayList(_ctrl.MaxPool); if (ctrl.TransactionAffinity) { if (SQL.IsPlatformNT5()) { _txPool = CreateResourcePool(); } } _cleanupTimer = CreateCleanupTimer(); _state = State.Running; // PerfCounters - this counter will never be decremented! SQL.IncrementPoolCount(); // Make sure we're at quota by posting a callback to the threadpool. ThreadPool.QueueUserWorkItem(new WaitCallback(PoolCreateRequest)); }
public ConnectionPool FindOrCreatePool(DefaultPoolControl ctrl, IntPtr SID) { Debug.Assert(ctrl != null, "Unexpected DefaultPoolControl null!"); Debug.Assert(ctrl.IntegratedSecurity, "DefaultPoolControl unexpectedly not using integrated security"); Debug.Assert(!SQL.IsPlatformWin9x(), "FindOrCreatePool that expects not 9x called on 9x!"); Debug.Assert(SID != IntPtr.Zero, "Unexpected SID == IntPtr.Zero!"); String poolKey = ctrl.Key; ConnectionPool pool = FindPool(poolKey, SID); if (pool == null) { try { lock (_mapSSPI.SyncRoot) { // Did somebody else created it while we were waiting? pool = FindPool(poolKey, SID); if (pool == null) { // Create a new pool, shove it into the map: pool = new ConnectionPool(ctrl); ArrayList items = (ArrayList)_mapSSPI[poolKey]; if (null == items) { items = new ArrayList(); _mapSSPI[poolKey] = items; } items.Add(pool); } } } catch { // MDAC 80973 throw; } } return(pool); }
public static SqlInternalConnection GetPooledConnection(SqlConnectionString options, out bool isInTransaction) { // If Init() has not been called, call it and set up the cached members if (null == _manager) { Init(); } ConnectionPool pool = null; SqlConnectionPoolControl poolControl = null; SqlInternalConnection con = null; IntPtr SID = IntPtr.Zero; // Actual SID IntPtr tokenStruct = IntPtr.Zero; // Struct in memory containing SID string encryptedConnectionString = options.EncryptedActualConnectionString; try { // 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. _txPool is not created on 9x, so if that is not null then we // know we are not on 9x so go ahead do security check. if (options.IntegratedSecurity && !_isWindows9x) { // If using integrated security, find the pool based on the connection string. Then, // compare the SIDs of all pools to find a match. If no match found, create a new pool. // This will guarantee anyone using integrated security will always be sent to the // appropriate pool. DefaultPoolControl.ObtainSidInfo(out SID, out tokenStruct); pool = _manager.FindPool(encryptedConnectionString, SID); // If we found a pool, then we no longer need this SID - free it's token struct! // However, if we did not find a pool then we will create a new one and it will be up // to that pool to free the tokenStruct memory. if (null != pool) { Marshal.FreeHGlobal(tokenStruct); } } else { pool = _manager.FindPool(encryptedConnectionString); } if (pool == null) { // If pool is null, then we need to create a new pool - based on the connection string // and userid. SID and tokenStruct are included for integrated security connections. if (options.IntegratedSecurity && !_isWindows9x) { poolControl = new SqlConnectionPoolControl(encryptedConnectionString, true, SID, tokenStruct, options); pool = _manager.FindOrCreatePool(poolControl, SID); // MDAC 81288 } else { poolControl = new SqlConnectionPoolControl(encryptedConnectionString, false, IntPtr.Zero, IntPtr.Zero, options); pool = _manager.FindOrCreatePool(poolControl); // MDAC 81288 } } } catch { // If an exception is thrown and the pool was not created or found, then we need to free the memory for // the token struct. if (null == poolControl) { Marshal.FreeHGlobal(tokenStruct); } throw; } con = pool.GetConnection(out isInTransaction); // If GetObject() failed, the pool timeout occurred. if (con == null) { throw SQL.PooledOpenTimeout(); } return(con); }
private void PoolCreateRequest(object state) { // called by pooler to ensure pool requests are currently being satisfied - // creation mutex has not been obtained // Before creating any new connections, reclaim any released connections that // were not closed. CheckForDeadConnections(); Counter comp = _poolCounter.Clone(); if (comp.IsInError) { return; } int nFree = comp.FreeCount; int nWait = comp.WaitCount; int nTotal = comp.TotalCount; if ((nTotal < _ctrl.MaxPool) && (((nFree == nWait) && (nTotal > 0)) || (nFree < nWait) || (nTotal < _ctrl.MinPool))) { // Check to see if pool was created using integrated security. If so, check to make // sure identity of current user matches that of user that created pool. If it doesn't match, // do not create any connections on the ThreadPool thread, since either Open will fail or we // will open a connection for this pool that does not belong in this pool. The side effect of this // is that if using integrated security min pool size cannot be guaranteed. // Also - 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 (_ctrl.IntegratedSecurity && !SQL.IsPlatformWin9x()) { IntPtr SID = IntPtr.Zero; IntPtr tokenStruct = IntPtr.Zero; try { DefaultPoolControl.ObtainSidInfo(out SID, out tokenStruct); if (!_ctrl.EqualSid(SID)) { return; } } finally { Marshal.FreeHGlobal(tokenStruct); } } try { try { // obtain creation mutex _creationMutex.WaitOne(); SqlInternalConnection newCon; comp = _poolCounter.Clone(); nFree = comp.FreeCount; nWait = comp.WaitCount; nTotal = comp.TotalCount; // Check IsInError again after obtaining mutex if (!comp.IsInError) { while ((nTotal < _ctrl.MaxPool) && (((nFree == nWait) && (nTotal > 0)) || (nFree < nWait) || (nTotal < _ctrl.MinPool))) { newCon = CreateConnection(); // We do not need to check error flag here, since we know if // CreateConnection returned null, we are in error case. if (null != newCon) { PutNewConnection(newCon); comp = _poolCounter.Clone(); nFree = comp.FreeCount; nWait = comp.WaitCount; nTotal = comp.TotalCount; } else { break; } } } } finally { // ReleaseMutex // always release _creationMutex.ReleaseMutex(); } } catch { // MDAC 80973 throw; } } }