Author: kwright
Date: Sun Nov 10 21:24:42 2013
New Revision: 1540553

URL: http://svn.apache.org/r1540553
Log:
Implement zookeeper related code, all except for zookeeper node acls.

Modified:
    
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/FileLockObject.java
    
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockObject.java
    
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperConnection.java
    
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperLockObject.java

Modified: 
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/FileLockObject.java
URL: 
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/FileLockObject.java?rev=1540553&r1=1540552&r2=1540553&view=diff
==============================================================================
--- 
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/FileLockObject.java
 (original)
+++ 
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/FileLockObject.java
 Sun Nov 10 21:24:42 2013
@@ -69,7 +69,7 @@ public class FileLockObject extends Lock
   }
 
   @Override
-  protected void obtainGlobalWriteLock()
+  protected void obtainGlobalWriteLockNoWait()
     throws ManifoldCFException, LockException, InterruptedException
   {
     if (isSync)
@@ -110,7 +110,7 @@ public class FileLockObject extends Lock
   }
 
   @Override
-  protected void obtainGlobalNonExWriteLock()
+  protected void obtainGlobalNonExWriteLockNoWait()
     throws ManifoldCFException, LockException, InterruptedException
   {
     // Attempt to obtain a global write lock
@@ -160,7 +160,7 @@ public class FileLockObject extends Lock
   }
 
   @Override
-  protected void obtainGlobalReadLock()
+  protected void obtainGlobalReadLockNoWait()
     throws ManifoldCFException, LockException, InterruptedException
   {
     // Attempt to obtain a global read lock

Modified: 
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockObject.java
URL: 
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockObject.java?rev=1540553&r1=1540552&r2=1540553&view=diff
==============================================================================
--- 
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockObject.java
 (original)
+++ 
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockObject.java
 Sun Nov 10 21:24:42 2013
@@ -108,11 +108,11 @@ public class LockObject
     if (obtainedRead > 0 || obtainedNonExWrite > 0)
       throw new LocalLockException(LOCKEDANOTHERTHREAD);
     // Attempt to obtain a global write lock
-    obtainGlobalWriteLock();
+    obtainGlobalWriteLockNoWait();
     obtainedWrite = true;
   }
 
-  protected void obtainGlobalWriteLock()
+  protected void obtainGlobalWriteLockNoWait()
     throws ManifoldCFException, LockException, InterruptedException
   {
   }
@@ -231,11 +231,11 @@ public class LockObject
       obtainedNonExWrite++;
       return;
     }
-    obtainGlobalNonExWriteLock();
+    obtainGlobalNonExWriteLockNoWait();
     obtainedNonExWrite++;
   }
 
-  protected void obtainGlobalNonExWriteLock()
+  protected void obtainGlobalNonExWriteLockNoWait()
     throws ManifoldCFException, LockException, InterruptedException
   {
   }
@@ -354,12 +354,12 @@ public class LockObject
       return;
     }
     // Got the read token locally!
-    obtainGlobalReadLock();
+    obtainGlobalReadLockNoWait();
 
     obtainedRead = 1;
   }
 
-  protected void obtainGlobalReadLock()
+  protected void obtainGlobalReadLockNoWait()
     throws ManifoldCFException, LockException, InterruptedException
   {
   }

Modified: 
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperConnection.java
URL: 
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperConnection.java?rev=1540553&r1=1540552&r2=1540553&view=diff
==============================================================================
--- 
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperConnection.java
 (original)
+++ 
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperConnection.java
 Sun Nov 10 21:24:42 2013
@@ -23,6 +23,8 @@ import org.apache.manifoldcf.core.system
 import org.apache.manifoldcf.core.system.ManifoldCF;
 
 import org.apache.zookeeper.*;
+import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.data.Stat;
 
 import java.util.*;
 import java.io.*;
@@ -35,11 +37,18 @@ import java.io.*;
 public class ZooKeeperConnection
 {
   public static final String _rcsid = "@(#)$Id$";
-       
-  // One zookeeper client per thread
+
+  private static final String READ_PREFIX = "read-";
+  private static final String NONEXWRITE_PREFIX = "nonexwrite-";
+  private static final String WRITE_PREFIX = "write-";
+
+  // Our zookeeper client
   protected ZooKeeper zookeeper = null;
   protected ZooKeeperWatcher zookeeperWatcher = null;
 
+  // Transient state
+  protected String lockNode = null;
+
   /** Constructor. */
   public ZooKeeperConnection(String connectString, int sessionTimeout)
     throws ManifoldCFException, InterruptedException
@@ -59,161 +68,282 @@ public class ZooKeeperConnection
     }
   }
 
-  public void obtainGlobalWriteLock(String lockPath)
-    throws ManifoldCFException, LockException, InterruptedException
+  /** Obtain a write lock, with no wait.
+  *@param lockPath is the lock node path.
+  *@return true if the lock was obtained, false otherwise.
+  */
+  public boolean obtainWriteLockNoWait(String lockPath)
+    throws ManifoldCFException, InterruptedException
   {
-    /*
-      1. Call create( ) to create a node with pathname "guid-/write-". This is 
the lock node
-         spoken of later in the protocol. Make sure to set both sequence and 
ephemeral flags.
-         If a recoverable error occurs calling create() the client should call 
getChildren() and
-         check for a node containing the guid used in the path name. This 
handles the case
-         (noted above) of the create() succeeding on the server but the server 
crashing before
-         returning the name of the new node.
-    */
-
-    /*
-      2. Call getChildren( ) on the lock node without setting the watch flag - 
this is important,
-         as it avoids the herd effect.
-    */
+    if (lockNode != null)
+      throw new IllegalStateException("Already have a lock in place: 
'"+lockNode+"'; can't also write lock '"+lockPath+"'");
 
-    /*
-      3. If there are no children with a lower sequence number than the node 
created in step
-         1, the client has the lock and the client exits the protocol.
-    */
-
-    /*
-      4. Call exists( ), with watch flag set, on the node with the pathname 
that has the next
-         lowest sequence number.
-    */
-
-    /* 5. If exists( ) returns false, goto step 2. Otherwise, wait for a 
notification for the
-         pathname from the previous step before going to step 2.
-    */
-
-    // MHL
+    try
+    {
+      // Assert that we want a read lock
+      lockNode = createSequentialChild(lockPath,WRITE_PREFIX);
+      String lockSequenceNumber = lockNode.substring(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
+          zookeeper.delete(lockNode,-1);
+          lockNode = null;
+          return false;
+        }
+      }
+      // We got it!
+      return true;
+    }
+    catch (KeeperException e)
+    {
+      throw new ManifoldCFException(e.getMessage(),e);
+    }
   }
   
-  public void clearGlobalWriteLock(String lockPath)
-    throws ManifoldCFException, LockException, InterruptedException
+  /** 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 boolean obtainNonExWriteLockNoWait(String lockPath)
+    throws ManifoldCFException, InterruptedException
   {
-    /*
-      Delete the node we created in step 1 above.
-    */
-    // MHL
-  }
+    if (lockNode != null)
+      throw new IllegalStateException("Already have a lock in place: 
'"+lockNode+"'; can't also non-ex write lock '"+lockPath+"'");
 
-  public void obtainGlobalNonExWriteLock(String lockPath)
-    throws ManifoldCFException, LockException, InterruptedException
-  {
-    // MHL
+    try
+    {
+      // Assert that we want a read lock
+      lockNode = createSequentialChild(lockPath,NONEXWRITE_PREFIX);
+      String lockSequenceNumber = 
lockNode.substring(NONEXWRITE_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(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
+          zookeeper.delete(lockNode,-1);
+          lockNode = null;
+          return false;
+        }
+      }
+      // We got it!
+      return true;
+    }
+    catch (KeeperException e)
+    {
+      throw new ManifoldCFException(e.getMessage(),e);
+    }
   }
 
-  public void clearGlobalNonExWriteLock(String lockPath)
-    throws ManifoldCFException, LockException, InterruptedException
-  {
-    // MHL
-  }
-  
-  public void obtainGlobalReadLock(String lockPath)
-    throws ManifoldCFException, LockException, InterruptedException
+  /** Obtain a read lock, with no wait.
+  *@param lockPath is the lock node path.
+  *@return true if the lock was obtained, false otherwise.
+  */
+  public boolean obtainReadLockNoWait(String lockPath)
+    throws ManifoldCFException, InterruptedException
   {
-    /*
-      1. Call create( ) to create a node with pathname "guid-/read-". This is 
the lock node use later in the
-         protocol. Make sure to set both the sequence and ephemeral flags.
-         If a recoverable error occurs calling create() the client should call 
getChildren() and
-         check for a node containing the guid used in the path name. This 
handles the case
-         (noted above) of the create() succeeding on the server but the server 
crashing before
-         returning the name of the new node.
-    */
-
-    /*
-      2. Call getChildren( ) on the lock node without setting the watch flag - 
this is important, as it
-         avoids the herd effect.
-    */
-
-    /*
-      3. If there are no children with a pathname starting with "write-" and 
having a lower
-         sequence number than the node created in step 1, the client has the 
lock and can exit the protocol.
-    */
-
-    /*
-      4. Otherwise, call exists( ), with watch flag, set on the node in lock 
directory with pathname
-         staring with "write-" having the next lowest sequence number.
-    */
-
-    /*
-      5. If exists( ) returns false, goto step 2.
-    */
-
-    /*
-      6. Otherwise, wait for a notification for the pathname from the previous 
step before going to step 2
-    */
-
-    // MHL
+    if (lockNode != null)
+      throw new IllegalStateException("Already have a lock in place: 
'"+lockNode+"'; can't also read lock '"+lockPath+"'");
 
+    try
+    {
+      // Assert that we want a read lock
+      lockNode = createSequentialChild(lockPath,READ_PREFIX);
+      String lockSequenceNumber = lockNode.substring(READ_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
+          continue;
+        if (otherLock.compareTo(lockSequenceNumber) < 0)
+        {
+          // We didn't get the lock.  Clean up and exit
+          zookeeper.delete(lockNode,-1);
+          lockNode = null;
+          return false;
+        }
+      }
+      // We got it!
+      return true;
+    }
+    catch (KeeperException e)
+    {
+      throw new ManifoldCFException(e.getMessage(),e);
+    }
   }
   
- public void clearGlobalReadLock(String lockPath)
-    throws ManifoldCFException, LockException, InterruptedException
+  /** Release the (saved) lock.
+  */
+  public void releaseLock()
+    throws ManifoldCFException, InterruptedException
   {
-    /*
-      Delete the node we created in step 1 above.
-    */
-    // MHL
+    if (lockNode == null)
+      throw new IllegalStateException("Can't release lock we don't hold");
+    try
+    {
+      zookeeper.delete(lockNode,-1);
+      lockNode = null;
+    }
+    catch (KeeperException e)
+    {
+      throw new ManifoldCFException(e.getMessage(),e);
+    }
   }
 
   public byte[] readData(String resourcePath)
     throws ManifoldCFException, InterruptedException
   {
-    // MHL
-    return null;
+    try
+    {
+      Stat s = zookeeper.exists(resourcePath,false);
+      if (s == null)
+        return null;
+      return zookeeper.getData(resourcePath,null,s);
+    }
+    catch (KeeperException e)
+    {
+      throw new ManifoldCFException(e.getMessage(),e);
+    }
   }
   
   public void writeData(String resourcePath, byte[] data)
     throws ManifoldCFException, InterruptedException
   {
-    // MHL
+    try
+    {
+      try
+      {
+        List<ACL> aclList = new ArrayList<ACL>();
+        // MHL
+        zookeeper.create(resourcePath, data, aclList, CreateMode.PERSISTENT);
+      }
+      catch (KeeperException e)
+      {
+        if (!(e instanceof KeeperException.NodeExistsException))
+          throw e;
+        zookeeper.setData(resourcePath, data, -1);
+      }
+    }
+    catch (KeeperException e)
+    {
+      throw new ManifoldCFException(e.getMessage(),e);
+    }
   }
 
   public void setGlobalFlag(String flagPath)
     throws ManifoldCFException, InterruptedException
   {
-    // MHL
+    try
+    {
+      List<ACL> acls = new ArrayList<ACL>();
+      // MHL
+      zookeeper.create(flagPath, new byte[0], acls, CreateMode.PERSISTENT);
+    }
+    catch (KeeperException e)
+    {
+      if (!(e instanceof KeeperException.NodeExistsException))
+        throw new ManifoldCFException(e.getMessage(),e);
+    }
   }
 
   public void clearGlobalFlag(String flagPath)
     throws ManifoldCFException, InterruptedException
   {
-    // MHL
+    try
+    {
+      zookeeper.delete(flagPath,-1);
+    }
+    catch (KeeperException e)
+    {
+      if (!(e instanceof KeeperException.NoNodeException))
+        return;
+      throw new ManifoldCFException(e.getMessage(),e);
+    }
   }
   
   public boolean checkGlobalFlag(String flagPath)
     throws ManifoldCFException, InterruptedException
   {
-    // MHL
-    return false;
+    try
+    {
+      Stat s = zookeeper.exists(flagPath,false);
+      return s != null;
+    }
+    catch (KeeperException e)
+    {
+      throw new ManifoldCFException(e.getMessage(),e);
+    }
   }
   
   /** Close this connection. */
   public void close()
     throws InterruptedException
   {
+    if (lockNode != null)
+      throw new IllegalStateException("Should not be closing handles that have 
open locks!  Locknode: '"+lockNode+"'");
     zookeeper.close();
     zookeeper = null;
     zookeeperWatcher = null;
   }
   
+  // Protected methods
+  
+  /** Create a node and a sequential child node.  Neither node has any data.
+  */
+  protected String createSequentialChild(String mainNode, String childPrefix)
+    throws KeeperException, InterruptedException
+  {
+    List<ACL> aclList = new ArrayList<ACL>();
+    // MHL for the right ACL.
+    try
+    {
+      zookeeper.create(mainNode, new byte[0], aclList, CreateMode.PERSISTENT);
+    }
+    catch (KeeperException e)
+    {
+      if (!(e instanceof KeeperException.NodeExistsException))
+        throw e;
+    }
+    
+    return zookeeper.create(mainNode + "/" + childPrefix, new byte[0], 
aclList, CreateMode.EPHEMERAL_SEQUENTIAL);
+  }
+
   /** Watcher class for zookeeper, so we get notified about zookeeper events. 
*/
   protected static class ZooKeeperWatcher implements Watcher
   {
     public ZooKeeperWatcher()
     {
-      // MHL
     }
     
     public void process(WatchedEvent event)
     {
-      // MHL
     }
 
   }

Modified: 
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperLockObject.java
URL: 
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperLockObject.java?rev=1540553&r1=1540552&r2=1540553&view=diff
==============================================================================
--- 
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperLockObject.java
 (original)
+++ 
manifoldcf/branches/CONNECTORS-13/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperLockObject.java
 Sun Nov 10 21:24:42 2013
@@ -30,11 +30,13 @@ public class ZooKeeperLockObject extends
 {
   public static final String _rcsid = "@(#)$Id$";
 
-  private final static String LOCK_PATH_PREFIX = 
"org.apache.manifoldcf.locks/";
+  private final static String LOCK_PATH_PREFIX = 
"org.apache.manifoldcf.locks-";
 
   private final ZooKeeperConnectionPool pool;
   private final String lockPath;
   
+  private ZooKeeperConnection currentConnection = null;
+
   public ZooKeeperLockObject(LockPool lockPool, Object lockKey, 
ZooKeeperConnectionPool pool)
   {
     super(lockPool,lockKey);
@@ -43,17 +45,26 @@ public class ZooKeeperLockObject extends
   }
 
   @Override
-  protected void obtainGlobalWriteLock()
+  protected void obtainGlobalWriteLockNoWait()
     throws ManifoldCFException, LockException, InterruptedException
   {
-    ZooKeeperConnection connection = pool.grab();
+    if (currentConnection != null)
+      throw new IllegalStateException("Already have a connection before write 
locking: "+lockPath);
+    boolean succeeded = false;
+    currentConnection = pool.grab();
     try
     {
-      connection.obtainGlobalWriteLock(lockPath);
+      succeeded = currentConnection.obtainWriteLockNoWait(lockPath);
+      if (!succeeded)
+        throw new LockException(LOCKEDANOTHERJVM);
     }
     finally
     {
-      pool.release(connection);
+      if (!succeeded)
+      {
+        pool.release(currentConnection);
+        currentConnection = null;
+      }
     }
   }
 
@@ -61,29 +72,32 @@ public class ZooKeeperLockObject extends
   protected void clearGlobalWriteLock()
     throws ManifoldCFException, LockException, InterruptedException
   {
-    ZooKeeperConnection connection = pool.grab();
-    try
-    {
-      connection.clearGlobalWriteLock(lockPath);
-    }
-    finally
-    {
-      pool.release(connection);
-    }
+    if (currentConnection == null)
+      throw new IllegalStateException("Cannot clear write lock we don't have: 
"+lockPath);
+    clearLock();
   }
-
+  
   @Override
-  protected void obtainGlobalNonExWriteLock()
+  protected void obtainGlobalNonExWriteLockNoWait()
     throws ManifoldCFException, LockException, InterruptedException
   {
-    ZooKeeperConnection connection = pool.grab();
+    if (currentConnection != null)
+      throw new IllegalStateException("Already have a connection before 
non-ex-write locking: "+lockPath);
+    boolean succeeded = false;
+    currentConnection = pool.grab();
     try
     {
-      connection.obtainGlobalNonExWriteLock(lockPath);
+      succeeded = currentConnection.obtainNonExWriteLockNoWait(lockPath);
+      if (!succeeded)
+        throw new LockException(LOCKEDANOTHERJVM);
     }
     finally
     {
-      pool.release(connection);
+      if (!succeeded)
+      {
+        pool.release(currentConnection);
+        currentConnection = null;
+      }
     }
   }
 
@@ -91,29 +105,32 @@ public class ZooKeeperLockObject extends
   protected void clearGlobalNonExWriteLock()
     throws ManifoldCFException, LockException, InterruptedException
   {
-    ZooKeeperConnection connection = pool.grab();
-    try
-    {
-      connection.clearGlobalNonExWriteLock(lockPath);
-    }
-    finally
-    {
-      pool.release(connection);
-    }
+    if (currentConnection == null)
+      throw new IllegalStateException("Cannot clear non-ex-write lock we don't 
have: "+lockPath);
+    clearLock();
   }
 
   @Override
-  protected void obtainGlobalReadLock()
+  protected void obtainGlobalReadLockNoWait()
     throws ManifoldCFException, LockException, InterruptedException
   {
-    ZooKeeperConnection connection = pool.grab();
+    if (currentConnection != null)
+      throw new IllegalStateException("Already have a connection before read 
locking: "+lockPath);
+    boolean succeeded = false;
+    currentConnection = pool.grab();
     try
     {
-      connection.obtainGlobalReadLock(lockPath);
+      succeeded = currentConnection.obtainReadLockNoWait(lockPath);
+      if (!succeeded)
+        throw new LockException(LOCKEDANOTHERJVM);
     }
     finally
     {
-      pool.release(connection);
+      if (!succeeded)
+      {
+        pool.release(currentConnection);
+        currentConnection = null;
+      }
     }
   }
 
@@ -121,17 +138,18 @@ public class ZooKeeperLockObject extends
   protected void clearGlobalReadLock()
     throws ManifoldCFException, LockException, InterruptedException
   {
-    ZooKeeperConnection connection = pool.grab();
-    try
-    {
-      connection.clearGlobalReadLock(lockPath);
-    }
-    finally
-    {
-      pool.release(connection);
-    }
+    if (currentConnection == null)
+      throw new IllegalStateException("Cannot clear read lock we don't have: 
"+lockPath);
+    clearLock();
   }
 
+  protected void clearLock()
+    throws ManifoldCFException, InterruptedException
+  {
+    currentConnection.releaseLock();
+    pool.release(currentConnection);
+    currentConnection = null;
+  }
 
 }
 


Reply via email to