public virtual void Release(E entry, bool reusable) { this.Lock.Lock(); try { if (this.leased.Remove(entry)) { RouteSpecificPool <T, C, E> pool = GetPool(entry.GetRoute()); pool.Free(entry, reusable); if (reusable && !this.isShutDown) { this.available.AddFirst(entry); OnRelease(entry); } else { entry.Close(); } PoolEntryFuture <E> future = pool.NextPending(); if (future != null) { this.pending.Remove(future); } else { future = this.pending.Poll(); } if (future != null) { future.Wakeup(); } } } finally { this.Lock.Unlock(); } }
/// <exception cref="System.IO.IOException"></exception> /// <exception cref="System.Exception"></exception> /// <exception cref="Sharpen.TimeoutException"></exception> private E GetPoolEntryBlocking(T route, object state, long timeout, TimeUnit tunit , PoolEntryFuture <E> future) { DateTime deadline = null; if (timeout > 0) { deadline = Sharpen.Extensions.CreateDate(Runtime.CurrentTimeMillis() + tunit.ToMillis (timeout)); } this.Lock.Lock(); try { RouteSpecificPool <T, C, E> pool = GetPool(route); E entry = null; while (entry == null) { Asserts.Check(!this.isShutDown, "Connection pool shut down"); for (; ;) { entry = pool.GetFree(state); if (entry == null) { break; } if (entry.IsClosed() || entry.IsExpired(Runtime.CurrentTimeMillis())) { entry.Close(); this.available.Remove(entry); pool.Free(entry, false); } else { break; } } if (entry != null) { this.available.Remove(entry); this.leased.AddItem(entry); return(entry); } // New connection is needed int maxPerRoute = GetMax(route); // Shrink the pool prior to allocating a new connection int excess = Math.Max(0, pool.GetAllocatedCount() + 1 - maxPerRoute); if (excess > 0) { for (int i = 0; i < excess; i++) { E lastUsed = pool.GetLastUsed(); if (lastUsed == null) { break; } lastUsed.Close(); this.available.Remove(lastUsed); pool.Remove(lastUsed); } } if (pool.GetAllocatedCount() < maxPerRoute) { int totalUsed = this.leased.Count; int freeCapacity = Math.Max(this.maxTotal - totalUsed, 0); if (freeCapacity > 0) { int totalAvailable = this.available.Count; if (totalAvailable > freeCapacity - 1) { if (!this.available.IsEmpty()) { E lastUsed = this.available.RemoveLast(); lastUsed.Close(); RouteSpecificPool <T, C, E> otherpool = GetPool(lastUsed.GetRoute()); otherpool.Remove(lastUsed); } } C conn = this.connFactory.Create(route); entry = pool.Add(conn); this.leased.AddItem(entry); return(entry); } } bool success = false; try { pool.Queue(future); this.pending.AddItem(future); success = future.Await(deadline); } finally { // In case of 'success', we were woken up by the // connection pool and should now have a connection // waiting for us, or else we're shutting down. // Just continue in the loop, both cases are checked. pool.Unqueue(future); this.pending.Remove(future); } // check for spurious wakeup vs. timeout if (!success && (deadline != null) && (deadline.GetTime() <= Runtime.CurrentTimeMillis ())) { break; } } throw new TimeoutException("Timeout waiting for connection"); } finally { this.Lock.Unlock(); } }