|
From: <ble...@us...> - 2010-09-21 16:47:28
|
Revision: 3605
http://bigdata.svn.sourceforge.net/bigdata/?rev=3605&view=rev
Author: blevine218
Date: 2010-09-21 16:47:18 +0000 (Tue, 21 Sep 2010)
Log Message:
-----------
Adding zookeeper suite of tests
All tests now run without failures
Modified Paths:
--------------
branches/maven_scaleout/bigdata-integ/pom.xml
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/AbstractFedZooTestCase.java
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/JiniStartSuite.java
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/config/JiniStartConfigSuite.java
Added Paths:
-----------
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/AbstractZooTestCase.java
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestHierarchicalZNodeWatcher.java
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestUnknownChildrenWatcher.java
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZLockImpl.java
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeCreatedWatcher.java
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeDeletedWatcher.java
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZooBarrier.java
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZooElection.java
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZooQueue.java
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZookeeperAccessor.java
branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/ZookeeperSuite.java
Modified: branches/maven_scaleout/bigdata-integ/pom.xml
===================================================================
--- branches/maven_scaleout/bigdata-integ/pom.xml 2010-09-21 15:00:39 UTC (rev 3604)
+++ branches/maven_scaleout/bigdata-integ/pom.xml 2010-09-21 16:47:18 UTC (rev 3605)
@@ -108,7 +108,11 @@
<include>**/Test*Remote.java</include>
</includes>
<excludes>
+ <!-- Don't include suites as part of the normal test run -->
<exclude>**/*Suite.java</exclude>
+
+ <!-- Don't include anonymous inner classes that happen to match the test pattern -->
+ <exclude>**/*$*.java</exclude>
</excludes>
<systemPropertyVariables>
Modified: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/AbstractFedZooTestCase.java
===================================================================
--- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/AbstractFedZooTestCase.java 2010-09-21 15:00:39 UTC (rev 3604)
+++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/AbstractFedZooTestCase.java 2010-09-21 16:47:18 UTC (rev 3605)
@@ -38,9 +38,8 @@
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.ACL;
-import org.junit.Rule;
-import org.junit.rules.TestName;
+
import com.bigdata.jini.start.config.ZookeeperClientConfig;
import com.bigdata.jini.start.process.ProcessHelper;
import com.bigdata.jini.start.process.ZookeeperProcessHelper;
Modified: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/JiniStartSuite.java
===================================================================
--- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/JiniStartSuite.java 2010-09-21 15:00:39 UTC (rev 3604)
+++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/JiniStartSuite.java 2010-09-21 16:47:18 UTC (rev 3605)
@@ -1,17 +1,4 @@
-/***********************************************************************
- *
- * $Id$
- *
- * Copyright (c) 2000-2010 Nokia Corporation.
- *
- * This material, including documentation and any related computer
- * programs, is protected by copyright controlled by Nokia Corporation.
- * All rights are reserved. Copying, including reproducing, storing,
- * adapting or translating, any or all of this material requires the prior
- * written consent of Nokia Corporation. This material also contains
- * confidential information which may not be disclosed to others without
- * the prior written consent of Nokia Corporation.
- **********************************************************************/
+
package com.bigdata.jini.start;
import org.junit.runner.RunWith;
Modified: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/config/JiniStartConfigSuite.java
===================================================================
--- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/config/JiniStartConfigSuite.java 2010-09-21 15:00:39 UTC (rev 3604)
+++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/config/JiniStartConfigSuite.java 2010-09-21 16:47:18 UTC (rev 3605)
@@ -1,17 +1,4 @@
-/***********************************************************************
- *
- * $Id$
- *
- * Copyright (c) 2000-2010 Nokia Corporation.
- *
- * This material, including documentation and any related computer
- * programs, is protected by copyright controlled by Nokia Corporation.
- * All rights are reserved. Copying, including reproducing, storing,
- * adapting or translating, any or all of this material requires the prior
- * written consent of Nokia Corporation. This material also contains
- * confidential information which may not be disclosed to others without
- * the prior written consent of Nokia Corporation.
- **********************************************************************/
+
package com.bigdata.jini.start.config;
import org.junit.runner.RunWith;
Copied: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/AbstractZooTestCase.java (from rev 3580, branches/maven_scaleout/bigdata-core/src/test/java/com/bigdata/zookeeper/AbstractZooTestCase.java)
===================================================================
--- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/AbstractZooTestCase.java (rev 0)
+++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/AbstractZooTestCase.java 2010-09-21 16:47:18 UTC (rev 3605)
@@ -0,0 +1,528 @@
+/*
+
+ Copyright (C) SYSTAP, LLC 2006-2008. All rights reserved.
+
+ Contact:
+ SYSTAP, LLC
+ 4501 Tower Road
+ Greensboro, NC 27410
+ lic...@bi...
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * Created on Jan 4, 2009
+ */
+
+package com.bigdata.zookeeper;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.BindException;
+import java.net.ServerSocket;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+
+import com.bigdata.DataFinder;
+import net.jini.config.Configuration;
+import net.jini.config.ConfigurationProvider;
+
+import org.apache.log4j.Logger;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.KeeperException.NodeExistsException;
+import org.apache.zookeeper.KeeperException.SessionExpiredException;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.server.quorum.QuorumPeerMain;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+
+import com.bigdata.jini.start.MockListener;
+import com.bigdata.jini.start.config.ZookeeperServerConfiguration;
+import com.bigdata.jini.start.process.ProcessHelper;
+import com.bigdata.jini.start.process.ZookeeperProcessHelper;
+import com.bigdata.jini.util.ConfigMath;
+import com.bigdata.resources.ResourceFileFilter;
+
+/**
+ * Abstract base class for zookeeper integration tests.
+ *
+ * @author <a href="mailto:tho...@us...">Bryan Thompson</a>
+ * @version $Id$
+ */
+public abstract class AbstractZooTestCase {
+
+ public final static Logger log = Logger.getLogger(AbstractZooTestCase.class);
+
+ /**
+ * Constructor
+ */
+ public AbstractZooTestCase() {
+
+ }
+
+ /**
+ * Return an open port on current machine. Try the suggested port first. If
+ * suggestedPort is zero, just select a random port
+ */
+ protected static int getPort(final int suggestedPort) throws IOException {
+
+ ServerSocket openSocket;
+
+ try {
+ openSocket = new ServerSocket(suggestedPort);
+ } catch (BindException ex) {
+ // the port is busy, so look for a random open port
+ openSocket = new ServerSocket(0);
+ }
+
+ final int port = openSocket.getLocalPort();
+
+ openSocket.close();
+
+ return port;
+ }
+
+ /**
+ * A configuration file used by some of the unit tests in this package. It
+ * contains a description of the zookeeper server instance in case we need
+ * to start one.
+ */
+ protected final String configFile = DataFinder.bestURI("testing/data/com/bigdata/zookeeper/testzoo.config").toASCIIString();
+
+ /**
+ * Note: The sessionTimeout is computed as 2x the tickTime as read out of
+ * the configuration file by {@link #setUp()}. This corresponds to the
+ * actual sessionTimeout for the client rather than a requested value.
+ */
+ int sessionTimeout;
+
+ /**
+ * The initial {@link ZooKeeper} instance obtained from the
+ * {@link #zookeeperAccessor} when the test was setup.
+ * <p>
+ * Note: Some unit tests use {@link #expireSession(ZooKeeper)} to expire the
+ * session associated with this {@link ZooKeeper} instance.
+ *
+ * @see ZooKeeperAccessor
+ */
+ protected ZooKeeper zookeeper;
+
+ /**
+ * Factory for {@link ZooKeeper} instances using the configured hosts and
+ * session timeout.
+ */
+ protected ZooKeeperAccessor zookeeperAccessor;
+
+ /**
+ * ACL used by the unit tests.
+ */
+ protected final List<ACL> acl = Ids.OPEN_ACL_UNSAFE;
+
+ protected final MockListener listener = new MockListener();
+
+ private File dataDir = null;
+
+ // the chosen client port.
+ int clientPort = -1;
+
+ @Before
+ public void setUp() throws Exception {
+
+ try {
+ // find ports that are not in use.
+ clientPort = getPort(2181/* suggestedPort */);
+ final int peerPort = getPort(2888/* suggestedPort */);
+ final int leaderPort = getPort(3888/* suggestedPort */);
+ final String servers = "1=localhost:" + peerPort + ":" + leaderPort;
+
+ // create a temporary file for zookeeper's state.
+ dataDir = File.createTempFile("test", ".zoo");
+ // delete the file so that it can be re-created as a directory.
+ dataDir.delete();
+ // recreate the file as a directory.
+ dataDir.mkdirs();
+
+ final String[] args = new String[] {
+ // The configuration file (overrides follow).
+ configFile,
+ // overrides the clientPort to be unique.
+ QuorumPeerMain.class.getName() + "."
+ + ZookeeperServerConfiguration.Options.CLIENT_PORT + "="
+ + clientPort,
+ // overrides servers declaration.
+ QuorumPeerMain.class.getName() + "."
+ + ZookeeperServerConfiguration.Options.SERVERS + "=\""
+ + servers + "\"",
+ // overrides the dataDir
+ QuorumPeerMain.class.getName() + "."
+ + ZookeeperServerConfiguration.Options.DATA_DIR
+ + "=new java.io.File("
+ + ConfigMath.q(dataDir.toString()) + ")"//
+ };
+
+ System.err.println("args=" + Arrays.toString(args));
+
+ final Configuration config = ConfigurationProvider.getInstance(args);
+
+ final int tickTime = (Integer) config.getEntry(QuorumPeerMain.class
+ .getName(), ZookeeperServerConfiguration.Options.TICK_TIME,
+ Integer.TYPE);
+
+ /*
+ * Note: This is the actual session timeout that the zookeeper service
+ * will impose on the client.
+ */
+ this.sessionTimeout = tickTime * 2;
+
+ // if necessary, start zookeeper (a server instance).
+ ZookeeperProcessHelper.startZookeeper(config, listener);
+
+ zookeeperAccessor = new ZooKeeperAccessor("localhost:" + clientPort, sessionTimeout);
+
+ zookeeper = zookeeperAccessor.getZookeeper();
+
+ try {
+
+ /*
+ * Since all unit tests use children of this node we must make sure
+ * that it exists.
+ */
+ zookeeper
+ .create("/test", new byte[] {}, acl, CreateMode.PERSISTENT);
+
+ } catch (NodeExistsException ex) {
+
+ if (log.isInfoEnabled())
+ log.info("/test already exits.");
+
+ }
+
+ } catch (Throwable t) {
+
+ // don't leave around the dataDir if the setup fails.
+ recursiveDelete(dataDir);
+
+ throw new Exception(t);
+
+ }
+
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ try {
+ if (zookeeperAccessor != null) {
+ zookeeperAccessor.close();
+ }
+
+ for (ProcessHelper h : listener.running) {
+ // destroy zookeeper service iff we started it.
+ h.kill(true/* immediateShutdown */);
+ }
+
+ if (dataDir != null) {
+ // clean out the zookeeper data dir.
+ recursiveDelete(dataDir);
+ }
+
+ } catch (Throwable t) {
+ log.error(t, t);
+ }
+ }
+
+ /**
+ * Return a new {@link Zookeeper} instance that is connected to the same
+ * zookeeper ensemble but which has a distinct session.
+ *
+ * @return
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ protected ZooKeeper getDistinctZooKeeperWithDistinctSession() throws IOException, InterruptedException {
+
+ final ZooKeeper zookeeper2 = new ZooKeeper(zookeeperAccessor.hosts,
+ zookeeperAccessor.sessionTimeout, new Watcher() {
+ public void process(WatchedEvent e) {
+
+ }
+ });
+
+ /*
+ * Wait until this instance is connected.
+ */
+ final long timeout = TimeUnit.MILLISECONDS.toNanos(1000/* ms */);
+
+ final long begin = System.nanoTime();
+
+ while (zookeeper2.getState() != ZooKeeper.States.CONNECTED
+ && zookeeper2.getState().isAlive()) {
+
+ final long elapsed = System.nanoTime() - begin;
+
+ if (elapsed > timeout) {
+ Assert.fail("ZooKeeper session did not connect? elapsed="+ TimeUnit.NANOSECONDS.toMillis(elapsed));
+ }
+
+ if (log.isInfoEnabled()) {
+ log.info("Awaiting connected.");
+ }
+
+ Thread.sleep(100/* ms */);
+
+ }
+
+ if (!zookeeper2.getState().isAlive()) {
+ Assert.fail("Zookeeper died?");
+ }
+
+ if(log.isInfoEnabled())
+ log.info("Zookeeper connected.");
+
+ return zookeeper2;
+
+ }
+
+ /**
+ * Return a new {@link ZooKeeper} instance that is connected to the same
+ * zookeeper ensemble as the given instance and is using the same session
+ * but is nevertheless a distinct instance.
+ * <p>
+ * Note: This is used by some unit tests to force the given
+ * {@link ZooKeeper} to report a {@link SessionExpiredException} by closing
+ * the returned instance.
+ *
+ * @param zookeeper
+ * A zookeeper instance.
+ *
+ * @return A distinct instance associated with the same session.
+ *
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ protected ZooKeeper getDistinctZooKeeperForSameSession(ZooKeeper zookeeper1)
+ throws IOException, InterruptedException {
+
+ final ZooKeeper zookeeper2 = new ZooKeeper(zookeeperAccessor.hosts,
+ zookeeperAccessor.sessionTimeout, new Watcher() {
+ public void process(WatchedEvent e) {
+
+ }
+ }, zookeeper1.getSessionId(), zookeeper1.getSessionPasswd());
+
+ /*
+ * Wait until this instance is connected.
+ */
+ final long timeout = TimeUnit.MILLISECONDS.toNanos(1000/* ms */);
+ final long begin = System.nanoTime();
+
+ while (zookeeper2.getState() != ZooKeeper.States.CONNECTED
+ && zookeeper2.getState().isAlive()) {
+ final long elapsed = System.nanoTime() - begin;
+
+ if (elapsed > timeout) {
+ Assert.fail("ZooKeeper session did not connect? elapsed=" + TimeUnit.NANOSECONDS.toMillis(elapsed));
+ }
+
+ if (log.isInfoEnabled()) {
+ log.info("Awaiting connected.");
+ }
+
+ Thread.sleep(100/* ms */);
+ }
+
+ if (!zookeeper2.getState().isAlive()) {
+ Assert.fail("Zookeeper died?");
+ }
+
+ if(log.isInfoEnabled())
+ log.info("Zookeeper connected.");
+
+ return zookeeper2;
+ }
+
+ /**
+ * Expires the session associated with the {@link Zookeeper} client
+ * instance.
+ *
+ * @param zookeeper
+ *
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ protected void expireSession(ZooKeeper zookeeper) throws IOException,InterruptedException {
+
+ /*
+ * Obtain a distinct ZooKeeper instance associated with the _same_
+ * session.
+ */
+ final ZooKeeper zookeeper2 = getDistinctZooKeeperForSameSession(zookeeper);
+
+ /*
+ * Close this instance, forcing the original instance to report a
+ * SessionExpiredException. Note that this is not synchronous so we need
+ * to wait until the original ZooKeeper instance notices that its
+ * session is expired.
+ */
+ zookeeper2.close();
+
+ /*
+ * Wait up to the session timeout and then wait some more so that the
+ * events triggered by that timeout have time to propagate.
+ */
+ final long timeout = TimeUnit.MILLISECONDS.toNanos(sessionTimeout * 2);
+ final long begin = System.nanoTime();
+
+ while (zookeeper.getState().isAlive()) {
+ final long elapsed = System.nanoTime() - begin;
+
+ if (elapsed > timeout) {
+ Assert.fail("ZooKeeper session did not expire? elapsed="
+ + TimeUnit.NANOSECONDS.toMillis(elapsed)
+ + ", sessionTimeout=" + sessionTimeout);
+ }
+
+ if(log.isInfoEnabled()) {
+ log.info("Awaiting session expired.");
+ }
+
+ Thread.sleep(500/* ms */);
+ }
+
+ if (log.isInfoEnabled()) {
+ final long elapsed = System.nanoTime() - begin;
+
+ log.info("Session was expired: elapsed="
+ + TimeUnit.NANOSECONDS.toMillis(elapsed)
+ + ", sessionTimeout=" + sessionTimeout);
+ }
+ }
+
+ /**
+ * Class used to test concurrency primitives.
+ *
+ * @author <a href="mailto:tho...@us...">Bryan Thompson</a>
+ * @version $Id$
+ */
+ abstract protected class ClientThread extends Thread {
+
+ private final Thread main;
+ protected final ReentrantLock lock;
+
+ /**
+ *
+ * @param main
+ * The thread in which the test is running.
+ * @param lock
+ * A lock.
+ */
+ public ClientThread(final Thread main, final ReentrantLock lock) {
+
+ if (main == null)
+ throw new IllegalArgumentException();
+
+ if (lock == null)
+ throw new IllegalArgumentException();
+
+ this.main = main;
+ this.lock = lock;
+ setDaemon(true);
+ }
+
+ public void run() {
+ try {
+ run2();
+ } catch (Throwable t) {
+
+ // log error since won't be seen otherwise.
+ log.error(t.getLocalizedMessage(), t);
+
+ // interrupt the main thread.
+ main.interrupt();
+ }
+ }
+
+ abstract void run2() throws Exception;
+ }
+
+ /**
+ * Recursively removes any files and subdirectories and then removes the
+ * file (or directory) itself.
+ * <p>
+ * Note: Files that are not recognized will be logged by the
+ * {@link ResourceFileFilter}.
+ *
+ * @param f
+ * A file or directory.
+ */
+ private void recursiveDelete(final File f) {
+
+ if (f.isDirectory()) {
+
+ final File[] children = f.listFiles();
+
+ if (children == null) {
+ // The directory does not exist.
+ return;
+ }
+
+ for (int i = 0; i < children.length; i++) {
+ recursiveDelete(children[i]);
+ }
+ }
+
+ if(log.isInfoEnabled())
+ log.info("Removing: " + f);
+
+ if (f.exists() && !f.delete()) {
+ log.warn("Could not remove: " + f);
+ }
+ }
+
+ /**
+ * Recursive delete of znodes.
+ *
+ * @param zpath
+ *
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ protected void destroyZNodes(final ZooKeeper zookeeper, final String zpath)
+ throws KeeperException, InterruptedException {
+
+ // System.err.println("enter : " + zpath);
+
+ final List<String> children = zookeeper.getChildren(zpath, false);
+
+ for (String child : children) {
+ destroyZNodes(zookeeper, zpath + "/" + child);
+ }
+
+ if(log.isInfoEnabled())
+ log.info("delete: " + zpath);
+
+ zookeeper.delete(zpath, -1/* version */);
+ }
+
+ protected String getName() {
+ return getClass().getSimpleName();
+ }
+}
Copied: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestHierarchicalZNodeWatcher.java (from rev 3580, branches/maven_scaleout/bigdata-core/src/test/java/com/bigdata/zookeeper/TestHierarchicalZNodeWatcher.java)
===================================================================
--- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestHierarchicalZNodeWatcher.java (rev 0)
+++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestHierarchicalZNodeWatcher.java 2010-09-21 16:47:18 UTC (rev 3605)
@@ -0,0 +1,317 @@
+/*
+
+Copyright (C) SYSTAP, LLC 2006-2008. All rights reserved.
+
+Contact:
+ SYSTAP, LLC
+ 4501 Tower Road
+ Greensboro, NC 27410
+ lic...@bi...
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+/*
+ * Created on Jan 12, 2009
+ */
+
+package com.bigdata.zookeeper;
+
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.AssertionFailedError;
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher.Event;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test suite for {@link HierarchicalZNodeWatcher}.
+ * <p>
+ * Note: Zookeeper has other events that could appear during these unit tests,
+ * such as the connection status change events. However the unit test are not
+ * expecting such events during testing. If they appear, those events could
+ * cause test failures when we examine the queue. Basically, the tests are not
+ * robust if your zookeeper client is flakey.
+ *
+ * @author <a href="mailto:tho...@us...">Bryan Thompson</a>
+ * @version $Id$
+ */
+public class TestHierarchicalZNodeWatcher extends AbstractZooTestCase implements
+ HierarchicalZNodeWatcherFlags {
+
+ /**
+ *
+ */
+ public TestHierarchicalZNodeWatcher() {
+
+ }
+
+
+ protected String zroot;
+
+ /**
+ * Sets up a unique {@link #zroot}.
+ */
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ zroot = zookeeper.create("/test", new byte[0], acl, CreateMode.PERSISTENT_SEQUENTIAL);
+ }
+
+ /**
+ * Destroys the {@link #zroot} and its children.
+ */
+ @After
+ public void tearDown() throws Exception {
+ if (zroot != null) {
+ destroyZNodes(zookeeperAccessor.getZookeeper(), zroot);
+ }
+ super.tearDown();
+ }
+
+ /**
+ * Test when the node at the root of the hierarchy does not exist when we
+ * setup the watcher, then create the znode and verify that we see the event
+ * in the queue.
+ *
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ @Test
+ public void test_noticeCreate() throws KeeperException,
+ InterruptedException {
+
+ WatchedEvent e;
+
+ final String zroot = this.zroot + "/" + "a";
+ final HierarchicalZNodeWatcher watcher = new HierarchicalZNodeWatcher(
+ zookeeper, zroot, EXISTS) {
+
+ @Override
+ protected int watch(String path, String child) {
+ return NONE;
+ }
+ };
+
+ Assert.assertTrue(watcher.queue.isEmpty());
+ Assert.assertTrue(watcher.isWatched(zroot));
+
+ /*
+ * Create the zroot and verify the event is placed into the queue.
+ */
+
+ zookeeper.create(zroot, new byte[0], acl, CreateMode.PERSISTENT);
+
+ // look for the create event.
+ e= watcher.queue.poll(1000, TimeUnit.MILLISECONDS);
+
+ Assert.assertNotNull(e);
+ Assert.assertEquals(zroot,e.getPath());
+ Assert.assertEquals(Event.EventType.NodeCreated,e.getType());
+ Assert.assertTrue(watcher.queue.isEmpty());
+
+ /*
+ * Delete the znode and verify the event is placed into the queue.
+ */
+
+ zookeeper.delete(zroot, -1/*version*/);
+
+ // look for the delete event.
+ e = watcher.queue.poll(1000, TimeUnit.MILLISECONDS);
+
+ Assert.assertNotNull(e);
+ Assert.assertEquals(zroot,e.getPath());
+ Assert.assertEquals(Event.EventType.NodeDeleted, e.getType());
+ Assert.assertTrue(watcher.queue.isEmpty());
+
+ /*
+ * Re-create the zroot and verify the event is placed into the queue
+ * (this makes sure that we are keeping the watch in place).
+ */
+
+ zookeeper.create(zroot, new byte[0], acl, CreateMode.PERSISTENT);
+
+ // look for the create event.
+ e = watcher.queue.poll(1000, TimeUnit.MILLISECONDS);
+
+ Assert.assertNotNull(e);
+ Assert.assertEquals(zroot, e.getPath());
+ Assert.assertEquals(Event.EventType.NodeCreated, e.getType());
+ Assert.assertTrue(watcher.queue.isEmpty());
+
+ /*
+ * cancel the watcher and verify that it does not notice a delete of the
+ * zroot after it was cancelled.
+ */
+ watcher.cancel();
+
+ /*
+ * Delete the znode - no event should appear.
+ */
+
+ zookeeper.delete(zroot, -1/*version*/);
+
+ // look for the delete event.
+ e = watcher.queue.poll(1000, TimeUnit.MILLISECONDS);
+
+ Assert.assertNull(e);
+
+ }
+
+ /**
+ * Unit test verifies that we notice specific children as they are created
+ * and destroyed. "red" znodes are ignored. if the znode is "blue" then we
+ * extend the watch over its children as well.
+ *
+ * @throws KeeperException
+ * @throws InterruptedException
+ *
+ * @todo test queue when data is changed.
+ */
+ @Test
+ public void test_noticeChildren() throws InterruptedException, KeeperException {
+
+ WatchedEvent e;
+
+ HierarchicalZNodeWatcher watcher = new HierarchicalZNodeWatcher(zookeeper, zroot, EXISTS | CHILDREN) {
+
+ @Override
+ protected int watch(String path, String child) {
+
+ if (child.equals("red"))
+ return NONE;
+
+ if (child.equals("blue"))
+ return EXISTS | CHILDREN;
+
+ if (child.equals("green"))
+ return DATA;
+
+ throw new AssertionFailedError("Not expecting: path=" + path
+ + ", child=" + child);
+
+ }
+
+ };
+
+ zookeeper.create(zroot + "/" + "red", new byte[0], acl, CreateMode.PERSISTENT);
+
+ e = watcher.queue.poll(1000,TimeUnit.MILLISECONDS);
+ Assert.assertNotNull(e);
+ Assert.assertEquals(zroot,e.getPath());
+ Assert.assertEquals(Event.EventType.NodeChildrenChanged,e.getType());
+
+ zookeeper.create(zroot + "/" + "blue", new byte[0], acl,
+ CreateMode.PERSISTENT);
+
+// e = watcher.queue.poll(1000,TimeUnit.MILLISECONDS);
+// assertNotNull(e);
+// assertEquals(zroot+"/"+"red",e.getPath());
+// assertEquals(Event.EventType.NodeCreated,e.getType());
+
+ zookeeper.create(zroot + "/" + "blue" + "/" + "green", new byte[0],
+ acl, CreateMode.PERSISTENT);
+
+ Assert.assertEquals(NONE, watcher.getFlags(zroot + "/" + "red"));
+ Assert.assertEquals(EXISTS | CHILDREN, watcher.getFlags(zroot + "/" + "blue"));
+ Assert.assertEquals(DATA, watcher.getFlags(zroot + "/" + "blue" + "/" + "green"));
+
+ // clear any events in the queue.
+ watcher.queue.clear();
+
+ // update the data.
+ zookeeper.setData(zroot + "/" + "blue" + "/" + "green", new byte[] { 1 }, -1/* version */);
+
+ // verify event.
+ e = watcher.queue.poll(1000,TimeUnit.MILLISECONDS);
+ Assert.assertNotNull(e);
+ Assert.assertEquals(zroot + "/" + "blue" + "/" + "green",e.getPath());
+ Assert.assertEquals(Event.EventType.NodeDataChanged,e.getType());
+
+ // won't been seen since a "red" path.
+ zookeeper.create(zroot + "/" + "red" + "/" + "blue", new byte[0], acl, CreateMode.PERSISTENT);
+
+ Assert.assertEquals(NONE, watcher.getFlags(zroot + "/" + "red" + "/" + "blue"));
+
+ /*
+ * There should be three watched znodes: zroot; zroot/blue; and
+ * zroot/blue/green
+ */
+ Assert.assertEquals(3,watcher.getWatchedSize());
+
+ watcher.cancel();
+
+ Assert.assertEquals(0,watcher.getWatchedSize());
+ Assert.assertFalse(watcher.isWatched(zroot));
+ Assert.assertFalse(watcher.isWatched(zroot+"/"+"blue"));
+ Assert.assertFalse(watcher.isWatched(zroot+"/"+"blue"+"/"+"green"));
+
+ Assert.assertTrue(watcher.queue.isEmpty());
+
+ /*
+ * Setup a new watcher that wathes all paths but the red ones. The
+ * znodes already exist. Now verify that we receive various notices when
+ * the watcher is created.
+ */
+ watcher = new HierarchicalZNodeWatcher(zookeeper, zroot, ALL, true/* pumpMockEventsDuringStartup */) {
+
+ @Override
+ protected int watch(String path, String child) {
+
+ return ALL;
+
+ }
+
+// @Override
+// protected void addedWatch(String path, int flags) {
+//
+// placeMockEventInQueue(path, flags);
+//
+// }
+
+ };
+
+ /*
+ * We created 4 znodes plus the pre-existing zroot, so there should be
+ * five nodes picked up by the new watcher.
+ */
+ final String[] nodes = new String[] {
+ zroot,
+ zroot + "/" + "red",
+ zroot + "/" + "red" + "/" + "blue",
+ zroot + "/" + "blue",
+ zroot + "/" + "green" + "/" + "green",
+ };
+
+ // verify new watched size.
+ Assert.assertEquals(nodes.length, watcher.getWatchedSize());
+
+ /*
+ * Verify mock events were pumped into the queue. Since we specified
+ * ALL, there should be three events for each znode.
+ */
+ Assert.assertEquals(3 * 5, watcher.queue.size());
+
+ while ((e = watcher.queue.poll()) != null) {
+ System.err.println("mockEvent: "+e);
+ }
+
+ watcher.cancel();
+ }
+}
Copied: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestUnknownChildrenWatcher.java (from rev 3580, branches/maven_scaleout/bigdata-core/src/test/java/com/bigdata/zookeeper/TestUnknownChildrenWatcher.java)
===================================================================
--- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestUnknownChildrenWatcher.java (rev 0)
+++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestUnknownChildrenWatcher.java 2010-09-21 16:47:18 UTC (rev 3605)
@@ -0,0 +1,53 @@
+/*
+
+Copyright (C) SYSTAP, LLC 2006-2008. All rights reserved.
+
+Contact:
+ SYSTAP, LLC
+ 4501 Tower Road
+ Greensboro, NC 27410
+ lic...@bi...
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+/*
+ * Created on Jan 22, 2009
+ */
+
+package com.bigdata.zookeeper;
+
+import org.junit.Test;
+
+/**
+ * Test suite for watcher for unknown children (those not previously seen).
+ *
+ * @author <a href="mailto:tho...@us...">Bryan Thompson</a>
+ * @version $Id$
+ */
+public class TestUnknownChildrenWatcher extends AbstractZooTestCase {
+
+ /**
+ *
+ */
+ public TestUnknownChildrenWatcher() {
+ }
+
+
+ /** @todo place holder for unit tests. */
+ @Test
+ public void test_nothing() {
+
+ }
+
+}
Copied: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZLockImpl.java (from rev 3580, branches/maven_scaleout/bigdata-core/src/test/java/com/bigdata/zookeeper/TestZLockImpl.java)
===================================================================
--- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZLockImpl.java (rev 0)
+++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZLockImpl.java 2010-09-21 16:47:18 UTC (rev 3605)
@@ -0,0 +1,626 @@
+/*
+
+ Copyright (C) SYSTAP, LLC 2006-2008. All rights reserved.
+
+ Contact:
+ SYSTAP, LLC
+ 4501 Tower Road
+ Greensboro, NC 27410
+ lic...@bi...
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * Created on Jan 7, 2009
+ */
+
+package com.bigdata.zookeeper;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.KeeperException.NoNodeException;
+import org.apache.zookeeper.KeeperException.SessionExpiredException;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.bigdata.util.concurrent.DaemonThreadFactory;
+
+/**
+ * Test suite for {@link ZLockImpl}.
+ *
+ * @author <a href="mailto:tho...@us...">Bryan Thompson</a>
+ * @version $Id$
+ *
+ * @todo do test w/ ensemble where we kill the server to which the client is
+ * connected and verify that the client transparently reconnects to
+ * another server and continues to await the lock.
+ */
+public class TestZLockImpl extends AbstractZooTestCase {
+
+ /**
+ *
+ */
+ public TestZLockImpl() {
+ }
+
+
+ /**
+ * Simple lock protocol test.
+ *
+ * @todo test w/ timeout.
+ *
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ @Test
+ public void test_lock() throws KeeperException, InterruptedException {
+
+ final Thread mainThread = Thread.currentThread();
+
+ // a node that is guarenteed to be unique w/in the test namespace.
+ final String zpath = "/test/" + getName() + UUID.randomUUID();
+
+ try {
+ /*
+ * verify no such node (should be unique and therefore not
+ * preexist).
+ */
+ zookeeper.getChildren(zpath, false);
+ Assert.fail("zpath exists: " + zpath);
+ } catch (NoNodeException ex) {
+ // ignore.
+ }
+
+ // instances that can contend for the lock.
+ final ZLockImpl lock1 = ZLockImpl.getLock(zookeeper, zpath, acl);
+
+ // znode not created during ctor (more robust this way).
+ Assert.assertNull(zookeeper.exists(zpath, false));
+
+ final ZLockImpl lock2 = ZLockImpl.getLock(zookeeper, zpath, acl);
+
+ // znode not created during ctor (more robust this way).
+ Assert.assertNull(zookeeper.exists(zpath, false));
+
+ // obtain the lock.
+ lock1.lock();
+
+ log.info("lock1 was granted in main thread");
+
+ // one child in the queue - the one that holds the lock.
+ Assert.assertEquals(1, zookeeper.getChildren(zpath, false).size());
+
+ Assert.assertTrue(lock1.isLockHeld());
+
+ // run a thread that will contend for the lock.
+ final Thread t2 = new Thread() {
+
+ public void run() {
+
+ try {
+
+ log.info("Starting 2nd thread.");
+
+ Assert.assertTrue(lock1.isLockHeld());
+
+ log.info("Should block seeking lock2 in 2nd thread.");
+
+ lock2.lock();
+
+ log.info("lock2 was granted");
+
+ // one child in the queue - the one that holds the lock.
+ Assert.assertEquals(1, zookeeper.getChildren(zpath, false).size());
+
+ } catch (Throwable t) {
+
+ // log error
+ log.error(t, t);
+
+ // interrupt the main thread.
+ mainThread.interrupt();
+
+ }
+ }
+
+ };
+
+ t2.setDaemon(true);
+
+ t2.start();
+
+ // wait until the other child is also contending for the lock
+ for (int i = 0; i < 10; i++) {
+
+ final int n = zookeeper.getChildren(zpath, false).size();
+
+ log.info("nchildren=" + n);
+
+ if (n == 2)
+ break;
+
+ Thread.sleep(10/* ms */);
+
+ }
+
+ // should be exactly two children in the queue.
+ Assert.assertEquals(2, zookeeper.getChildren(zpath, false).size());
+
+ log.info("Will release lock1.");
+
+ // release the lock.
+ lock1.unlock();
+
+ log.info("Released lock1.");
+
+ // wait until the other thread gains the lock.
+ for (int i = 0; i < 10 && !lock2.isLockHeld(); i++) {
+
+ Thread.sleep(10/* ms */);
+
+ }
+
+ log.info("Verifying lock2 is held.");
+
+ // verify lock is held.
+ Assert.assertTrue(lock2.isLockHeld());
+
+ log.info("Verifying queue contains only lock2.");
+
+ // verify one child in the queue.
+ Assert.assertEquals(1, zookeeper.getChildren(zpath, false).size());
+
+ log.info("Releasing lock2 from main thread.");
+
+ // release the lock.
+ lock2.unlock();
+
+ log.info("Verifying queue is empty.");
+
+ // queue is empty.
+ Assert.assertEquals(0, zookeeper.getChildren(zpath, false).size());
+
+ log.info("Test done.");
+
+ }
+
+ /**
+ * Unit test explores behavior when someone stomps on the zchild while a
+ * lock is held and another lock is in the queue (note that you can not
+ * delete the parent without deleting the children in zookeeper, so you will
+ * always see a queue purged of children before the queue node itself is
+ * deleted).
+ *
+ * @throws InterruptedException
+ * @throws KeeperException
+ */
+ @Test
+ public void test_breakLock() throws KeeperException, InterruptedException {
+
+ final Thread mainThread = Thread.currentThread();
+
+ // a node that is guarenteed to be unique w/in the test namespace.
+ final String zpath = "/test/" + getName() + UUID.randomUUID();
+
+ try {
+ /*
+ * verify no such node (should be unique and therefore not
+ * preexist).
+ */
+ zookeeper.getChildren(zpath, false);
+ Assert.fail("zpath exists: " + zpath);
+ } catch (NoNodeException ex) {
+ // ignore.
+ }
+
+ // instances that can contend for the lock.
+ final ZLockImpl lock1 = ZLockImpl.getLock(zookeeper, zpath, acl);
+
+ // znode not created during ctor (more robust this way).
+ Assert.assertNull(zookeeper.exists(zpath, false));
+
+ final ZLockImpl lock2 = ZLockImpl.getLock(zookeeper, zpath, acl);
+
+ // znode not created during ctor (more robust this way).
+ Assert.assertNull(zookeeper.exists(zpath, false));
+
+ // obtain the lock.
+ lock1.lock();
+
+ log.info("lock1 was granted");
+
+ // one child in the queue - the one that holds the lock.
+ Assert.assertEquals(1, zookeeper.getChildren(zpath, false).size());
+
+ Assert.assertTrue(lock1.isLockHeld());
+
+ // run a thread that will contend for the lock.
+ final Thread t2 = new Thread() {
+
+ public void run() {
+
+ try {
+
+ Assert.assertTrue(lock1.isLockHeld());
+
+ lock2.lock();
+
+ log.info("lock2 granted.");
+
+ } catch (Throwable t) {
+
+ // log error
+ log.error(t, t);
+
+ // interrupt the main thread.
+ mainThread.interrupt();
+
+ }
+
+ }
+
+ };
+
+ t2.setDaemon(true);
+
+ t2.start();
+
+ // wait until the other child is also contending for the lock
+ for (int i = 0; i < 10
+ && zookeeper.getChildren(zpath, false).size() != 2; i++) {
+
+ Thread.sleep(10/* ms */);
+
+ }
+
+ // should be exactly two children in the queue.
+ Assert.assertEquals(2, zookeeper.getChildren(zpath, false).size());
+
+ // break the lock.
+ {
+ final String z = zpath + "/"
+ + ((ZLockImpl) lock1).getLockRequestZNode();
+ log.info("breaking lock: deleting " + z);
+ zookeeper.delete(z, -1/* version */);
+ log.info("broke lock: deleted " + z);
+ }
+
+ Assert.assertTrue(!lock1.isLockHeld());
+
+ Assert.assertTrue(lock2.isLockHeld());
+
+ log.info("lock1.unlock() - begin");
+
+ lock1.unlock();
+
+ log.info("lock1.unlock() - done");
+
+ Assert.assertFalse(lock1.isLockHeld());
+
+ }
+
+ /**
+ * Unit test verifies that a {@link Thread} holding a {@link ZLock} may NOT
+ * acquire it again.
+ *
+ * @throws InterruptedException
+ * @throws KeeperException
+ */
+ @Test
+ public void test_notReentrant() throws KeeperException,
+ InterruptedException {
+
+ // a node that is guarenteed to be unique w/in the test namespace.
+ final String zpath = "/test/" + getName() + UUID.randomUUID();
+
+ final ZLockImpl zlock = ZLockImpl.getLock(zookeeper, zpath, acl);
+
+ zlock.lock();
+
+ Assert.assertTrue(zlock.isLockHeld());
+
+ try {
+ zlock.lock(500, TimeUnit.MILLISECONDS);
+ Assert.fail("Expecting: " + TimeoutException.class);
+ } catch (TimeoutException ex) {
+ log.info("Expected exception: " + ex);
+ }
+
+ // Assert.assertTrue(zlock.isLockHeld());
+ //
+ // zlock.unlock();
+ //
+ // Assert.assertTrue(zlock.isLockHeld());
+ //
+ // zlock.unlock();
+ //
+ // Assert.assertFalse(zlock.isLockHeld());
+
+ }
+
+ /**
+ * Unit test where the session is expired before the lock is requested.
+ * lock() should throw out the {@link SessionExpiredException}. We then
+ * verify that we can obtain a new {@link ZooKeeper} instance associated
+ * with a new session and request and obtain the zlock.
+ *
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws KeeperException
+ */
+ @Test
+ public void test_sessionExpiredBeforeLockRequest() throws IOException,
+ KeeperException, InterruptedException {
+
+ // a node that is guarenteed to be unique w/in the test namespace.
+ final String zpath = "/test/" + getName() + UUID.randomUUID();
+
+ expireSession(zookeeper);
+
+ {
+
+ // obtain a lock object.
+ final ZLockImpl zlock = ZLockImpl.getLock(zookeeper, zpath, acl);
+
+ try {
+
+ zlock.lock();
+
+ Assert.fail("Expecting: " + SessionExpiredException.class);
+
+ } catch (SessionExpiredException ex) {
+
+ if (log.isInfoEnabled())
+ log.info("Ignoring expected exception: " + ex);
+
+ }
+
+ }
+
+ // get a new instance associated with a new session.
+ zookeeper = zookeeperAccessor.getZookeeper();
+
+ // obtain a lock object.
+ final ZLockImpl zlock = ZLockImpl.getLock(zookeeper, zpath, acl);
+ zlock.lock();
+ try {
+
+ } finally {
+ zlock.unlock();
+ }
+
+ }
+
+ /**
+ * Unit test where the session is expired while the caller is holding the
+ * lock. The test verifies that isLockHeld() throws a
+ * {@link SessionExpiredException}.
+ *
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws KeeperException
+ */
+ @Test
+ public void test_sessionExpiredWhileHoldingLock() throws IOException,
+ KeeperException, InterruptedException {
+
+ // a node that is guarenteed to be unique w/in the test namespace.
+ final String zpath = "/test/" + getName() + UUID.randomUUID();
+
+ // obtain a lock object.
+ final ZLockImpl zlock = ZLockImpl.getLock(zookeeper, zpath, acl);
+ zlock.lock();
+ try {
+
+ Assert.assertTrue(zlock.isLockHeld());
+
+ expireSession(zookeeper);
+
+ try {
+
+ zlock.isLockHeld();
+
+ Assert.fail("Expecting: " + SessionExpiredException.class);
+
+ } catch (SessionExpiredException ex) {
+
+ if (log.isInfoEnabled())
+ log.info("Ignoring expected exception: " + ex);
+
+ }
+
+ } finally {
+ /*
+ * Note: This also verifies that NO exception is thrown here even
+ * though the session has been expired. This is done to avoid have
+ * the expired session problem appear to arise from unlock() when it
+ * matters more that people see if when testing to verify that they
+ * hold the lock.
+ */
+ zlock.unlock();
+ }
+
+ }
+
+ /**
+ * Unit test for destroying a lock which is actively contended by other
+ * processes.
+ *
+ * @throws InterruptedException
+ * @throws KeeperException
+ * @throws ExecutionException
+ */
+ @Test
+ public void test_destroyLock() throws KeeperException,
+ InterruptedException, ExecutionException {
+
+ // a node that is guarenteed to be unique w/in the test namespace.
+ final String zpath = "/test/" + getName() + UUID.randomUUID();
+
+ final int ntasks = 4;
+
+ final ExecutorService service = Executors.newFixedThreadPool(ntasks,
+ DaemonThreadFactory.defaultThreadFactory());
+
+ final LinkedList<Callable<Void>> tasks = new LinkedList<Callable<Void>>();
+
+ for (int i = 0; i < ntasks; i++) {
+
+ tasks.add(new Callable<Void>() {
+
+ /**
+ * Contends for the zlock.
+ * <p>
+ * Note: Task uses a distinct ZooKeeper having a distinct
+ * session.
+ */
+ public Void call() throws Exception {
+
+ final ZooKeeper zookeeper2 = getDistinctZooKeeperWithDistinctSession();
+
+ // obtain a lock object.
+ final ZLockImpl zlock = ZLockImpl.getLock(zookeeper2,
+ zpath, acl);
+
+ zlock.lock();
+ try {
+
+ Assert.fail("Should not have obtained the lock.");
+
+ } finally {
+
+ zlock.unlock();
+
+ }
+
+ return null;
+
+ }
+
+ });
+
+ }
+
+ final List<Future<Void>> futures = new LinkedList<Future<Void>>();
+ try {
+
+ // obtain a lock object.
+ final ZLockImpl zlock = ZLockImpl.getLock(zookeeper, zpath, acl);
+
+ zlock.lock();
+ try {
+
+ // verify that the main thread holds the zlock.
+ Assert.assertTrue(zlock.isLockHeld());
+
+ // start the other tasks. they will contend for the same zlock.
+ for (Callable<Void> task : tasks) {
+
+ futures.add(service.submit(task));
+
+ }
+
+ // wait until everyone is contending for the lock.
+ int queueSize;
+ while ((queueSize = zlock.getQueue().length) < ntasks + 1) {
+
+ if (log.isInfoEnabled())
+ log.info("Waiting for other processes: queueSize="
+ + queueSize);
+
+ Thread.sleep(100/* ms */);
+
+ }
+
+ if (log.isInfoEnabled())
+ log.info("Main thread will now destroy the lock.");
+
+ zlock.destroyLock();
+
+ // verify lock no longer held.
+ Assert.assertFalse(zlock.isLockHeld());
+
+ } finally {
+
+ // note: should quitely succeed if the lock was destroyed.
+ zlock.unlock();
+
+ }
+
+ } finally {
+
+ service.shutdownNow();
+
+ }
+
+ // verify all tasks started.
+ Assert.assertEquals(ntasks, futures.size());
+
+ // check their futures.
+ for (Future<Void> f : futures) {
+
+ try {
+
+ f.get();
+
+ } catch (ExecutionException ex) {
+
+ final Throwable cause = ex.getCause();
+
+ if (cause != null && cause instanceof InterruptedException) {
+
+ /*
+ * When the lock znode is destroyed, the other processes
+ * contending for the zlock will notice in their
+ * ZLockWatcher. The ZLockWatcher will be set its
+ * [cancelled] flag and an InterruptedException will be
+ * thrown out of lock().
+ */
+
+ if (log.isInfoEnabled()) {
+
+ log.info("Ignoring expected exception: " + cause);
+
+ }
+
+ continue;
+
+ }
+
+ /*
+ * Rethrow the execption.
+ *
+ * Note: If any of the tasks gains the lock, then it will throw
+ * an AssertionFailedError.
+ */
+
+ throw ex;
+
+ }
+
+ }
+ }
+}
Copied: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeCreatedWatcher.java (from rev 3580, branches/maven_scaleout/bigdata-core/src/test/java/com/bigdata/zookeeper/TestZNodeCreatedWatcher.java)
===================================================================
--- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeCreatedWatcher.java (rev 0)
+++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeCreatedWatcher.java 2010-09-21 16:47:18 UTC (rev 3605)
@@ -0,0 +1,113 @@
+/*
+
+Copyright (C) SYSTAP, LLC 2006-2008. All rights reserved.
+
+Contact:
+ SYSTAP, LLC
+ 4501 Tower Road
+ Greensboro, NC 27410
+ lic...@bi...
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+/*
+ * Created on Jan 7, 2009
+ */
+
+package com.bigdata.zookeeper;
+
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test suite for {@link ZNodeCreatedWatcher}.
+ *
+ * @author <a href="mailto:tho...@us...">Bryan Thompson</a>
+ * @version $Id$
+ *
+ * @todo do test where we kill and then restart the server while awaiting the
+ * event and verify that we reconnect to the server and continue to await
+ * the event.
+ *
+ * @todo do test w/ ensemble where we kill the server to which the client is
+ * connected and verify that reconnect to another server and continue to
+ * await the event.
+ */
+public class TestZNodeCreatedWatcher extends AbstractZooTestCase {
+
+ /**
+ *
+ */
+ public TestZNodeCreatedWatcher() {
+ }
+
+
+ /**
+ * Verify that we can detect the create of a znode.
+ *
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ @Test
+ public void test_awaitCreate() throws KeeperException, InterruptedException {
+
+ // a node that is guaranteed to be unique w/in the test namespace.
+ final String zpath = "/test/" + getName() + UUID.randomUUID();
+
+ final Thread mainThread = Thread.currentThread();
+
+ final Thread t = new Thread() {
+
+ public void run() {
+
+ try {
+
+ Thread.sleep(100/*ms*/);
+
+ zookeeper.create(zpath, new byte[0], Ids.OPEN_ACL_UNSAFE,
+ CreateMode.PERSISTENT);
+
+ } catch (Throwable t) {
+
+ // log error
+ log.error(t, t);
+
+ // interrupt the main thread.
+ mainThread.interrupt();
+
+ }
+ }
+
+ };
+
+ t.setDaemon(true);
+
+ t.start();
+
+ ZNodeCreatedWatcher.awaitCreate(zookeeper, zpath, 250,
+ TimeUnit.MILLISECONDS);
+
+// ZNodeCreatedWatcher.awaitCreate(zookeeper, zpath, 250,
+// TimeUnit.MILLISECONDS);
+
+ // verify znode was created.
+ Assert.assertNotNull(zookeeper.exists(zpath, false));
+ }
+}
Copied: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeDeletedWatcher.java (from rev 3580, branches/maven_scaleout/bigdata-core/src/test/java/com/bigdata/zookeeper/TestZNodeDeletedWatcher.java)
===================================================================
--- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeDeletedWatcher.java (rev 0)
+++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeDele...
[truncated message content] |