/// <summary> /// Releases an item back into the pool /// </summary> /// <param name="socket"></param> private void ReleaseSocket(PooledSocket socket) { if (log.IsDebugEnabled) { log.Debug("Releasing socket " + socket.InstanceId); log.Debug("Are we alive? " + this.isAlive); } if (this.isAlive) { // is it still working (i.e. the server is still connected) if (socket.IsAlive) { // mark the item as free this.freeItems.Push(socket); // signal the event so if someone is waiting for it can reuse this item this.semaphore.Release(); } else { // kill this item socket.Destroy(); // mark ourselves as not working for a while this.MarkAsDead(); // make sure to signal the Acquire so it can create a new conenction // if the failure policy keeps the pool alive this.semaphore.Release(); } } else { // one of our previous sockets has died, so probably all of them // are dead. so, kill the socket (this will eventually clear the pool as well) socket.Destroy(); } }
/// <summary> /// Acquires a new item from the pool /// </summary> /// <returns>An <see cref="T:PooledSocket"/> instance which is connected to the memcached server, or <value>null</value> if the pool is dead.</returns> public IPooledSocketResult Acquire() { var result = new PooledSocketResult(); var message = string.Empty; bool hasDebug = log.IsDebugEnabled; if (hasDebug) { log.Debug("Acquiring stream from pool. " + this.endPoint); } if (!this.isAlive || this.isDisposed) { message = "Pool is dead or disposed, returning null. " + this.endPoint; result.Fail(message); if (hasDebug) { log.Debug(message); } return(result); } PooledSocket retval = null; if (!this.semaphore.WaitOne(this.queueTimeout)) { message = "Pool is full, timeouting. " + this.endPoint; if (hasDebug) { log.Debug(message); } result.Fail(message, new TimeoutException()); // everyone is so busy return(result); } // maybe we died while waiting if (!this.isAlive) { message = "Pool is dead, returning null. " + this.endPoint; if (hasDebug) { log.Debug(message); } result.Fail(message); return(result); } // do we have free items? if (this.freeItems.TryPop(out retval)) { #region [ get it from the pool ] try { retval.Reset(); message = "Socket was reset. " + retval.InstanceId; if (hasDebug) { log.Debug(message); } result.Pass(message); result.Value = retval; return(result); } catch (Exception e) { message = "Failed to reset an acquired socket."; log.Error(message, e); this.MarkAsDead(); result.Fail(message, e); return(result); } #endregion } // free item pool is empty message = "Could not get a socket from the pool, Creating a new item. " + this.endPoint; if (hasDebug) { log.Debug(message); } try { // okay, create the new item retval = this.CreateSocket(); result.Value = retval; result.Pass(); } catch (Exception e) { message = "Failed to create socket. " + this.endPoint; log.Error(message, e); // eventhough this item failed the failure policy may keep the pool alive // so we need to make sure to release the semaphore, so new connections can be // acquired or created (otherwise dead conenctions would "fill up" the pool // while the FP pretends that the pool is healthy) semaphore.Release(); this.MarkAsDead(); result.Fail(message); return(result); } if (hasDebug) { log.Debug("Done."); } return(result); }