Beispiel #1
0
        private DBPooledObject TryGetResourceFromContext(out bool isInTransaction)
        {
            isInTransaction = false;

            DBPooledObject obj = null;

            try {
                if (PoolControl.TransactionAffinity && ContextUtil.IsInTransaction)
                {
                    isInTransaction = true;
                    if (null != _txPool)
                    {
                        obj = (DBPooledObject)_txPool.GetResource();
                    }
                }
                else
                {
                    isInTransaction = false;
                }
            }
            catch (Exception e) {
                ADP.TraceException(e);
            }
#if ALLOWTRACING
            if (null != obj)
            {
                ADP.TraceObjectPoolActivity("GetFromTransactedPool", obj);
            }
#endif //ALLOWTRACING
            return(obj);
        }
 static internal void TraceObjectPoolActivity(string eventName, DBPooledObject pooledObject)
 {
     if (_traceObjectPoolActivity)
     {
         Debug.WriteLine(String.Format("*** {0,-24} svcctx=0x{1}",
                                       eventName,
                                       ((IntPtr)((OracleInternalConnection)pooledObject).ServiceContextHandle.Handle).ToInt64().ToString("x")
                                       ));
     }
 }
Beispiel #3
0
        private void PutNewObject(DBPooledObject obj)
        {
            Debug.Assert(null != obj, "why are we adding a null object to the pool?");

#if ALLOWTRACING
            ADP.TraceObjectPoolActivity("PutToGeneralPool", obj);
#endif //ALLOWTRACING
            _stackNew.Push(obj);
#if USECOUNTEROBJECT
            _poolCounter.Modify(cAddFree);
#endif //USECOUNTEROBJECT
            SafeNativeMethods.ReleaseSemaphore(_waitHandles[SEMAPHORE_HANDLE].Handle, 1, IntPtr.Zero);
        }
Beispiel #4
0
        private void DestroyObject(DBPooledObject obj)
        {
#if ALLOWTRACING
            ADP.TraceObjectPoolActivity("DestroyObject", obj);
#endif //ALLOWTRACING

            lock (_objectList.SyncRoot) {
                _objectList.Remove(obj);
#if !USECOUNTEROBJECT
                _totalObjects = _objectList.Count;
#endif //!USECOUNTEROBJECT
            }
#if USECOUNTEROBJECT
            _poolCounter.Modify(-cAddTotal);
#endif //USECOUNTEROBJECT
            PoolControl.DestroyObject(this, obj);
        }
Beispiel #5
0
        private DBPooledObject CreateObject()
        {
            DBPooledObject newObj = null;

            try {
                newObj = PoolControl.CreateObject(this);

                Debug.Assert(newObj != null, "CreateObject succeeded, but object null");

                newObj.PrePush(null);

                lock (_objectList.SyncRoot) {
                    _objectList.Add(newObj);
#if !USECOUNTEROBJECT
                    _totalObjects = _objectList.Count;
#endif //!USECOUNTEROBJECT
                }
#if USECOUNTEROBJECT
                _poolCounter.Modify(cAddTotal);
#endif //USECOUNTEROBJECT

#if ALLOWTRACING
                ADP.TraceObjectPoolActivity("CreateObject", newObj);
#endif //ALLOWTRACING

                // Reset the error wait:
                _errorWait = ERROR_WAIT_DEFAULT;
            }
            catch (Exception e)  {
                ADP.TraceException(e);

                newObj = null; // set to null, so we do not return bad new object
                // Failed to create instance
                _resError = e;
                SafeNativeMethods.SetEvent(_waitHandles[ERROR_HANDLE].Handle);
#if USECOUNTEROBJECT
                _poolCounter.Modify(cErrorFlag);
#else //!USECOUNTEROBJECT
                _errorOccurred = true;
#endif //!USECOUNTEROBJECT
                _errorTimer = new Timer(new TimerCallback(this.ErrorCallback), null, _errorWait, _errorWait);
                _errorWait *= 2;
            }

            return(newObj);
        }
Beispiel #6
0
            private void ReturnToPool()
            {
                if (_signaled)
                {
                    if (null != _pooledObject && null != _pool)
                    {
                        _pool.PutNewObject(_pooledObject);
                        _pool         = null;
                        _pooledObject = null;
                    }

                    if (0 != _cookie && null != _point)
                    {
                        _point.Unadvise(_cookie);
                        _point  = null;
                        _cookie = 0;
                    }
                }
            }
Beispiel #7
0
        private bool TryPutResourceInContext(DBPooledObject obj)
        {
            try {
                if (PoolControl.TransactionAffinity && ContextUtil.IsInTransaction)
                {
                    if (null != _txPool)
                    {
                        if (_txPool.PutResource(obj))
                        {
#if ALLOWTRACING
                            ADP.TraceObjectPoolActivity("PutToTransactedPool", obj);
#endif //ALLOWTRACING
                            return(true);
                        }
                    }
                }
            }
            catch (Exception e) {
                ADP.TraceException(e);
            }
            return(false);
        }
Beispiel #8
0
        private DBPooledObject GetFromPool(object owningObject)
        {
            DBPooledObject res = null;

            res = (DBPooledObject)_stackNew.Pop();
            if (res == null)
            {
                res = (DBPooledObject)_stackOld.Pop();
            }

            // Shouldn't be null, we could assert here.
            Debug.Assert(res != null, "GetFromPool called with nothing in the pool!");

            if (null != res)
            {
                res.PostPop(owningObject);
#if ALLOWTRACING
                ADP.TraceObjectPoolActivity("GetFromGeneralPool", res);
#endif //ALLOWTRACING
            }

            return(res);
        }
Beispiel #9
0
        public void PutObject(DBPooledObject obj, object owningObject)
        {
            if (obj == null)
            {
                throw ADP.ArgumentNull("obj");
            }

            obj.PrePush(owningObject);

            if (_state != State.ShuttingDown)
            {
                bool isInTransaction = obj.Deactivate();

                if (obj.CanBePooled())
                {
#if USEORAMTS
                    ITransaction transaction = obj.ManualEnlistedTransaction;

                    if (null != transaction)
                    {
                        // When the object is put back into the pool while it is manually
                        // enlisted in a distributed transaction, we must create an outcome
                        // event and let the object wait until the distributed transaction
                        // has finished.  Once it does, the TransactionOutcomeEvents class
                        // can put it back into the general population of the pool.

                        UCOMIConnectionPoint point = (UCOMIConnectionPoint)transaction;

                        TransactionOutcomeEvents outcomeEvent = new TransactionOutcomeEvents(this, obj, point);

                        Int32 cookie = 0;
                        point.Advise(outcomeEvent, out cookie); // Register for callbacks, obtain cookie
                        outcomeEvent.SetCookie(cookie);         // Set the cookie on the event

#if ALLOWTRACING
                        ADP.TraceObjectPoolActivity("WaitForOutcomeEvnt", obj);
#endif //ALLOWTRACING
                        return;
                    }
#endif //USEORAMTS
                    // Try shoving it in the tx context first.  If that succeeds,
                    // we're done.
                    if (isInTransaction && TryPutResourceInContext(obj))
                    {
                        return;
                    }

                    // If the above failed, we just shove it into our current collection
                    PutNewObject(obj);
                }
                else
                {
                    DestroyObject(obj);
                    // Make sure we're at quota by posting a callback to the threadpool.
                    ThreadPool.QueueUserWorkItem(new WaitCallback(PoolCreateRequest));
                }
            }
            else
            {
                // If we're shutting down, we destroy the object.
                DestroyObject(obj);
            }
        }
Beispiel #10
0
        public DBPooledObject GetObject(object owningObject, out bool isInTransaction)
        {
            DBPooledObject obj = null;

            isInTransaction = false;

            if (_state != State.Running)
            {
                return(null);
            }

            // Try to get from the context if we're context specific:
            obj = TryGetResourceFromContext(out isInTransaction);

            if (null != obj)
            {
                obj.PostPop(owningObject);
            }
            else
            {
#if USECOUNTEROBJECT
                _poolCounter.Modify(cAddWait);
#else //!USECOUNTEROBJECT
                Interlocked.Increment(ref _waitCount);
#endif //!USECOUNTEROBJECT

                ObjectPoolWaitHandle[] localWaitHandles = _waitHandles;

                while (obj == null)
                {
                    int r = WaitHandle.WaitAny(localWaitHandles, PoolControl.CreationTimeout, false);

                    // 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 (r)
                    {
                    case WAIT_TIMEOUT:
#if USECOUNTEROBJECT
                        _poolCounter.Modify(-cAddWait);
#else //!USECOUNTEROBJECT
                        Interlocked.Decrement(ref _waitCount);
#endif //!USECOUNTEROBJECT
                        return(null);

                    case ERROR_HANDLE:
                        // Throw the error that PoolCreateRequest stashed.
#if USECOUNTEROBJECT
                        _poolCounter.Modify(-cAddWait);
#else //!USECOUNTEROBJECT
                        Interlocked.Decrement(ref _waitCount);
#endif //!USECOUNTEROBJECT
                        throw _resError;

                    case CREATION_HANDLE:
                        try {
                            obj = UserCreateRequest();

                            if (null != obj)
                            {
                                obj.PostPop(owningObject);
#if USECOUNTEROBJECT
                                _poolCounter.Modify(-cAddWait);
#else //!USECOUNTEROBJECT
                                Interlocked.Decrement(ref _waitCount);
#endif //!USECOUNTEROBJECT
                            }
                            else
                            {
                                // If we were not able to create an object, check to see if
                                // we reached MaxPool.  If so, we will no longer wait on the
                                // CreationHandle, but instead wait for a free object or
                                // the timeout.

                                // BUG - if we receive the CreationHandle midway into the wait
                                // period and re-wait, we will be waiting on the full period
#if USECOUNTEROBJECT
                                if (_poolCounter.TotalCount == PoolControl.MaxPool)
                                {
#else //!USECOUNTEROBJECT
                                if (Count >= PoolControl.MaxPool)
                                {
#endif //!USECOUNTEROBJECT
                                    if (!ReclaimEmancipatedObjects())
                                    {
                                        // modify handle array not to wait on creation mutex anymore
                                        localWaitHandles    = new ObjectPoolWaitHandle[2];
                                        localWaitHandles[0] = _waitHandles[0];
                                        localWaitHandles[1] = _waitHandles[1];
                                    }
                                }
                            }
                        }
                        finally {
                            _creationMutex.ReleaseMutex();
                        }
                        break;

                    default:
                        //
                        //  guaranteed available inventory
                        //
#if USECOUNTEROBJECT
                        _poolCounter.Modify(-cAddWait - cAddFree);
#else //!USECOUNTEROBJECT
                        Interlocked.Decrement(ref _waitCount);
#endif //!USECOUNTEROBJECT
                        obj = GetFromPool(owningObject);
                        break;
                    }
                }
            }
            Debug.Assert(obj != null, "Failed to create pooled object, resulted in null instance.");

            if (null != obj)
            {
                obj.Activate();
            }

            return(obj);
        }
Beispiel #11
0
        private void CleanupCallback(Object state)
        {
            // Called when the cleanup-timer ticks over.
            //
            // This is the automatic prunning method.  Every period, we will perform a two-step
            // process.  First, for the objects above MinPool, we will obtain the semaphore for
            // the object and then destroy it if it was on the old stack.  We will continue this
            // until we either reach MinPool size, or we are unable to obtain a free object, or
            // until we have exhausted all the objects on the old stack.  After that, push all
            // objects on the new stack to the old stack.  So, every period the objects on the
            // old stack are destroyed and the objects on the new stack are pushed to the old
            // stack.  All objects that are currently out and in use are not on either stack.
            // With this logic, a object is prunned if unused for at least one period but not
            // more than two periods.

            // Destroy free objects above MinPool size from old stack.
#if USECOUNTEROBJECT
            while (_poolCounter.TotalCount > _ctrl.MinPool)
#else //!USECOUNTEROBJECT
            while (Count > _ctrl.MinPool)
#endif //!USECOUNTEROBJECT
            {
                // While above MinPoolSize...

                if (_waitHandles[SEMAPHORE_HANDLE].WaitOne(0, false) /* != WAIT_TIMEOUT */)
                {
                    // We obtained a objects from the semaphore.
                    DBPooledObject obj = (DBPooledObject)_stackOld.Pop();

                    if (null != obj)
                    {
                        // If we obtained one from the old stack, destroy it.
#if USECOUNTEROBJECT
                        _poolCounter.Modify(-cAddFree);
#endif //USECOUNTEROBJECT
                        DestroyObject(obj);
                    }
                    else
                    {
                        // Else we exhausted the old stack, so break.
                        SafeNativeMethods.ReleaseSemaphore(_waitHandles[SEMAPHORE_HANDLE].Handle, 1, IntPtr.Zero);
                        break;
                    }
                }
                else
                {
                    break;
                }
            }

            // Push to the old-stack.  For each free object, move object from new stack
            // to old stack.
            if (_waitHandles[SEMAPHORE_HANDLE].WaitOne(0, false) /* != WAIT_TIMEOUT */)
            {
                for (;;)
                {
                    DBPooledObject obj = (DBPooledObject)_stackNew.Pop();

                    if (null == obj)
                    {
                        break;
                    }

                    _stackOld.Push(obj);
                }
                SafeNativeMethods.ReleaseSemaphore(_waitHandles[SEMAPHORE_HANDLE].Handle, 1, IntPtr.Zero);
            }

            // Make sure we're at quota by posting a callback to the threadpool.
            ThreadPool.QueueUserWorkItem(new WaitCallback(PoolCreateRequest));
        }
Beispiel #12
0
            private bool _signaled;                    // Bool in case signal occurs before Cookie is set.

            public TransactionOutcomeEvents(DBObjectPool pool, DBPooledObject pooledObject, UCOMIConnectionPoint point)
            {
                _pool         = pool;
                _pooledObject = pooledObject;
                _point        = point;
            }
Beispiel #13
0
 public abstract void DestroyObject(DBObjectPool p, DBPooledObject con);
 public override void DestroyObject(DBObjectPool p, DBPooledObject con)
 {
     con.Close();
 }