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