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());
 }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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);
        }
예제 #5
0
        internal override void SetInnerConnectionTo(DbConnection owningObject, System.Data.ProviderBase.DbConnectionInternal to)
        {
            OracleConnection connection = owningObject as OracleConnection;

            if (connection != null)
            {
                connection.SetInnerConnectionTo(to);
            }
        }
예제 #6
0
 internal OracleInternalConnection GetOpenInternalConnection()
 {
     System.Data.ProviderBase.DbConnectionInternal innerConnection = this.InnerConnection;
     if (!(innerConnection is OracleInternalConnection))
     {
         throw System.Data.Common.ADP.ClosedConnectionError();
     }
     return(innerConnection as OracleInternalConnection);
 }
예제 #7
0
        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());
        }
예제 #8
0
 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;
     }
 }
예제 #9
0
        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;
            }
        }
예제 #10
0
 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());
     }
 }
예제 #11
0
 // 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;
     }
 }
예제 #12
0
 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);
 }
예제 #13
0
 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);
 }
예제 #15
0
        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;
 }
예제 #17
0
        /// <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;
        }
예제 #18
0
        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;
        }
예제 #19
0
        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));
        }
예제 #20
0
        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();
                    }
                }
            }
        }
예제 #21
0
        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);
        }
예제 #22
0
 abstract internal bool SetInnerConnectionFrom(DbConnection owningObject, DbConnectionInternal to, DbConnectionInternal from);
예제 #23
0
		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;
 }
예제 #26
0
        /// <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);
        }
예제 #27
0
        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);
        }
예제 #28
0
        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);
        }
예제 #29
0
 public virtual DataTable GetSchema(DbConnection connection, DbConnectionInternal internalConnection, string collectionName, string[] restrictions)
 {
     throw new NotImplementedException();
 }
예제 #30
0
		protected virtual DbMetaDataFactory CreateMetaDataFactory (DbConnectionInternal internalConnection)
		{
			throw new NotImplementedException ();
		}
예제 #31
0
 public virtual DataTable PrepareCollection(string collectionName, string[] restrictions, DbConnection connection, DbConnectionInternal internalConnection)
 {
     throw new NotImplementedException();
 }
예제 #32
0
        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);
        }
예제 #33
0
        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));
        }
예제 #34
0
        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;
        }
예제 #35
0
        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));
        }
예제 #36
0
        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();
        }
예제 #37
0
 protected internal DbMetaDataFactory GetMetaDataFactory(DbConnectionString connectionOptions, DbConnectionInternal internalConnection)
 {
     throw new NotImplementedException();
 }
예제 #38
0
        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);
        }
 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));
     }
 }
예제 #40
0
 protected virtual IAsyncResult BeginCreateConnection(DbConnectionBase owningObject, DbConnectionString connectionOptions, DbConnectionInternal connection, AsyncCallback callback, object asyncStateObject)
 {
     throw new NotImplementedException();
 }
예제 #41
0
        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;
        }
예제 #42
0
 protected virtual DbMetaDataFactory CreateMetaDataFactory(DbConnectionInternal internalConnection)
 {
     throw new NotImplementedException();
 }
예제 #43
0
 abstract internal void SetInnerConnectionTo(DbConnection owningObject, DbConnectionInternal to);
예제 #44
0
        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);
        }
예제 #45
0
		protected virtual IAsyncResult BeginCreateConnection (DbConnectionBase owningObject, DbConnectionString connectionOptions, DbConnectionInternal connection, AsyncCallback callback, object asyncStateObject)
		{
			throw new NotImplementedException ();
		}
예제 #46
0
 abstract internal void SetInnerConnectionEvent(DbConnection owningObject, DbConnectionInternal to);
예제 #47
0
        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);
        }
예제 #48
0
        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);
        }
예제 #49
0
        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;
            }
        }
예제 #50
0
 protected abstract DbMetaDataFactory CreateMetaDataFactory(DbConnectionInternal internalConnection);
예제 #51
0
        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);
        }
예제 #52
0
 internal abstract bool SetInnerConnectionFrom(DbConnection owningObject, DbConnectionInternal to, DbConnectionInternal from);
예제 #53
0
        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;
        }
예제 #54
0
 internal abstract void SetInnerConnectionTo(DbConnection owningObject, DbConnectionInternal to);
예제 #55
0
 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;
     }
 }
예제 #56
0
        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);

        }
예제 #58
0
        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);
     }
 }
예제 #60
0
        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);
        }