public OdbcConnection() { this.connectionTimeout = 15; this.ObjectID = Interlocked.Increment(ref _objectTypeCount); GC.SuppressFinalize(this); this._innerConnection = DbConnectionClosedNeverOpened.SingletonInstance; }
protected override DbMetaDataFactory CreateMetaDataFactory(DbConnectionInternal internalConnection, out bool cacheMetaDataFactory) { cacheMetaDataFactory = false; OleDbConnectionInternal internal2 = (OleDbConnectionInternal) internalConnection; OleDbConnection connection = internal2.Connection; NameValueCollection section = (NameValueCollection) System.Configuration.PrivilegedConfigurationManager.GetSection("system.data.oledb"); Stream xMLStream = null; string dataSourcePropertyValue = connection.GetDataSourcePropertyValue(OleDbPropertySetGuid.DataSourceInfo, 0x60) as string; if (section != null) { string[] values = null; string name = null; if (dataSourcePropertyValue != null) { name = dataSourcePropertyValue + ":MetaDataXml"; values = section.GetValues(name); } if (values == null) { name = "defaultMetaDataXml"; values = section.GetValues(name); } if (values != null) { xMLStream = ADP.GetXmlStreamFromValues(values, name); } } if (xMLStream == null) { xMLStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("System.Data.OleDb.OleDbMetaData.xml"); cacheMetaDataFactory = true; } return new OleDbMetaDataFactory(xMLStream, internal2.ServerVersion, internal2.ServerVersion, internal2.GetSchemaRowsetInformation()); }
private void ConnectionString_Set(string value) { System.Data.Common.DbConnectionOptions userConnectionOptions = null; System.Data.ProviderBase.DbConnectionPoolGroup group = this.ConnectionFactory.GetConnectionPoolGroup(value, null, ref userConnectionOptions); System.Data.ProviderBase.DbConnectionInternal innerConnection = this.InnerConnection; bool allowSetConnectionString = innerConnection.AllowSetConnectionString; if (allowSetConnectionString) { allowSetConnectionString = this.SetInnerConnectionFrom(System.Data.ProviderBase.DbConnectionClosedBusy.SingletonInstance, innerConnection); if (allowSetConnectionString) { this._userConnectionOptions = userConnectionOptions; this._poolGroup = group; this._innerConnection = System.Data.ProviderBase.DbConnectionClosedNeverOpened.SingletonInstance; } } if (!allowSetConnectionString) { throw System.Data.Common.ADP.OpenConnectionPropertySet("ConnectionString", innerConnection.State); } if (Bid.TraceOn) { string str = (userConnectionOptions != null) ? userConnectionOptions.UsersConnectionStringForTrace() : ""; Bid.Trace("<prov.DbConnectionHelper.ConnectionString_Set|API> %d#, '%ls'\n", this.ObjectID, str); } }
override protected DbMetaDataFactory CreateMetaDataFactory(DbConnectionInternal internalConnection, out bool cacheMetaDataFactory){ Debug.Assert (internalConnection != null,"internalConnection may not be null."); cacheMetaDataFactory = false; OdbcConnection odbcOuterConnection = ((OdbcConnectionOpen)internalConnection).OuterConnection; Debug.Assert(odbcOuterConnection != null,"outer connection may not be null."); NameValueCollection settings = (NameValueCollection)PrivilegedConfigurationManager.GetSection("system.data.odbc"); Stream XMLStream =null; // get the DBMS Name object driverName = null; string stringValue = odbcOuterConnection.GetInfoStringUnhandled(ODBC32.SQL_INFO.DRIVER_NAME); if (stringValue != null) { driverName = stringValue; } if (settings != null){ string [] values = null; string metaDataXML = null; // first try to get the provider specific xml // if driver name is not supported we can't build the settings key needed to // get the provider specific XML path if (driverName != null){ metaDataXML = ((string)driverName) + _MetaData; values = settings.GetValues(metaDataXML); } // if we did not find provider specific xml see if there is new default xml if (values == null) { metaDataXML = _defaultMetaDataXml; values = settings.GetValues(metaDataXML); } // If there is an XML file get it if (values != null) { XMLStream = ADP.GetXmlStreamFromValues(values,metaDataXML); } } // use the embedded xml if the user did not over ride it if (XMLStream == null){ XMLStream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("System.Data.Odbc.OdbcMetaData.xml"); cacheMetaDataFactory = true; } Debug.Assert (XMLStream != null,"XMLstream may not be null."); String versionString = odbcOuterConnection.GetInfoStringUnhandled(ODBC32.SQL_INFO.DBMS_VER); return new OdbcMetaDataFactory (XMLStream, versionString, versionString, odbcOuterConnection); }
internal override void SetInnerConnectionTo(DbConnection owningObject, System.Data.ProviderBase.DbConnectionInternal to) { OracleConnection connection = owningObject as OracleConnection; if (connection != null) { connection.SetInnerConnectionTo(to); } }
internal OracleInternalConnection GetOpenInternalConnection() { System.Data.ProviderBase.DbConnectionInternal innerConnection = this.InnerConnection; if (!(innerConnection is OracleInternalConnection)) { throw System.Data.Common.ADP.ClosedConnectionError(); } return(innerConnection as OracleInternalConnection); }
override protected DbMetaDataFactory CreateMetaDataFactory(DbConnectionInternal internalConnection, out bool cacheMetaDataFactory){ Debug.Assert (internalConnection != null,"internalConnection may not be null."); cacheMetaDataFactory = false; OleDbConnectionInternal oleDbInternalConnection = (OleDbConnectionInternal) internalConnection; OleDbConnection oleDbOuterConnection = oleDbInternalConnection.Connection; Debug.Assert(oleDbOuterConnection != null,"outer connection may not be null."); NameValueCollection settings = (NameValueCollection)PrivilegedConfigurationManager.GetSection("system.data.oledb"); Stream XMLStream =null; String providerFileName = oleDbOuterConnection.GetDataSourcePropertyValue(OleDbPropertySetGuid.DataSourceInfo,ODB.DBPROP_PROVIDERFILENAME) as string; if (settings != null){ string [] values = null; string metaDataXML = null; // first try to get the provider specific xml // if providerfilename is not supported we can't build the settings key needed to // get the provider specific XML path if (providerFileName != null){ metaDataXML = providerFileName + _metaDataXml; values = settings.GetValues(metaDataXML); } // if we did not find provider specific xml see if there is new default xml if (values == null) { metaDataXML =_defaultMetaDataXml; values = settings.GetValues(metaDataXML); } // If there is new XML get it if (values != null) { XMLStream = ADP.GetXmlStreamFromValues(values,metaDataXML); } } // if the xml was not obtained from machine.config use the embedded XML resource if (XMLStream == null) { XMLStream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("System.Data.OleDb.OleDbMetaData.xml"); cacheMetaDataFactory = true; } Debug.Assert (XMLStream != null,"XMLstream may not be null."); // using the ServerVersion as the NormalizedServerVersion. Doing this for two reasons // 1) The Spec for DBPROP_DBMSVER normalizes the ServerVersion // 2) for OLE DB its the only game in town return new OleDbMetaDataFactory (XMLStream, oleDbInternalConnection.ServerVersion, oleDbInternalConnection.ServerVersion, oleDbInternalConnection.GetSchemaRowsetInformation()); }
private void CopyFrom(OracleConnection connection) { System.Data.Common.ADP.CheckArgumentNull(connection, "connection"); this._userConnectionOptions = connection.UserConnectionOptions; this._poolGroup = connection.PoolGroup; if (System.Data.ProviderBase.DbConnectionClosedNeverOpened.SingletonInstance == connection._innerConnection) { this._innerConnection = System.Data.ProviderBase.DbConnectionClosedNeverOpened.SingletonInstance; } else { this._innerConnection = System.Data.ProviderBase.DbConnectionClosedPreviouslyOpened.SingletonInstance; } }
private void CopyFrom(SqlConnection connection) { ADP.CheckArgumentNull(connection, "connection"); _userConnectionOptions = connection.UserConnectionOptions; _poolGroup = connection.PoolGroup; if (DbConnectionClosedNeverOpened.SingletonInstance == connection._innerConnection) { _innerConnection = DbConnectionClosedNeverOpened.SingletonInstance; } else { _innerConnection = DbConnectionClosedPreviouslyOpened.SingletonInstance; } }
internal void Abort(Exception e) { System.Data.ProviderBase.DbConnectionInternal comparand = this._innerConnection; if (ConnectionState.Open == comparand.State) { Interlocked.CompareExchange <System.Data.ProviderBase.DbConnectionInternal>(ref this._innerConnection, System.Data.ProviderBase.DbConnectionClosedPreviouslyOpened.SingletonInstance, comparand); comparand.DoomThisConnection(); } if (e is OutOfMemoryException) { Bid.Trace("<prov.DbConnectionHelper.Abort|RES|INFO|CPOOL> %d#, Aborting operation due to asynchronous exception: %ls\n", this.ObjectID, "OutOfMemory"); } else { Bid.Trace("<prov.DbConnectionHelper.Abort|RES|INFO|CPOOL> %d#, Aborting operation due to asynchronous exception: %ls\n", this.ObjectID, e.ToString()); } }
// Copy Constructor private void CopyFrom(CONNECTIONOBJECTNAME connection) { // V1.2.3300 ADP.CheckArgumentNull(connection, "connection"); _userConnectionOptions = connection.UserConnectionOptions; _poolGroup = connection.PoolGroup; // SQLBU 432115 // Match the original connection's behavior for whether the connection was never opened, // but ensure Clone is in the closed state. if (DbConnectionClosedNeverOpened.SingletonInstance == connection._innerConnection) { _innerConnection = DbConnectionClosedNeverOpened.SingletonInstance; } else { _innerConnection = DbConnectionClosedPreviouslyOpened.SingletonInstance; } }
public override void EnlistTransaction(System.Transactions.Transaction transaction) { ExecutePermission.Demand(); Bid.Trace("<prov.DbConnectionHelper.EnlistTransaction|RES|TRAN> %d#, Connection enlisting in a transaction.\n", this.ObjectID); System.Data.ProviderBase.DbConnectionInternal innerConnection = this.InnerConnection; System.Transactions.Transaction enlistedTransaction = innerConnection.EnlistedTransaction; if (enlistedTransaction != null) { if (enlistedTransaction.Equals(transaction)) { return; } if (enlistedTransaction.TransactionInformation.Status == System.Transactions.TransactionStatus.Active) { throw System.Data.Common.ADP.TransactionPresent(); } } innerConnection.EnlistTransaction(transaction); GC.KeepAlive(this); }
private void ConnectionString_Set(DbConnectionPoolKey key) { DbConnectionOptions connectionOptions = null; System.Data.ProviderBase.DbConnectionPoolGroup poolGroup = ConnectionFactory.GetConnectionPoolGroup(key, null, ref connectionOptions); DbConnectionInternal connectionInternal = InnerConnection; bool flag = connectionInternal.AllowSetConnectionString; if (flag) { flag = SetInnerConnectionFrom(DbConnectionClosedBusy.SingletonInstance, connectionInternal); if (flag) { _userConnectionOptions = connectionOptions; _poolGroup = poolGroup; _innerConnection = DbConnectionClosedNeverOpened.SingletonInstance; } } if (!flag) { throw ADP.OpenConnectionPropertySet(ADP.ConnectionString, connectionInternal.State); } }
protected override DbMetaDataFactory CreateMetaDataFactory(DbConnectionInternal internalConnection, out bool cacheMetaDataFactory) { cacheMetaDataFactory = false; OdbcConnection outerConnection = ((OdbcConnectionOpen) internalConnection).OuterConnection; NameValueCollection section = (NameValueCollection) System.Configuration.PrivilegedConfigurationManager.GetSection("system.data.odbc"); Stream xMLStream = null; object obj2 = null; string infoStringUnhandled = outerConnection.GetInfoStringUnhandled(ODBC32.SQL_INFO.DRIVER_NAME); if (infoStringUnhandled != null) { obj2 = infoStringUnhandled; } if (section != null) { string[] values = null; string name = null; if (obj2 != null) { name = ((string) obj2) + ":MetaDataXml"; values = section.GetValues(name); } if (values == null) { name = "defaultMetaDataXml"; values = section.GetValues(name); } if (values != null) { xMLStream = ADP.GetXmlStreamFromValues(values, name); } } if (xMLStream == null) { xMLStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("System.Data.Odbc.OdbcMetaData.xml"); cacheMetaDataFactory = true; } string serverVersion = outerConnection.GetInfoStringUnhandled(ODBC32.SQL_INFO.DBMS_VER); return new OdbcMetaDataFactory(xMLStream, serverVersion, serverVersion, outerConnection); }
internal void SetInnerConnectionEvent(System.Data.ProviderBase.DbConnectionInternal to) { ConnectionState originalState = this._innerConnection.State & ConnectionState.Open; ConnectionState currentState = to.State & ConnectionState.Open; if ((originalState != currentState) && (currentState == ConnectionState.Closed)) { this._closeCount++; } this._innerConnection = to; if ((originalState == ConnectionState.Closed) && (ConnectionState.Open == currentState)) { this.OnStateChange(System.Data.ProviderBase.DbConnectionInternal.StateChangeOpen); } else if ((ConnectionState.Open == originalState) && (currentState == ConnectionState.Closed)) { this.OnStateChange(System.Data.ProviderBase.DbConnectionInternal.StateChangeClosed); } else if (originalState != currentState) { this.OnStateChange(new StateChangeEventArgs(originalState, currentState)); } }
override internal bool SetInnerConnectionFrom(DbConnection owningObject, DbConnectionInternal to, DbConnectionInternal from) { SqlConnection c = (owningObject as SqlConnection); if (null != c) { return c.SetInnerConnectionFrom(to, from); } return false; }
/// <summary> /// Creates a new connection to replace an existing connection /// </summary> /// <param name="owningObject">Outer connection that currently owns <paramref name="oldConnection"/></param> /// <param name="userOptions">Options used to create the new connection</param> /// <param name="oldConnection">Inner connection that will be replaced</param> /// <returns>A new inner connection that is attached to the <paramref name="owningObject"/></returns> internal DbConnectionInternal ReplaceConnection(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) { DbConnectionInternal newConnection = UserCreateRequest(owningObject, userOptions, oldConnection); if (newConnection != null) { PrepareConnection(owningObject, newConnection); oldConnection.PrepareForReplaceConnection(); oldConnection.DeactivateConnection(); oldConnection.Dispose(); } return newConnection; }
private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObjectsTimeout, bool allowCreate, bool onlyOneCheckConnection, DbConnectionOptions userOptions, out DbConnectionInternal connection) { DbConnectionInternal obj = null; if (null == obj) { Interlocked.Increment(ref _waitCount); do { int waitResult = BOGUS_HANDLE; try { try { } finally { waitResult = WaitHandle.WaitAny(_waitHandles.GetHandles(allowCreate), unchecked((int)waitForMultipleObjectsTimeout)); } // From the WaitAny docs: "If more than one object became signaled during // the call, this is the array index of the signaled object with the // smallest index value of all the signaled objects." This is important // so that the free object signal will be returned before a creation // signal. switch (waitResult) { case WaitHandle.WaitTimeout: Interlocked.Decrement(ref _waitCount); connection = null; return false; case ERROR_HANDLE: // Throw the error that PoolCreateRequest stashed. Interlocked.Decrement(ref _waitCount); throw TryCloneCachedException(); case CREATION_HANDLE: try { obj = UserCreateRequest(owningObject, userOptions); } catch { if (null == obj) { Interlocked.Decrement(ref _waitCount); } throw; } finally { // Ensure that we release this waiter, regardless // of any exceptions that may be thrown. if (null != obj) { Interlocked.Decrement(ref _waitCount); } } if (null == obj) { // 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. if (Count >= MaxPoolSize && 0 != MaxPoolSize) { if (!ReclaimEmancipatedObjects()) { // modify handle array not to wait on creation mutex anymore Debug.Assert(2 == CREATION_HANDLE, "creation handle changed value"); allowCreate = false; } } } break; case SEMAPHORE_HANDLE: // // guaranteed available inventory // Interlocked.Decrement(ref _waitCount); obj = GetFromGeneralPool(); if ((obj != null) && (!obj.IsConnectionAlive())) { DestroyObject(obj); obj = null; // Setting to null in case creating a new object fails if (onlyOneCheckConnection) { if (_waitHandles.CreationSemaphore.WaitOne(unchecked((int)waitForMultipleObjectsTimeout))) { try { obj = UserCreateRequest(owningObject, userOptions); } finally { _waitHandles.CreationSemaphore.Release(1); } } else { // Timeout waiting for creation semaphore - return null connection = null; return false; } } } break; default: Interlocked.Decrement(ref _waitCount); throw ADP.InternalError(ADP.InternalErrorCode.UnexpectedWaitAnyResult); } } finally { if (CREATION_HANDLE == waitResult) { _waitHandles.CreationSemaphore.Release(1); } } } while (null == obj); } if (null != obj) { PrepareConnection(owningObject, obj); } connection = obj; return true; }
private void WaitForPendingOpen() { PendingGetConnection next; do { bool started = false; try { try { } finally { started = Interlocked.CompareExchange(ref _pendingOpensWaiting, 1, 0) == 0; } if (!started) { return; } while (_pendingOpens.TryDequeue(out next)) { if (next.Completion.Task.IsCompleted) { continue; } uint delay; if (next.DueTime == Timeout.Infinite) { delay = unchecked ((uint)Timeout.Infinite); } else { delay = (uint)Math.Max(ADP.TimerRemainingMilliseconds(next.DueTime), 0); } DbConnectionInternal connection = null; bool timeout = false; Exception caughtException = null; try { bool allowCreate = true; bool onlyOneCheckConnection = false; timeout = !TryGetConnection(next.Owner, delay, allowCreate, onlyOneCheckConnection, next.UserOptions, out connection); } catch (Exception e) { caughtException = e; } if (caughtException != null) { next.Completion.TrySetException(caughtException); } else if (timeout) { next.Completion.TrySetException(ADP.ExceptionWithStackTrace(ADP.PooledOpenTimeout())); } else { Debug.Assert(connection != null, "connection should never be null in success case"); if (!next.Completion.TrySetResult(connection)) { // if the completion was cancelled, lets try and get this connection back for the next try PutObject(connection, next.Owner); } } } } finally { if (started) { Interlocked.Exchange(ref _pendingOpensWaiting, 0); } } } while (_pendingOpens.TryPeek(out next)); }
private void PoolCreateRequest() { // called by pooler to ensure pool requests are currently being satisfied - // creation mutex has not been obtained if (State.Running == _state) { // 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; waitOpenThread.Start(); } // Before creating any new objects, reclaim any released objects that were // not closed. ReclaimEmancipatedObjects(); if (NeedToReplenish) { // Check to see if pool was created using integrated security and if so, make // sure the identity of current user matches that of user that created pool. // If it doesn't match, do not create any objects on the ThreadPool thread, // since either Open will fail or we will open a object 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. if (UsingIntegrateSecurity && !_identity.Equals(DbConnectionPoolIdentity.GetCurrent())) { return; } if (_waitHandles.CreationSemaphore.WaitOne(CreationTimeout)) { try { while (NeedToReplenish) { // Don't specify any user options because there is no outer connection associated with the new connection DbConnectionInternal newObj = CreateObject(owningObject: null, userOptions: null, oldConnection: null); // We do not need to check error flag here, since we know if // CreateObject returned null, we are in error case. if (null != newObj) { PutNewObject(newObj); } else { break; } } } finally { // reuse waitResult and ignore its value _waitHandles.CreationSemaphore.Release(1); } } else { // do not wait forever and potential block this worker thread // instead wait for a period of time and just requeue to try again QueuePoolCreateRequest(); } } } }
private bool TryGetConnection(DbConnection owningObject, int waitForMultipleObjectsTimeout, bool allowCreate, bool onlyOneCheckConnection, DbConnectionOptions userOptions, out DbConnectionInternal connection) { DbConnectionInternal obj = null; if (null == obj) { Interlocked.Increment(ref _waitCount); do { int waitResult = WaitHandle.WaitTimeout; try { if (!allowCreate) { if (_waitHandles.PoolSemaphore.Wait(waitForMultipleObjectsTimeout)) { waitResult = SEMAPHORE_HANDLE; } else { waitResult = WaitHandle.WaitTimeout; } } else { bool obtainedPoolSemaphore = false; DateTime start = DateTime.UtcNow; do { waitResult = WaitHandle.WaitAny(_waitHandles.Handles, waitForMultipleObjectsTimeout); // Obtaining the WaitHandle for a SemaphoreSlim doesn't actually take one from the count // So we need to wait on the SemaphoreSlim seperately if (waitResult == SEMAPHORE_HANDLE) { if (_waitHandles.PoolSemaphore.Wait(TimeSpan.Zero)) { obtainedPoolSemaphore = true; } else { DateTime currentTime = DateTime.UtcNow; waitForMultipleObjectsTimeout -= (currentTime - start).Milliseconds; } } } while ((waitResult == SEMAPHORE_HANDLE) && !obtainedPoolSemaphore); } // From the WaitAny docs: "If more than one object became signaled during // the call, this is the array index of the signaled object with the // smallest index value of all the signaled objects." This is important // so that the free object signal will be returned before a creation // signal. switch (waitResult) { case WaitHandle.WaitTimeout: Interlocked.Decrement(ref _waitCount); connection = null; return(false); case CREATION_HANDLE: try { obj = UserCreateRequest(owningObject, userOptions); } catch { if (null == obj) { Interlocked.Decrement(ref _waitCount); } throw; } finally { // Ensure that we release this waiter, regardless // of any exceptions that may be thrown. if (null != obj) { Interlocked.Decrement(ref _waitCount); } } if (null == obj) { // 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. if (Count >= MaxPoolSize && 0 != MaxPoolSize) { if (!ReclaimEmancipatedObjects()) { // modify handle array not to wait on creation mutex anymore allowCreate = false; } } } break; case SEMAPHORE_HANDLE: // // guaranteed available inventory // Interlocked.Decrement(ref _waitCount); obj = GetFromGeneralPool(); if ((obj != null) && (!obj.IsConnectionAlive())) { DestroyObject(obj); obj = null; // Setting to null in case creating a new object fails if (onlyOneCheckConnection) { if (_waitHandles.CreationSemaphore.WaitOne(unchecked ((int)waitForMultipleObjectsTimeout))) { try { obj = UserCreateRequest(owningObject, userOptions); } finally { _waitHandles.CreationSemaphore.Release(1); } } else { // Timeout waiting for creation semaphore - return null connection = null; return(false); } } } break; default: Interlocked.Decrement(ref _waitCount); throw ADP.InternalError(ADP.InternalErrorCode.UnexpectedWaitAnyResult); } } finally { if (CREATION_HANDLE == waitResult) { _waitHandles.CreationSemaphore.Release(); } } } while (null == obj); } if (null != obj) { PrepareConnection(owningObject, obj); } connection = obj; return(true); }
abstract internal bool SetInnerConnectionFrom(DbConnection owningObject, DbConnectionInternal to, DbConnectionInternal from);
protected internal DbMetaDataFactory GetMetaDataFactory (DbConnectionString connectionOptions, DbConnectionInternal internalConnection) { throw new NotImplementedException (); }
public OracleConnection() { this.ObjectID = Interlocked.Increment(ref _objectTypeCount); GC.SuppressFinalize(this); this._innerConnection = System.Data.ProviderBase.DbConnectionClosedNeverOpened.SingletonInstance; }
internal void SetInnerConnectionTo(System.Data.ProviderBase.DbConnectionInternal to) { this._innerConnection = to; }
/// <summary> /// Creates a new connection to replace an existing connection /// </summary> /// <param name="owningObject">Outer connection that currently owns <paramref name="oldConnection"/></param> /// <param name="userOptions">Options used to create the new connection</param> /// <param name="oldConnection">Inner connection that will be replaced</param> /// <returns>A new inner connection that is attached to the <paramref name="owningObject"/></returns> internal DbConnectionInternal ReplaceConnection(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) { DbConnectionInternal newConnection = UserCreateRequest(owningObject, userOptions, oldConnection); if (newConnection != null) { PrepareConnection(owningObject, newConnection); oldConnection.PrepareForReplaceConnection(); oldConnection.DeactivateConnection(); oldConnection.Dispose(); } return(newConnection); }
private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObjectsTimeout, bool allowCreate, bool onlyOneCheckConnection, DbConnectionOptions userOptions, out DbConnectionInternal connection) { DbConnectionInternal obj = null; if (null == obj) { Interlocked.Increment(ref _waitCount); do { int waitResult = BOGUS_HANDLE; try { try { } finally { waitResult = WaitHandle.WaitAny(_waitHandles.GetHandles(allowCreate), unchecked ((int)waitForMultipleObjectsTimeout)); } // From the WaitAny docs: "If more than one object became signaled during // the call, this is the array index of the signaled object with the // smallest index value of all the signaled objects." This is important // so that the free object signal will be returned before a creation // signal. switch (waitResult) { case WaitHandle.WaitTimeout: Interlocked.Decrement(ref _waitCount); connection = null; return(false); case ERROR_HANDLE: // Throw the error that PoolCreateRequest stashed. Interlocked.Decrement(ref _waitCount); throw TryCloneCachedException(); case CREATION_HANDLE: try { obj = UserCreateRequest(owningObject, userOptions); } catch { if (null == obj) { Interlocked.Decrement(ref _waitCount); } throw; } finally { // Ensure that we release this waiter, regardless // of any exceptions that may be thrown. if (null != obj) { Interlocked.Decrement(ref _waitCount); } } if (null == obj) { // 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. if (Count >= MaxPoolSize && 0 != MaxPoolSize) { if (!ReclaimEmancipatedObjects()) { // modify handle array not to wait on creation mutex anymore Debug.Assert(2 == CREATION_HANDLE, "creation handle changed value"); allowCreate = false; } } } break; case SEMAPHORE_HANDLE: // // guaranteed available inventory // Interlocked.Decrement(ref _waitCount); obj = GetFromGeneralPool(); if ((obj != null) && (!obj.IsConnectionAlive())) { DestroyObject(obj); obj = null; // Setting to null in case creating a new object fails if (onlyOneCheckConnection) { if (_waitHandles.CreationSemaphore.WaitOne(unchecked ((int)waitForMultipleObjectsTimeout))) { try { obj = UserCreateRequest(owningObject, userOptions); } finally { _waitHandles.CreationSemaphore.Release(1); } } else { // Timeout waiting for creation semaphore - return null connection = null; return(false); } } } break; default: Interlocked.Decrement(ref _waitCount); throw ADP.InternalError(ADP.InternalErrorCode.UnexpectedWaitAnyResult); } } finally { if (CREATION_HANDLE == waitResult) { _waitHandles.CreationSemaphore.Release(1); } } } while (null == obj); } if (null != obj) { PrepareConnection(owningObject, obj); } connection = obj; return(true); }
internal bool TryGetConnection(DbConnection owningObject, TaskCompletionSource <DbConnectionInternal> retry, DbConnectionOptions userOptions, out DbConnectionInternal connection) { uint waitForMultipleObjectsTimeout = 0; bool allowCreate = false; if (retry == null) { waitForMultipleObjectsTimeout = (uint)CreationTimeout; // Set the wait timeout to INFINITE (-1) if the SQL connection timeout is 0 (== infinite) if (waitForMultipleObjectsTimeout == 0) { waitForMultipleObjectsTimeout = unchecked ((uint)Timeout.Infinite); } allowCreate = true; } if (_state != State.Running) { connection = null; return(true); } bool onlyOneCheckConnection = true; if (TryGetConnection(owningObject, waitForMultipleObjectsTimeout, allowCreate, onlyOneCheckConnection, userOptions, out connection)) { return(true); } else if (retry == null) { // timed out on a sync call return(true); } var pendingGetConnection = new PendingGetConnection( CreationTimeout == 0 ? Timeout.Infinite : ADP.TimerCurrent() + ADP.TimerFromSeconds(CreationTimeout / 1000), owningObject, retry, userOptions); _pendingOpens.Enqueue(pendingGetConnection); // it is better to StartNew too many times than not enough if (_pendingOpensWaiting == 0) { Thread waitOpenThread = new Thread(WaitForPendingOpen); waitOpenThread.IsBackground = true; waitOpenThread.Start(); } connection = null; return(false); }
public virtual DataTable GetSchema(DbConnection connection, DbConnectionInternal internalConnection, string collectionName, string[] restrictions) { throw new NotImplementedException(); }
protected virtual DbMetaDataFactory CreateMetaDataFactory (DbConnectionInternal internalConnection) { throw new NotImplementedException (); }
public virtual DataTable PrepareCollection(string collectionName, string[] restrictions, DbConnection connection, DbConnectionInternal internalConnection) { throw new NotImplementedException(); }
internal void PutObject(DbConnectionInternal obj, object owningObject) { Debug.Assert(null != obj, "null obj?"); // Once a connection is closing (which is the state that we're in at // this point in time) you cannot delegate a transaction to or enlist // a transaction in it, so we can correctly presume that if there was // not a delegated or enlisted transaction to start with, that there // will not be a delegated or enlisted transaction once we leave the // lock. lock (obj) { // Calling PrePush prevents the object from being reclaimed // once we leave the lock, because it sets _pooledCount such // that it won't appear to be out of the pool. What that // means, is that we're now responsible for this connection: // it won't get reclaimed if we drop the ball somewhere. obj.PrePush(owningObject); } DeactivateObject(obj); }
internal override bool SetInnerConnectionFrom(DbConnection owningObject, System.Data.ProviderBase.DbConnectionInternal to, System.Data.ProviderBase.DbConnectionInternal from) { OracleConnection connection = owningObject as OracleConnection; return((connection != null) && connection.SetInnerConnectionFrom(to, from)); }
private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) { DbConnectionInternal newObj = null; try { newObj = _connectionFactory.CreatePooledConnection(this, owningObject, _connectionPoolGroup.ConnectionOptions, _connectionPoolGroup.PoolKey, userOptions); if (null == newObj) { throw ADP.InternalError(ADP.InternalErrorCode.CreateObjectReturnedNull); // CreateObject succeeded, but null object } if (!newObj.CanBePooled) { throw ADP.InternalError(ADP.InternalErrorCode.NewObjectCannotBePooled); // CreateObject succeeded, but non-poolable object } newObj.PrePush(null); lock (_objectList) { if ((oldConnection != null) && (oldConnection.Pool == this)) { _objectList.Remove(oldConnection); } _objectList.Add(newObj); _totalObjects = _objectList.Count; } // If the old connection belonged to another pool, we need to remove it from that if (oldConnection != null) { var oldConnectionPool = oldConnection.Pool; if (oldConnectionPool != null && oldConnectionPool != this) { Debug.Assert(oldConnectionPool._state == State.ShuttingDown, "Old connections pool should be shutting down"); lock (oldConnectionPool._objectList) { oldConnectionPool._objectList.Remove(oldConnection); oldConnectionPool._totalObjects = oldConnectionPool._objectList.Count; } } } // Reset the error wait: _errorWait = ERROR_WAIT_DEFAULT; } catch (Exception e) { if (!ADP.IsCatchableExceptionType(e)) { throw; } newObj = null; // set to null, so we do not return bad new object // Failed to create instance _resError = e; // 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); bool timerIsNotDisposed; try { } finally { _waitHandles.ErrorEvent.Set(); _errorOccurred = true; // Enable the timer. // Note that the timer is created to allow periodic invocation. If ThreadAbort occurs in the middle of ErrorCallback, // the timer will restart. Otherwise, the timer callback (ErrorCallback) destroys the timer after resetting the error to avoid second callback. _errorTimer = t; timerIsNotDisposed = t.Change(_errorWait, _errorWait); } Debug.Assert(timerIsNotDisposed, "ErrorCallback timer has been disposed"); if (30000 < _errorWait) { _errorWait = 60000; } else { _errorWait *= 2; } throw; } return newObj; }
protected override System.Data.ProviderBase.DbMetaDataFactory CreateMetaDataFactory(System.Data.ProviderBase.DbConnectionInternal internalConnection, out bool cacheMetaDataFactory) { cacheMetaDataFactory = false; NameValueCollection section = (NameValueCollection)System.Configuration.PrivilegedConfigurationManager.GetSection("system.data.oracleclient"); Stream xmlStream = null; if (section != null) { string[] values = section.GetValues("MetaDataXml"); if (values != null) { xmlStream = System.Data.Common.ADP.GetXmlStreamFromValues(values, "MetaDataXml"); } } if (xmlStream == null) { xmlStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("System.Data.OracleClient.OracleMetaData.xml"); cacheMetaDataFactory = true; } return(new System.Data.ProviderBase.DbMetaDataFactory(xmlStream, internalConnection.ServerVersion, internalConnection.ServerVersionNormalized)); }
internal void DestroyObject(DbConnectionInternal obj) { // A connection with a delegated transaction cannot be disposed of // until the delegated transaction has actually completed. Instead, // we simply leave it alone; when the transaction completes, it will // come back through PutObjectFromTransactedPool, which will call us // again. bool removed = false; lock (_objectList) { removed = _objectList.Remove(obj); Debug.Assert(removed, "attempt to DestroyObject not in list"); _totalObjects = _objectList.Count; } if (removed) { } obj.Dispose(); }
protected internal DbMetaDataFactory GetMetaDataFactory(DbConnectionString connectionOptions, DbConnectionInternal internalConnection) { throw new NotImplementedException(); }
private void DeactivateObject(DbConnectionInternal obj) { obj.DeactivateConnection(); bool returnToGeneralPool = false; bool destroyObject = false; if (obj.IsConnectionDoomed) { // the object is not fit for reuse -- just dispose of it. destroyObject = true; } else { // NOTE: constructor should ensure that current state cannot be State.Initializing, so it can only // be State.Running or State.ShuttingDown Debug.Assert(_state == State.Running || _state == State.ShuttingDown); lock (obj) { // A connection with a delegated transaction cannot currently // be returned to a different customer until the transaction // actually completes, so we send it into Stasis -- the SysTx // transaction object will ensure that it is owned (not lost), // and it will be certain to put it back into the pool. if (_state == State.ShuttingDown) { // connection is being closed and the pool has been marked as shutting // down, so destroy this object. destroyObject = true; } else { if (obj.CanBePooled) { // We must put this connection into the transacted pool // while inside a lock to prevent a race condition with // the transaction asynchronously completing on a second // thread. // return to general pool returnToGeneralPool = true; } else { // object is not fit for reuse -- just dispose of it destroyObject = true; } } } } if (returnToGeneralPool) { // Only push the connection into the general pool if we didn't // already push it onto the transacted pool, put it into stasis, // or want to destroy it. Debug.Assert(destroyObject == false); PutNewObject(obj); } else if (destroyObject) { DestroyObject(obj); QueuePoolCreateRequest(); } //------------------------------------------------------------------------------------- // postcondition // ensure that the connection was processed Debug.Assert( returnToGeneralPool == true || destroyObject == true); }
protected virtual IAsyncResult BeginCreateConnection(DbConnectionBase owningObject, DbConnectionString connectionOptions, DbConnectionInternal connection, AsyncCallback callback, object asyncStateObject) { throw new NotImplementedException(); }
internal bool TryGetConnection(DbConnection owningConnection, TaskCompletionSource<DbConnectionInternal> retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, out DbConnectionInternal connection) { Debug.Assert(null != owningConnection, "null owningConnection?"); DbConnectionPoolGroup poolGroup; DbConnectionPool connectionPool; connection = null; // Work around race condition with clearing the pool between GetConnectionPool obtaining pool // and GetConnection on the pool checking the pool state. Clearing the pool in this window // will switch the pool into the ShuttingDown state, and GetConnection will return null. // There is probably a better solution involving locking the pool/group, but that entails a major // re-design of the connection pooling synchronization, so is post-poned for now. // Use retriesLeft to prevent CPU spikes with incremental sleep // start with one msec, double the time every retry // max time is: 1 + 2 + 4 + ... + 2^(retries-1) == 2^retries -1 == 1023ms (for 10 retries) int retriesLeft = 10; int timeBetweenRetriesMilliseconds = 1; do { poolGroup = GetConnectionPoolGroup(owningConnection); // Doing this on the callers thread is important because it looks up the WindowsIdentity from the thread. connectionPool = GetConnectionPool(owningConnection, poolGroup); if (null == connectionPool) { // If GetConnectionPool returns null, we can be certain that // this connection should not be pooled via DbConnectionPool // or have a disabled pool entry. poolGroup = GetConnectionPoolGroup(owningConnection); // previous entry have been disabled if (retry != null) { Task<DbConnectionInternal> newTask; CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); lock (s_pendingOpenNonPooled) { // look for an available task slot (completed or empty) int idx; for (idx = 0; idx < s_pendingOpenNonPooled.Length; idx++) { Task task = s_pendingOpenNonPooled[idx]; if (task == null) { s_pendingOpenNonPooled[idx] = GetCompletedTask(); break; } else if (task.IsCompleted) { break; } } // if didn't find one, pick the next one in round-robbin fashion if (idx == s_pendingOpenNonPooled.Length) { idx = s_pendingOpenNonPooledNext++ % s_pendingOpenNonPooled.Length; } // now that we have an antecedent task, schedule our work when it is completed. // If it is a new slot or a compelted task, this continuation will start right away. newTask = s_pendingOpenNonPooled[idx].ContinueWith((_) => { var newConnection = CreateNonPooledConnection(owningConnection, poolGroup, userOptions); if ((oldConnection != null) && (oldConnection.State == ConnectionState.Open)) { oldConnection.PrepareForReplaceConnection(); oldConnection.Dispose(); } return newConnection; }, cancellationTokenSource.Token, TaskContinuationOptions.LongRunning, TaskScheduler.Default); // Place this new task in the slot so any future work will be queued behind it s_pendingOpenNonPooled[idx] = newTask; } // Set up the timeout (if needed) if (owningConnection.ConnectionTimeout > 0) { int connectionTimeoutMilliseconds = owningConnection.ConnectionTimeout * 1000; cancellationTokenSource.CancelAfter(connectionTimeoutMilliseconds); } // once the task is done, propagate the final results to the original caller newTask.ContinueWith((task) => { cancellationTokenSource.Dispose(); if (task.IsCanceled) { retry.TrySetException(ADP.ExceptionWithStackTrace(ADP.NonPooledOpenTimeout())); } else if (task.IsFaulted) { retry.TrySetException(task.Exception.InnerException); } else { if (!retry.TrySetResult(task.Result)) { // The outer TaskCompletionSource was already completed // Which means that we don't know if someone has messed with the outer connection in the middle of creation // So the best thing to do now is to destroy the newly created connection task.Result.DoomThisConnection(); task.Result.Dispose(); } } }, TaskScheduler.Default); return false; } connection = CreateNonPooledConnection(owningConnection, poolGroup, userOptions); } else { if (((SqlClient.SqlConnection)owningConnection).ForceNewConnection) { Debug.Assert(!(oldConnection is DbConnectionClosed), "Force new connection, but there is no old connection"); connection = connectionPool.ReplaceConnection(owningConnection, userOptions, oldConnection); } else { if (!connectionPool.TryGetConnection(owningConnection, retry, userOptions, out connection)) { return false; } } if (connection == null) { // connection creation failed on semaphore waiting or if max pool reached if (connectionPool.IsRunning) { // If GetConnection failed while the pool is running, the pool timeout occurred. throw ADP.PooledOpenTimeout(); } else { // We've hit the race condition, where the pool was shut down after we got it from the group. // Yield time slice to allow shut down activities to complete and a new, running pool to be instantiated // before retrying. Threading.Thread.Sleep(timeBetweenRetriesMilliseconds); timeBetweenRetriesMilliseconds *= 2; // double the wait time for next iteration } } } } while (connection == null && retriesLeft-- > 0); if (connection == null) { // exhausted all retries or timed out - give up throw ADP.PooledOpenTimeout(); } return true; }
protected virtual DbMetaDataFactory CreateMetaDataFactory(DbConnectionInternal internalConnection) { throw new NotImplementedException(); }
abstract internal void SetInnerConnectionTo(DbConnection owningObject, DbConnectionInternal to);
internal bool TryGetConnection(DbConnection owningConnection, TaskCompletionSource <DbConnectionInternal> retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, out DbConnectionInternal connection) { Debug.Assert(null != owningConnection, "null owningConnection?"); DbConnectionPoolGroup poolGroup; DbConnectionPool connectionPool; connection = null; // Work around race condition with clearing the pool between GetConnectionPool obtaining pool // and GetConnection on the pool checking the pool state. Clearing the pool in this window // will switch the pool into the ShuttingDown state, and GetConnection will return null. // There is probably a better solution involving locking the pool/group, but that entails a major // re-design of the connection pooling synchronization, so is postponed for now. // Use retriesLeft to prevent CPU spikes with incremental sleep // start with one msec, double the time every retry // max time is: 1 + 2 + 4 + ... + 2^(retries-1) == 2^retries -1 == 1023ms (for 10 retries) int retriesLeft = 10; int timeBetweenRetriesMilliseconds = 1; do { poolGroup = GetConnectionPoolGroup(owningConnection); // Doing this on the callers thread is important because it looks up the WindowsIdentity from the thread. connectionPool = GetConnectionPool(owningConnection, poolGroup); if (null == connectionPool) { // If GetConnectionPool returns null, we can be certain that // this connection should not be pooled via DbConnectionPool // or have a disabled pool entry. poolGroup = GetConnectionPoolGroup(owningConnection); // previous entry have been disabled if (retry != null) { Task <DbConnectionInternal> newTask; CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); lock (s_pendingOpenNonPooled) { // look for an available task slot (completed or empty) int idx; for (idx = 0; idx < s_pendingOpenNonPooled.Length; idx++) { Task task = s_pendingOpenNonPooled[idx]; if (task == null) { s_pendingOpenNonPooled[idx] = GetCompletedTask(); break; } else if (task.IsCompleted) { break; } } // if didn't find one, pick the next one in round-robin fashion if (idx == s_pendingOpenNonPooled.Length) { idx = (int)(s_pendingOpenNonPooledNext % s_pendingOpenNonPooled.Length); unchecked { s_pendingOpenNonPooledNext++; } } // now that we have an antecedent task, schedule our work when it is completed. // If it is a new slot or a completed task, this continuation will start right away. newTask = s_pendingOpenNonPooled[idx].ContinueWith((_) => { var newConnection = CreateNonPooledConnection(owningConnection, poolGroup, userOptions); if ((oldConnection != null) && (oldConnection.State == ConnectionState.Open)) { oldConnection.PrepareForReplaceConnection(); oldConnection.Dispose(); } return(newConnection); }, cancellationTokenSource.Token, TaskContinuationOptions.LongRunning, TaskScheduler.Default); // Place this new task in the slot so any future work will be queued behind it s_pendingOpenNonPooled[idx] = newTask; } // Set up the timeout (if needed) if (owningConnection.ConnectionTimeout > 0) { int connectionTimeoutMilliseconds = owningConnection.ConnectionTimeout * 1000; cancellationTokenSource.CancelAfter(connectionTimeoutMilliseconds); } // once the task is done, propagate the final results to the original caller newTask.ContinueWith((task) => { cancellationTokenSource.Dispose(); if (task.IsCanceled) { retry.TrySetException(ADP.ExceptionWithStackTrace(ADP.NonPooledOpenTimeout())); } else if (task.IsFaulted) { retry.TrySetException(task.Exception.InnerException); } else { if (!retry.TrySetResult(task.Result)) { // The outer TaskCompletionSource was already completed // Which means that we don't know if someone has messed with the outer connection in the middle of creation // So the best thing to do now is to destroy the newly created connection task.Result.DoomThisConnection(); task.Result.Dispose(); } } }, TaskScheduler.Default); return(false); } connection = CreateNonPooledConnection(owningConnection, poolGroup, userOptions); } else { if (((SqlClient.SqlConnection)owningConnection).ForceNewConnection) { Debug.Assert(!(oldConnection is DbConnectionClosed), "Force new connection, but there is no old connection"); connection = connectionPool.ReplaceConnection(owningConnection, userOptions, oldConnection); } else { if (!connectionPool.TryGetConnection(owningConnection, retry, userOptions, out connection)) { return(false); } } if (connection == null) { // connection creation failed on semaphore waiting or if max pool reached if (connectionPool.IsRunning) { // If GetConnection failed while the pool is running, the pool timeout occurred. throw ADP.PooledOpenTimeout(); } else { // We've hit the race condition, where the pool was shut down after we got it from the group. // Yield time slice to allow shut down activities to complete and a new, running pool to be instantiated // before retrying. Threading.Thread.Sleep(timeBetweenRetriesMilliseconds); timeBetweenRetriesMilliseconds *= 2; // double the wait time for next iteration } } } } while (connection == null && retriesLeft-- > 0); if (connection == null) { // exhausted all retries or timed out - give up throw ADP.PooledOpenTimeout(); } return(true); }
protected virtual IAsyncResult BeginCreateConnection (DbConnectionBase owningObject, DbConnectionString connectionOptions, DbConnectionInternal connection, AsyncCallback callback, object asyncStateObject) { throw new NotImplementedException (); }
abstract internal void SetInnerConnectionEvent(DbConnection owningObject, DbConnectionInternal to);
internal void PutNewObject(DbConnectionInternal obj) { Debug.Assert(null != obj, "why are we adding a null object to the pool?"); // Debug.Assert(obj.CanBePooled, "non-poolable object in pool"); _stackNew.Push(obj); _waitHandles.PoolSemaphore.Release(1); }
internal DbMetaDataFactory GetMetaDataFactory(DbConnectionPoolGroup connectionPoolGroup, DbConnectionInternal internalConnection) { Debug.Assert(connectionPoolGroup != null, "connectionPoolGroup may not be null."); // get the matadatafactory from the pool entry. If it does not already have one // create one and save it on the pool entry DbMetaDataFactory?metaDataFactory = connectionPoolGroup.MetaDataFactory; // consider serializing this so we don't construct multiple metadata factories // if two threads happen to hit this at the same time. One will be GC'd if (metaDataFactory == null) { metaDataFactory = CreateMetaDataFactory(internalConnection); connectionPoolGroup.MetaDataFactory = metaDataFactory; } return(metaDataFactory); }
private DbConnectionInternal UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection = null) { // called by user when they were not able to obtain a free object but // instead obtained creation mutex DbConnectionInternal obj = null; if (ErrorOccurred) { throw TryCloneCachedException(); } else { if ((oldConnection != null) || (Count < MaxPoolSize) || (0 == MaxPoolSize)) { // 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; } }
protected abstract DbMetaDataFactory CreateMetaDataFactory(DbConnectionInternal internalConnection);
internal abstract bool SetInnerConnectionFrom(DbConnection owningObject, DbConnectionInternal to, DbConnectionInternal from);
internal bool TryGetConnection(DbConnection owningObject, TaskCompletionSource<DbConnectionInternal> retry, DbConnectionOptions userOptions, out DbConnectionInternal connection) { uint waitForMultipleObjectsTimeout = 0; bool allowCreate = false; if (retry == null) { waitForMultipleObjectsTimeout = (uint)CreationTimeout; // Set the wait timeout to INFINITE (-1) if the SQL connection timeout is 0 (== infinite) if (waitForMultipleObjectsTimeout == 0) waitForMultipleObjectsTimeout = unchecked((uint)Timeout.Infinite); allowCreate = true; } if (_state != State.Running) { connection = null; return true; } bool onlyOneCheckConnection = true; if (TryGetConnection(owningObject, waitForMultipleObjectsTimeout, allowCreate, onlyOneCheckConnection, userOptions, out connection)) { return true; } else if (retry == null) { // timed out on a sync call return true; } var pendingGetConnection = new PendingGetConnection( CreationTimeout == 0 ? Timeout.Infinite : ADP.TimerCurrent() + ADP.TimerFromSeconds(CreationTimeout / 1000), owningObject, retry, userOptions); _pendingOpens.Enqueue(pendingGetConnection); // it is better to StartNew too many times than not enough if (_pendingOpensWaiting == 0) { Thread waitOpenThread = new Thread(WaitForPendingOpen); waitOpenThread.IsBackground = true; waitOpenThread.Start(); } connection = null; return false; }
internal abstract void SetInnerConnectionTo(DbConnection owningObject, DbConnectionInternal to);
private void PrepareConnection(DbConnection owningObject, DbConnectionInternal obj) { lock (obj) { // Protect against Clear and ReclaimEmancipatedObjects, which call IsEmancipated, which is affected by PrePush and PostPop obj.PostPop(owningObject); } try { obj.ActivateConnection(); } catch { // if Activate throws an exception // put it back in the pool or have it properly disposed of this.PutObject(obj, owningObject); throw; } }
private bool ReclaimEmancipatedObjects() { bool emancipatedObjectFound = false; List <DbConnectionInternal> reclaimedObjects = new List <DbConnectionInternal>(); int count; lock (_objectList) { count = _objectList.Count; for (int i = 0; i < count; ++i) { DbConnectionInternal obj = _objectList[i]; if (null != obj) { bool locked = false; try { Monitor.TryEnter(obj, ref locked); if (locked) { // avoid race condition with PrePush/PostPop and IsEmancipated if (obj.IsEmancipated) { // Inside the lock, we want to do as little // as possible, so we simply mark the object // as being in the pool, but hand it off to // an out of pool list to be deactivated, // etc. obj.PrePush(null); reclaimedObjects.Add(obj); } } } finally { if (locked) { Monitor.Exit(obj); } } } } } // NOTE: we don't want to call DeactivateObject while we're locked, // because it can make roundtrips to the server and this will block // object creation in the pooler. Instead, we queue things we need // to do up, and process them outside the lock. count = reclaimedObjects.Count; for (int i = 0; i < count; ++i) { DbConnectionInternal obj = reclaimedObjects[i]; emancipatedObjectFound = true; DeactivateObject(obj); } return(emancipatedObjectFound); }
override protected DbMetaDataFactory CreateMetaDataFactory(DbConnectionInternal internalConnection, out bool cacheMetaDataFactory){ Debug.Assert (internalConnection != null, "internalConnection may not be null."); cacheMetaDataFactory = false; if (internalConnection is SqlInternalConnectionSmi) { throw SQL.NotAvailableOnContextConnection(); } Stream XMLStream =null; #if !NO_CONFIGURATION NameValueCollection settings = (NameValueCollection)PrivilegedConfigurationManager.GetSection("system.data.sqlclient"); if (settings != null){ string [] values = settings.GetValues(_metaDataXml); if (values != null) { XMLStream = ADP.GetXmlStreamFromValues(values, _metaDataXml); } } #endif // if the xml was not obtained from machine.config use the embedded XML resource if (XMLStream == null){ XMLStream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("System.Data.SqlClient.SqlMetaData.xml"); cacheMetaDataFactory = true; } Debug.Assert (XMLStream != null,"XMLstream may not be null."); return new SqlMetaDataFactory (XMLStream, internalConnection.ServerVersion, internalConnection.ServerVersion); //internalConnection.ServerVersionNormalized); }
private DbConnectionInternal UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection = null) { // called by user when they were not able to obtain a free object but // instead obtained creation mutex DbConnectionInternal obj = null; if (ErrorOccurred) { throw TryCloneCachedException(); } else { if ((oldConnection != null) || (Count < MaxPoolSize) || (0 == MaxPoolSize)) { // 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); } }
override internal void SetInnerConnectionTo(DbConnection owningObject, DbConnectionInternal to) { SqlConnection c = (owningObject as SqlConnection); if (null != c) { c.SetInnerConnectionTo(to); } }
private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) { DbConnectionInternal newObj = null; try { newObj = _connectionFactory.CreatePooledConnection(this, owningObject, _connectionPoolGroup.ConnectionOptions, _connectionPoolGroup.PoolKey, userOptions); if (null == newObj) { throw ADP.InternalError(ADP.InternalErrorCode.CreateObjectReturnedNull); // CreateObject succeeded, but null object } if (!newObj.CanBePooled) { throw ADP.InternalError(ADP.InternalErrorCode.NewObjectCannotBePooled); // CreateObject succeeded, but non-poolable object } newObj.PrePush(null); lock (_objectList) { if ((oldConnection != null) && (oldConnection.Pool == this)) { _objectList.Remove(oldConnection); } _objectList.Add(newObj); _totalObjects = _objectList.Count; } // If the old connection belonged to another pool, we need to remove it from that if (oldConnection != null) { var oldConnectionPool = oldConnection.Pool; if (oldConnectionPool != null && oldConnectionPool != this) { Debug.Assert(oldConnectionPool._state == State.ShuttingDown, "Old connections pool should be shutting down"); lock (oldConnectionPool._objectList) { oldConnectionPool._objectList.Remove(oldConnection); oldConnectionPool._totalObjects = oldConnectionPool._objectList.Count; } } } // Reset the error wait: _errorWait = ERROR_WAIT_DEFAULT; } catch (Exception e) { if (!ADP.IsCatchableExceptionType(e)) { throw; } newObj = null; // set to null, so we do not return bad new object // Failed to create instance _resError = e; // 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); bool timerIsNotDisposed; try { } finally { _waitHandles.ErrorEvent.Set(); _errorOccurred = true; // Enable the timer. // Note that the timer is created to allow periodic invocation. If ThreadAbort occurs in the middle of ErrorCallback, // the timer will restart. Otherwise, the timer callback (ErrorCallback) destroys the timer after resetting the error to avoid second callback. _errorTimer = t; timerIsNotDisposed = t.Change(_errorWait, _errorWait); } Debug.Assert(timerIsNotDisposed, "ErrorCallback timer has been disposed"); if (30000 < _errorWait) { _errorWait = 60000; } else { _errorWait *= 2; } throw; } return(newObj); }