manifoldcf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kwri...@apache.org
Subject svn commit: r1625396 - in /manifoldcf/branches/dev_1x: ./ CHANGES.txt framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperConnection.java
Date Tue, 16 Sep 2014 21:14:53 GMT
Author: kwright
Date: Tue Sep 16 21:14:52 2014
New Revision: 1625396

URL: http://svn.apache.org/r1625396
Log:
Pull up fix for CONNECTORS-1031 from trunk.

Modified:
    manifoldcf/branches/dev_1x/   (props changed)
    manifoldcf/branches/dev_1x/CHANGES.txt
    manifoldcf/branches/dev_1x/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperConnection.java

Propchange: manifoldcf/branches/dev_1x/
------------------------------------------------------------------------------
  Merged /manifoldcf/trunk:r1625394

Modified: manifoldcf/branches/dev_1x/CHANGES.txt
URL: http://svn.apache.org/viewvc/manifoldcf/branches/dev_1x/CHANGES.txt?rev=1625396&r1=1625395&r2=1625396&view=diff
==============================================================================
--- manifoldcf/branches/dev_1x/CHANGES.txt (original)
+++ manifoldcf/branches/dev_1x/CHANGES.txt Tue Sep 16 21:14:52 2014
@@ -3,6 +3,10 @@ $Id$
 
 ======================= 1.8-dev =====================
 
+CONNECTORS-1031: Fix Zookeeper synchronization to be resilient
+against short tick time settings.
+(Karl Wright)
+
 CONNECTORS-1027: Improve some general and PostgreSQL queries
 for large crawling sets.
 (Paul Boichat, Karl Wright)

Modified: manifoldcf/branches/dev_1x/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperConnection.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/dev_1x/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperConnection.java?rev=1625396&r1=1625395&r2=1625396&view=diff
==============================================================================
--- manifoldcf/branches/dev_1x/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperConnection.java
(original)
+++ manifoldcf/branches/dev_1x/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperConnection.java
Tue Sep 16 21:14:52 2014
@@ -289,12 +289,65 @@ public class ZooKeeperConnection
       try
       {
         // Assert that we want a write lock
-        lockNode = createSequentialChild(lockPath,WRITE_PREFIX);
-        try
+        if (lockNode == null)
+          lockNode = createSequentialChild(lockPath,WRITE_PREFIX);
+        String lockSequenceNumber = lockNode.substring(lockPath.length() + 1 + WRITE_PREFIX.length());
+        // See if we got it
+        List<String> children = zookeeper.getChildren(lockPath,false);
+        for (String x : children)
+        {
+          String otherLock;
+          if (x.startsWith(WRITE_PREFIX))
+            otherLock = x.substring(WRITE_PREFIX.length());
+          else if (x.startsWith(NONEXWRITE_PREFIX))
+            otherLock = x.substring(NONEXWRITE_PREFIX.length());
+          else if (x.startsWith(READ_PREFIX))
+            otherLock = x.substring(READ_PREFIX.length());
+          else
+            continue;
+          if (otherLock.compareTo(lockSequenceNumber) < 0)
+          {
+            // We didn't get the lock.  Clean up and exit
+            releaseLock();
+            return false;
+          }
+        }
+        // We got it!
+        return true;
+      }
+      catch (KeeperException e)
+      {
+        handleEphemeralNodeKeeperException(e);
+      }
+    }
+  }
+  
+  /** Obtain a write lock, with wait.
+  *@param lockPath is the lock node path.
+  */
+  public void obtainWriteLock(String lockPath)
+    throws ManifoldCFException, InterruptedException
+  {
+    if (lockNode != null)
+      throw new IllegalStateException("Already have a lock in place: '"+lockNode+"'; can't
also write lock '"+lockPath+"'");
+
+    while (true)
+    {
+      try
+      {
+        // Assert that we want a write lock
+        if (lockNode == null)
+          lockNode = createSequentialChild(lockPath,WRITE_PREFIX);
+        long lockSequenceNumber = new Long(lockNode.substring(lockPath.length() + 1 + WRITE_PREFIX.length())).longValue();
+        //System.out.println("Trying to get write lock for '"+lockSequenceNumber+"'");
+        while (true)
         {
-          String lockSequenceNumber = lockNode.substring(lockPath.length() + 1 + WRITE_PREFIX.length());
+          //System.out.println("Assessing whether we got lock for '"+lockNode+"'...");
           // See if we got it
           List<String> children = zookeeper.getChildren(lockPath,false);
+          String previousLock = null;
+          boolean gotLock = true;
+          long highestPreviousLockIndex = -1L;
           for (String x : children)
           {
             String otherLock;
@@ -306,192 +359,122 @@ public class ZooKeeperConnection
               otherLock = x.substring(READ_PREFIX.length());
             else
               continue;
-            if (otherLock.compareTo(lockSequenceNumber) < 0)
+            long otherLockSequenceNumber = new Long(otherLock).longValue();
+            //System.out.println("Saw other child sequence number "+otherLockSequenceNumber);
+            if (otherLockSequenceNumber < lockSequenceNumber)
             {
-              // We didn't get the lock.  Clean up and exit
-              while (true)
+              // We didn't get the lock.  But keep going because we're looking for the node
right before the
+              // one we just asserted.
+              gotLock = false;
+              if (otherLockSequenceNumber > highestPreviousLockIndex)
               {
-                try
-                {
-                  zookeeper.delete(lockNode,-1);
-                  lockNode = null;
-                  break;
-                }
-                catch (KeeperException.NoNodeException e)
-                {
-                  lockNode = null;
-                  break;
-                }
-                catch (KeeperException e)
-                {
-                  handleKeeperException(e);
-                }
+                previousLock = x;
+                highestPreviousLockIndex = otherLockSequenceNumber;
               }
-              return false;
             }
           }
-        }
-        catch (Throwable e)
-        {
-          while (true)
+
+          if (gotLock)
           {
-            try
-            {
-              zookeeper.delete(lockNode,-1);
-              lockNode = null;
-              break;
-            }
-            catch (KeeperException.NoNodeException e2)
-            {
-              lockNode = null;
-              break;
-            }
-            catch (KeeperException e2)
-            {
-              handleKeeperException(e2);
-            }
+            // We got it!
+            //System.out.println("Got write lock for '"+lockSequenceNumber+"'");
+            return;
           }
-          if (e instanceof KeeperException)
-            throw (KeeperException)e;
-          else if (e instanceof InterruptedException)
-            throw (InterruptedException)e;
-          else if (e instanceof Error)
-            throw (Error)e;
-          else if (e instanceof RuntimeException)
-            throw (RuntimeException)e;
-          else
-            throw new RuntimeException("Unknown exception type '"+e.getClass().getName()+"':
"+e.getMessage(),e);
+
+          // There SHOULD be a previous node immediately prior to the one we asserted.  If
we didn't find one, go back around;
+          // the previous lock was probably created and destroyed before we managed to get
the children.
+          if (previousLock != null)
+          {
+            //System.out.println(" Waiting on '"+previousLock+"' for write lock '"+lockSequenceNumber+"'");
+            // Create an exists() watch on the previous node, and wait until we are awakened
by that watch firing.
+            ExistsWatcher w = new ExistsWatcher();
+            Stat s = zookeeper.exists(lockPath+"/"+previousLock, w);
+            if (s != null)
+              w.waitForEvent();
+          }
+          //else
+          //  System.out.println(" Retrying for write lock '"+lockSequenceNumber+"'");
         }
-        // We got it!
-        return true;
       }
       catch (KeeperException e)
       {
-        handleKeeperException(e);
+        handleEphemeralNodeKeeperException(e);
       }
     }
   }
-  
-  /** Obtain a write lock, with wait.
+
+  /** Obtain a non-ex-write lock, with no wait.
   *@param lockPath is the lock node path.
+  *@return true if the lock was obtained, false otherwise.
   */
-  public void obtainWriteLock(String lockPath)
+  public boolean obtainNonExWriteLockNoWait(String lockPath)
     throws ManifoldCFException, InterruptedException
   {
     if (lockNode != null)
-      throw new IllegalStateException("Already have a lock in place: '"+lockNode+"'; can't
also write lock '"+lockPath+"'");
+      throw new IllegalStateException("Already have a lock in place: '"+lockNode+"'; can't
also non-ex write lock '"+lockPath+"'");
 
     while (true)
     {
       try
       {
-        // Assert that we want a write lock
-        lockNode = createSequentialChild(lockPath,WRITE_PREFIX);
-        try
+        // Assert that we want a read lock
+        if (lockNode == null)
+          lockNode = createSequentialChild(lockPath,NONEXWRITE_PREFIX);
+        String lockSequenceNumber = lockNode.substring(lockPath.length() + 1 + NONEXWRITE_PREFIX.length());
+        // See if we got it
+        List<String> children = null;
+        while (true)
         {
-          long lockSequenceNumber = new Long(lockNode.substring(lockPath.length() + 1 + WRITE_PREFIX.length())).longValue();
-          //System.out.println("Trying to get write lock for '"+lockSequenceNumber+"'");
-          while (true)
+          try
           {
-            //System.out.println("Assessing whether we got lock for '"+lockNode+"'...");
-            // See if we got it
-            List<String> children = zookeeper.getChildren(lockPath,false);
-            String previousLock = null;
-            boolean gotLock = true;
-            long highestPreviousLockIndex = -1L;
-            for (String x : children)
-            {
-              String otherLock;
-              if (x.startsWith(WRITE_PREFIX))
-                otherLock = x.substring(WRITE_PREFIX.length());
-              else if (x.startsWith(NONEXWRITE_PREFIX))
-                otherLock = x.substring(NONEXWRITE_PREFIX.length());
-              else if (x.startsWith(READ_PREFIX))
-                otherLock = x.substring(READ_PREFIX.length());
-              else
-                continue;
-              long otherLockSequenceNumber = new Long(otherLock).longValue();
-              //System.out.println("Saw other child sequence number "+otherLockSequenceNumber);
-              if (otherLockSequenceNumber < lockSequenceNumber)
-              {
-                // We didn't get the lock.  But keep going because we're looking for the
node right before the
-                // one we just asserted.
-                gotLock = false;
-                if (otherLockSequenceNumber > highestPreviousLockIndex)
-                {
-                  previousLock = x;
-                  highestPreviousLockIndex = otherLockSequenceNumber;
-                }
-              }
-            }
-
-            if (gotLock)
-            {
-              // We got it!
-              //System.out.println("Got write lock for '"+lockSequenceNumber+"'");
-              return;
-            }
-
-            // There SHOULD be a previous node immediately prior to the one we asserted.
 If we didn't find one, go back around;
-            // the previous lock was probably created and destroyed before we managed to
get the children.
-            if (previousLock != null)
-            {
-              //System.out.println(" Waiting on '"+previousLock+"' for write lock '"+lockSequenceNumber+"'");
-              // Create an exists() watch on the previous node, and wait until we are awakened
by that watch firing.
-              ExistsWatcher w = new ExistsWatcher();
-              Stat s = zookeeper.exists(lockPath+"/"+previousLock, w);
-              if (s != null)
-                w.waitForEvent();
-            }
-            //else
-            //  System.out.println(" Retrying for write lock '"+lockSequenceNumber+"'");
+            children = zookeeper.getChildren(lockPath,false);
+            break;
+          }
+          catch (KeeperException.NoNodeException e)
+          {
+            // New session; back around again.
+            break;
+          }
+          catch (KeeperException e)
+          {
+            handleKeeperException(e);
           }
         }
-        catch (Throwable e)
+        if (children == null)
         {
-          //System.out.println("Unexpected keeper exception: "+e.getMessage());
-          while (true)
+          // Reassert ephemeral node b/c we had a session restart
+          continue;
+        }
+        for (String x : children)
+        {
+          String otherLock;
+          if (x.startsWith(WRITE_PREFIX))
+            otherLock = x.substring(WRITE_PREFIX.length());
+          else if (x.startsWith(READ_PREFIX))
+            otherLock = x.substring(READ_PREFIX.length());
+          else
+            continue;
+          if (otherLock.compareTo(lockSequenceNumber) < 0)
           {
-            try
-            {
-              zookeeper.delete(lockNode,-1);
-              lockNode = null;
-              break;
-            }
-            catch (KeeperException.NoNodeException e2)
-            {
-              lockNode = null;
-              break;
-            }
-            catch (KeeperException e2)
-            {
-              handleKeeperException(e2);
-            }
+            // We didn't get the lock.  Clean up and exit
+            releaseLock();
+            return false;
           }
-          if (e instanceof KeeperException)
-            throw (KeeperException)e;
-          else if (e instanceof InterruptedException)
-            throw (InterruptedException)e;
-          else if (e instanceof Error)
-            throw (Error)e;
-          else if (e instanceof RuntimeException)
-            throw (RuntimeException)e;
-          else
-            throw new RuntimeException("Unknown exception type '"+e.getClass().getName()+"':
"+e.getMessage(),e);
         }
+        // We got it!
+        return true;
       }
       catch (KeeperException e)
       {
-        handleKeeperException(e);
+        handleEphemeralNodeKeeperException(e);
       }
     }
   }
 
-  /** Obtain a non-ex-write lock, with no wait.
+  /** Obtain a non-ex-write lock, with wait.
   *@param lockPath is the lock node path.
-  *@return true if the lock was obtained, false otherwise.
   */
-  public boolean obtainNonExWriteLockNoWait(String lockPath)
+  public void obtainNonExWriteLock(String lockPath)
     throws ManifoldCFException, InterruptedException
   {
     if (lockNode != null)
@@ -502,10 +485,11 @@ public class ZooKeeperConnection
       try
       {
         // Assert that we want a read lock
-        lockNode = createSequentialChild(lockPath,NONEXWRITE_PREFIX);
-        try
+        if (lockNode == null)
+          lockNode = createSequentialChild(lockPath,NONEXWRITE_PREFIX);
+        long lockSequenceNumber = new Long(lockNode.substring(lockPath.length() + 1 + NONEXWRITE_PREFIX.length())).longValue();
+        while (true)
         {
-          String lockSequenceNumber = lockNode.substring(lockPath.length() + 1 + NONEXWRITE_PREFIX.length());
           // See if we got it
           List<String> children = null;
           while (true)
@@ -517,7 +501,6 @@ public class ZooKeeperConnection
             }
             catch (KeeperException.NoNodeException e)
             {
-              // New session; back around again.
               break;
             }
             catch (KeeperException e)
@@ -525,11 +508,13 @@ public class ZooKeeperConnection
               handleKeeperException(e);
             }
           }
+
           if (children == null)
-          {
-            // Reassert ephemeral node b/c we had a session restart
-            continue;
-          }
+            break;
+
+          String previousLock = null;
+          boolean gotLock = true;
+          long highestPreviousLockIndex = -1L;
           for (String x : children)
           {
             String otherLock;
@@ -539,205 +524,112 @@ public class ZooKeeperConnection
               otherLock = x.substring(READ_PREFIX.length());
             else
               continue;
-            if (otherLock.compareTo(lockSequenceNumber) < 0)
-            {
-              // We didn't get the lock.  Clean up and exit
-              while (true)
+            long otherLockSequenceNumber = new Long(otherLock).longValue();
+            //System.out.println("Saw other child sequence number "+otherLockSequenceNumber);
+            if (otherLockSequenceNumber < lockSequenceNumber)
+            {
+              // We didn't get the lock.  But keep going because we're looking for the node
right before the
+              // one we just asserted.
+              gotLock = false;
+              if (otherLockSequenceNumber > highestPreviousLockIndex)
               {
-                try
-                {
-                  zookeeper.delete(lockNode,-1);
-                  lockNode = null;
-                  break;
-                }
-                catch (KeeperException.NoNodeException e)
-                {
-                  lockNode = null;
-                  break;
-                }
-                catch (KeeperException e)
-                {
-                  handleKeeperException(e);
-                }
+                previousLock = x;
+                highestPreviousLockIndex = otherLockSequenceNumber;
               }
-              return false;
             }
           }
-        }
-        catch (Throwable e)
-        {
-          while (true)
+            
+          if (gotLock)
+            // We got it!
+            return;
+
+          // There SHOULD be a previous node immediately prior to the one we asserted.  If
we didn't find one, go back around;
+          // the previous lock was probably created and destroyed before we managed to get
the children.
+          if (previousLock != null)
           {
-            try
-            {
-              zookeeper.delete(lockNode,-1);
-              lockNode = null;
-              break;
-            }
-            catch (KeeperException.NoNodeException e2)
-            {
-              lockNode = null;
-              break;
-            }
-            catch (KeeperException e2)
-            {
-              handleKeeperException(e2);
-            }
+            // Create an exists() watch on the previous node, and wait until we are awakened
by that watch firing.
+            ExistsWatcher w = new ExistsWatcher();
+            Stat s = zookeeper.exists(lockPath+"/"+previousLock, w);
+            if (s != null)
+              w.waitForEvent();
           }
-          if (e instanceof KeeperException)
-            throw (KeeperException)e;
-          else if (e instanceof InterruptedException)
-            throw (InterruptedException)e;
-          else if (e instanceof Error)
-            throw (Error)e;
-          else if (e instanceof RuntimeException)
-            throw (RuntimeException)e;
-          else if (e instanceof ManifoldCFException)
-            throw (ManifoldCFException)e;
-          else
-            throw new RuntimeException("Unknown exception type '"+e.getClass().getName()+"':
"+e.getMessage(),e);
         }
-        // We got it!
-        return true;
       }
       catch (KeeperException e)
       {
-        handleKeeperException(e);
+        handleEphemeralNodeKeeperException(e);
       }
     }
   }
 
-  /** Obtain a non-ex-write lock, with wait.
+  /** Obtain a read lock, with no wait.
   *@param lockPath is the lock node path.
+  *@return true if the lock was obtained, false otherwise.
   */
-  public void obtainNonExWriteLock(String lockPath)
+  public boolean obtainReadLockNoWait(String lockPath)
     throws ManifoldCFException, InterruptedException
   {
     if (lockNode != null)
-      throw new IllegalStateException("Already have a lock in place: '"+lockNode+"'; can't
also non-ex write lock '"+lockPath+"'");
+      throw new IllegalStateException("Already have a lock in place: '"+lockNode+"'; can't
also read lock '"+lockPath+"'");
 
     while (true)
     {
       try
       {
         // Assert that we want a read lock
-        lockNode = createSequentialChild(lockPath,NONEXWRITE_PREFIX);
-        try
+        if (lockNode == null)
+          lockNode = createSequentialChild(lockPath,READ_PREFIX);
+        String lockSequenceNumber = lockNode.substring(lockPath.length() + 1 + READ_PREFIX.length());
+        // See if we got it
+        List<String> children = null;
+        while (true)
         {
-          long lockSequenceNumber = new Long(lockNode.substring(lockPath.length() + 1 + NONEXWRITE_PREFIX.length())).longValue();
-          while (true)
+          try
           {
-            // See if we got it
-            List<String> children = null;
-            while (true)
-            {
-              try
-              {
-                children = zookeeper.getChildren(lockPath,false);
-                break;
-              }
-              catch (KeeperException.NoNodeException e)
-              {
-                break;
-              }
-              catch (KeeperException e)
-              {
-                handleKeeperException(e);
-              }
-            }
-
-            if (children == null)
-              break;
-
-            String previousLock = null;
-            boolean gotLock = true;
-            long highestPreviousLockIndex = -1L;
-            for (String x : children)
-            {
-              String otherLock;
-              if (x.startsWith(WRITE_PREFIX))
-                otherLock = x.substring(WRITE_PREFIX.length());
-              else if (x.startsWith(READ_PREFIX))
-                otherLock = x.substring(READ_PREFIX.length());
-              else
-                continue;
-              long otherLockSequenceNumber = new Long(otherLock).longValue();
-              //System.out.println("Saw other child sequence number "+otherLockSequenceNumber);
-              if (otherLockSequenceNumber < lockSequenceNumber)
-              {
-                // We didn't get the lock.  But keep going because we're looking for the
node right before the
-                // one we just asserted.
-                gotLock = false;
-                if (otherLockSequenceNumber > highestPreviousLockIndex)
-                {
-                  previousLock = x;
-                  highestPreviousLockIndex = otherLockSequenceNumber;
-                }
-              }
-            }
-            
-            if (gotLock)
-              // We got it!
-              return;
-
-            // There SHOULD be a previous node immediately prior to the one we asserted.
 If we didn't find one, go back around;
-            // the previous lock was probably created and destroyed before we managed to
get the children.
-            if (previousLock != null)
-            {
-              // Create an exists() watch on the previous node, and wait until we are awakened
by that watch firing.
-              ExistsWatcher w = new ExistsWatcher();
-              Stat s = zookeeper.exists(lockPath+"/"+previousLock, w);
-              if (s != null)
-                w.waitForEvent();
-            }
+            children = zookeeper.getChildren(lockPath,false);
+            break;
+          }
+          catch (KeeperException.NoNodeException e)
+          {
+            break;
+          }
+          catch (KeeperException e)
+          {
+            handleKeeperException(e);
           }
         }
-        catch (Throwable e)
+        if (children == null)
+          continue;
+        for (String x : children)
         {
-          while (true)
+          String otherLock;
+          if (x.startsWith(WRITE_PREFIX))
+            otherLock = x.substring(WRITE_PREFIX.length());
+          else if (x.startsWith(NONEXWRITE_PREFIX))
+            otherLock = x.substring(NONEXWRITE_PREFIX.length());
+          else
+            continue;
+          if (otherLock.compareTo(lockSequenceNumber) < 0)
           {
-            try
-            {
-              zookeeper.delete(lockNode,-1);
-              lockNode = null;
-              break;
-            }
-            catch (KeeperException.NoNodeException e2)
-            {
-              lockNode = null;
-              break;
-            }
-            catch (KeeperException e2)
-            {
-              handleKeeperException(e2);
-            }
+            // We didn't get the lock.  Clean up and exit
+            releaseLock();
+            return false;
           }
-          if (e instanceof KeeperException)
-            throw (KeeperException)e;
-          else if (e instanceof InterruptedException)
-            throw (InterruptedException)e;
-          else if (e instanceof Error)
-            throw (Error)e;
-          else if (e instanceof RuntimeException)
-            throw (RuntimeException)e;
-          else if (e instanceof ManifoldCFException)
-            throw (ManifoldCFException)e;
-          else
-            throw new RuntimeException("Unknown exception type '"+e.getClass().getName()+"':
"+e.getMessage(),e);
         }
+        // We got it!
+        return true;
       }
       catch (KeeperException e)
       {
-        handleKeeperException(e);
+        handleEphemeralNodeKeeperException(e);
       }
     }
   }
-
-  /** Obtain a read lock, with no wait.
+  
+  /** Obtain a read lock, with wait.
   *@param lockPath is the lock node path.
-  *@return true if the lock was obtained, false otherwise.
   */
-  public boolean obtainReadLockNoWait(String lockPath)
+  public void obtainReadLock(String lockPath)
     throws ManifoldCFException, InterruptedException
   {
     if (lockNode != null)
@@ -748,10 +640,12 @@ public class ZooKeeperConnection
       try
       {
         // Assert that we want a read lock
-        lockNode = createSequentialChild(lockPath,READ_PREFIX);
-        try
+        if (lockNode == null)
+          lockNode = createSequentialChild(lockPath,READ_PREFIX);
+        long lockSequenceNumber = new Long(lockNode.substring(lockPath.length() + 1 + READ_PREFIX.length())).longValue();
+        //System.out.println("Trying to get read lock for '"+lockSequenceNumber+"'");
+        while (true)
         {
-          String lockSequenceNumber = lockNode.substring(lockPath.length() + 1 + READ_PREFIX.length());
           // See if we got it
           List<String> children = null;
           while (true)
@@ -770,8 +664,14 @@ public class ZooKeeperConnection
               handleKeeperException(e);
             }
           }
+
+          // Handle new session
           if (children == null)
-            continue;
+            break;
+            
+          String previousLock = null;
+          boolean gotLock = true;
+          long highestPreviousLockIndex = -1L;
           for (String x : children)
           {
             String otherLock;
@@ -781,205 +681,47 @@ public class ZooKeeperConnection
               otherLock = x.substring(NONEXWRITE_PREFIX.length());
             else
               continue;
-            if (otherLock.compareTo(lockSequenceNumber) < 0)
-            {
-              // We didn't get the lock.  Clean up and exit
-              while (true)
+            long otherLockSequenceNumber = new Long(otherLock).longValue();
+            //System.out.println("Saw other child sequence number "+otherLockSequenceNumber);
+            if (otherLockSequenceNumber < lockSequenceNumber)
+            {
+              // We didn't get the lock.  But keep going because we're looking for the node
right before the
+              // one we just asserted.
+              gotLock = false;
+              if (otherLockSequenceNumber > highestPreviousLockIndex)
               {
-                try
-                {
-                  zookeeper.delete(lockNode,-1);
-                  lockNode = null;
-                  break;
-                }
-                catch (KeeperException.NoNodeException e)
-                {
-                  lockNode = null;
-                  break;
-                }
-                catch (KeeperException e)
-                {
-                  handleKeeperException(e);
-                }
+                previousLock = x;
+                highestPreviousLockIndex = otherLockSequenceNumber;
               }
-              return false;
             }
           }
-        }
-        catch (Throwable e)
-        {
-          while (true)
+            
+          if (gotLock)
           {
-            try
-            {
-              zookeeper.delete(lockNode,-1);
-              lockNode = null;
-              break;
-            }
-            catch (KeeperException.NoNodeException e2)
-            {
-              lockNode = null;
-              break;
-            }
-            catch (KeeperException e2)
-            {
-              handleKeeperException(e2);
-            }
+            // We got it!
+            //System.out.println("Got read lock for '"+lockSequenceNumber+"'");
+            return;
           }
-          if (e instanceof KeeperException)
-            throw (KeeperException)e;
-          else if (e instanceof InterruptedException)
-            throw (InterruptedException)e;
-          else if (e instanceof Error)
-            throw (Error)e;
-          else if (e instanceof RuntimeException)
-            throw (RuntimeException)e;
-          else if (e instanceof ManifoldCFException)
-            throw (ManifoldCFException)e;
-          else
-            throw new RuntimeException("Unknown exception type '"+e.getClass().getName()+"':
"+e.getMessage(),e);
-        }
-        // We got it!
-        return true;
-      }
-      catch (KeeperException e)
-      {
-        handleKeeperException(e);
-      }
-    }
-  }
-  
-  /** Obtain a read lock, with wait.
-  *@param lockPath is the lock node path.
-  */
-  public void obtainReadLock(String lockPath)
-    throws ManifoldCFException, InterruptedException
-  {
-    if (lockNode != null)
-      throw new IllegalStateException("Already have a lock in place: '"+lockNode+"'; can't
also read lock '"+lockPath+"'");
-
-    while (true)
-    {
-      try
-      {
-        // Assert that we want a read lock
-        lockNode = createSequentialChild(lockPath,READ_PREFIX);
-        try
-        {
-          long lockSequenceNumber = new Long(lockNode.substring(lockPath.length() + 1 + READ_PREFIX.length())).longValue();
-          //System.out.println("Trying to get read lock for '"+lockSequenceNumber+"'");
-          while (true)
-          {
-            // See if we got it
-            List<String> children = null;
-            while (true)
-            {
-              try
-              {
-                children = zookeeper.getChildren(lockPath,false);
-                break;
-              }
-              catch (KeeperException.NoNodeException e)
-              {
-                break;
-              }
-              catch (KeeperException e)
-              {
-                handleKeeperException(e);
-              }
-            }
 
-            // Handle new session
-            if (children == null)
-              break;
-            
-            String previousLock = null;
-            boolean gotLock = true;
-            long highestPreviousLockIndex = -1L;
-            for (String x : children)
-            {
-              String otherLock;
-              if (x.startsWith(WRITE_PREFIX))
-                otherLock = x.substring(WRITE_PREFIX.length());
-              else if (x.startsWith(NONEXWRITE_PREFIX))
-                otherLock = x.substring(NONEXWRITE_PREFIX.length());
-              else
-                continue;
-              long otherLockSequenceNumber = new Long(otherLock).longValue();
-              //System.out.println("Saw other child sequence number "+otherLockSequenceNumber);
-              if (otherLockSequenceNumber < lockSequenceNumber)
-              {
-                // We didn't get the lock.  But keep going because we're looking for the
node right before the
-                // one we just asserted.
-                gotLock = false;
-                if (otherLockSequenceNumber > highestPreviousLockIndex)
-                {
-                  previousLock = x;
-                  highestPreviousLockIndex = otherLockSequenceNumber;
-                }
-              }
-            }
-            
-            if (gotLock)
-            {
-              // We got it!
-              //System.out.println("Got read lock for '"+lockSequenceNumber+"'");
-              return;
-            }
-
-            // There SHOULD be a previous node immediately prior to the one we asserted.
 If we didn't find one, go back around;
-            // the previous lock was probably created and destroyed before we managed to
get the children.
-            if (previousLock != null)
-            {
-              //System.out.println(" Waiting on '"+previousLock+"' for read lock '"+lockSequenceNumber+"'");
-              // Create an exists() watch on the previous node, and wait until we are awakened
by that watch firing.
-              ExistsWatcher w = new ExistsWatcher();
-              Stat s = zookeeper.exists(lockPath+"/"+previousLock, w);
-              if (s != null)
-                w.waitForEvent();
-            }
-            //else
-            //  System.out.println(" Retrying for read lock '"+lockSequenceNumber+"'");
-
-          }
-        }
-        catch (Throwable e)
-        {
-          while (true)
+          // There SHOULD be a previous node immediately prior to the one we asserted.  If
we didn't find one, go back around;
+          // the previous lock was probably created and destroyed before we managed to get
the children.
+          if (previousLock != null)
           {
-            try
-            {
-              zookeeper.delete(lockNode,-1);
-              lockNode = null;
-              break;
-            }
-            catch (KeeperException.NoNodeException e2)
-            {
-              lockNode = null;
-              break;
-            }
-            catch (KeeperException e2)
-            {
-              handleKeeperException(e2);
-            }
+            //System.out.println(" Waiting on '"+previousLock+"' for read lock '"+lockSequenceNumber+"'");
+            // Create an exists() watch on the previous node, and wait until we are awakened
by that watch firing.
+            ExistsWatcher w = new ExistsWatcher();
+            Stat s = zookeeper.exists(lockPath+"/"+previousLock, w);
+            if (s != null)
+              w.waitForEvent();
           }
-          if (e instanceof KeeperException)
-            throw (KeeperException)e;
-          else if (e instanceof InterruptedException)
-            throw (InterruptedException)e;
-          else if (e instanceof Error)
-            throw (Error)e;
-          else if (e instanceof RuntimeException)
-            throw (RuntimeException)e;
-          else if (e instanceof ManifoldCFException)
-            throw (ManifoldCFException)e;
-          else
-            throw new RuntimeException("Unknown exception type '"+e.getClass().getName()+"':
"+e.getMessage(),e);
+          //else
+          //  System.out.println(" Retrying for read lock '"+lockSequenceNumber+"'");
+
         }
       }
       catch (KeeperException e)
       {
-        handleKeeperException(e);
+        handleEphemeralNodeKeeperException(e);
       }
     }
   }
@@ -995,20 +737,17 @@ public class ZooKeeperConnection
     
     while (true)
     {
+      if (lockNode == null)
+        break;
       try
       {
         zookeeper.delete(lockNode,-1);
         lockNode = null;
         break;
       }
-      catch (KeeperException.NoNodeException e)
-      {
-        lockNode = null;
-        break;
-      }
       catch (KeeperException e)
       {
-        handleKeeperException(e);
+        handleEphemeralNodeKeeperException(e);
       }
     }
   }
@@ -1160,6 +899,27 @@ public class ZooKeeperConnection
     zookeeperWatcher = null;
   }
   
+  /** Handle keeper exceptions that may involve ephemeral node creation.
+  */
+  protected void handleEphemeralNodeKeeperException(KeeperException e)
+    throws ManifoldCFException, InterruptedException
+  {
+    if (e instanceof KeeperException.ConnectionLossException || e instanceof KeeperException.SessionExpiredException)
+    {
+      // Close the handle, open a new one
+      zookeeper.close();
+      lockNode = null;
+      createSession();
+    }
+    else
+    {
+      // If nothing we know how to deal with, throw.
+      throw new ManifoldCFException(e.getMessage(),e);
+    }
+  }
+
+  /** Handle keeper exceptions that don't involve ephemeral node creation.
+  */
   protected void handleKeeperException(KeeperException e)
     throws ManifoldCFException, InterruptedException
   {
@@ -1172,6 +932,7 @@ public class ZooKeeperConnection
     {
       // Close the handle, open a new one
       zookeeper.close();
+      lockNode = null;
       createSession();
     }
     else



Mime
View raw message