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") )); } }
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); }
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); }
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); }
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; } } }
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); }
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); }
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); } }
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); }
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)); }
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; }
public abstract void DestroyObject(DBObjectPool p, DBPooledObject con);
public override void DestroyObject(DBObjectPool p, DBPooledObject con) { con.Close(); }