Permalink
Browse files

Fixed some concurrency/race conditions during node failure (WIP?)

  • Loading branch information...
1 parent 96fbece commit f2b161a0909badf7981e055605d3a20f9a5db4dd @mnunberg committed Sep 24, 2012
Showing with 46 additions and 21 deletions.
  1. +46 −21 Enyim.Caching/Memcached/MemcachedNode.cs
@@ -139,6 +139,33 @@ public IPooledSocketResult Acquire()
return result;
}
}
+ /// <summary>
+ /// Tries to perform any actions on failure. Returns true if the policy
+ /// indicates that we should fail this node
+ /// </summary>
+ /// <returns></returns>
+ private bool TryToFail()
+ {
+
+ bool shouldFail;
+ if (failurePolicy != null)
+ {
+ shouldFail = failurePolicy.ShouldFail();
+ }
+ else
+ {
+ shouldFail = true;
+ }
+
+ if (!shouldFail)
+ {
+ return false;
+ }
+ if (Failed != null) {
+ Failed(this);
+ }
+ return true;
+ }
~MemcachedNode()
{
@@ -375,23 +402,15 @@ public IPooledSocketResult Acquire()
private void MarkAsDead()
{
if (log.IsDebugEnabled) log.DebugFormat("Mark as dead was requested for {0}", this.endPoint);
-
- var shouldFail = ownerNode.FailurePolicy.ShouldFail();
-
- if (log.IsDebugEnabled) log.Debug("FailurePolicy.ShouldFail(): " + shouldFail);
-
- if (shouldFail)
+ if (ownerNode == null || ownerNode.TryToFail() == false)
{
- if (log.IsWarnEnabled) log.WarnFormat("Marking node {0} as dead", this.endPoint);
-
- this.isAlive = false;
- this.markedAsDeadUtc = DateTime.UtcNow;
+ return;
+ }
- var f = this.ownerNode.Failed;
+ if (log.IsWarnEnabled) log.WarnFormat("Marking node {0} as dead", this.endPoint);
- if (f != null)
- f(this.ownerNode);
- }
+ this.isAlive = false;
+ this.markedAsDeadUtc = DateTime.UtcNow;
}
/// <summary>
@@ -413,9 +432,6 @@ private void ReleaseSocket(PooledSocket socket)
{
// 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
{
@@ -424,10 +440,6 @@ private void ReleaseSocket(PooledSocket socket)
// 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
@@ -436,6 +448,19 @@ private void ReleaseSocket(PooledSocket socket)
// are dead. so, kill the socket (this will eventually clear the pool as well)
socket.Destroy();
}
+
+ // In any event, we want to let any waiters know that we can create a new
+ // socket:
+ if (semaphore != null)
+ {
+ try
+ {
+ semaphore.Release();
+ }
+ catch (ObjectDisposedException)
+ {
+ }
+ }
}

0 comments on commit f2b161a

Please sign in to comment.