Author: jgray Date: Wed Jul 14 03:41:11 2010 New Revision: 963935 URL: http://svn.apache.org/viewvc?rev=963935&view=rev Log: HBASE-2695 [MasterStartupCleanup-v4] Cleans up the master startup, adds new ZK tool ActiveMasterManager for master-side (part of master cleanup and refactor) Added: hbase/branches/0.90_master_rewrite/BRANCH_TODO.txt hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/ActiveMasterManager.java hbase/branches/0.90_master_rewrite/src/test/java/org/apache/hadoop/hbase/master/TestActiveMasterManager.java Modified: hbase/branches/0.90_master_rewrite/BRANCH_CHANGES.txt hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/FileSystemManager.java hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/HMaster.java hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/MasterStatus.java hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/ZKMasterAddressWatcher.java hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/regionserver/MasterAddressManager.java hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKUtil.java hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/zookeeper/ZooKeeperWatcher.java hbase/branches/0.90_master_rewrite/src/test/java/org/apache/hadoop/hbase/regionserver/TestMasterAddressManager.java Modified: hbase/branches/0.90_master_rewrite/BRANCH_CHANGES.txt URL: http://svn.apache.org/viewvc/hbase/branches/0.90_master_rewrite/BRANCH_CHANGES.txt?rev=963935&r1=963934&r2=963935&view=diff ============================================================================== --- hbase/branches/0.90_master_rewrite/BRANCH_CHANGES.txt (original) +++ hbase/branches/0.90_master_rewrite/BRANCH_CHANGES.txt Wed Jul 14 03:41:11 2010 @@ -14,6 +14,9 @@ Branch 0.90.0 - Master Rewrite Branch HBASE-2696 Re-enabled TestZooKeeper.testRegionServerSessionExpired HBASE-2699 [LoadBalancer-v5] Reimplement load balancing to be a background process and to not use heartbeats + HBASE-2695 [MasterStartupCleanup-v4] Cleans up the master startup, adds + new ZK tool ActiveMasterManager for master-side (part of + master cleanup and refactor) NEW FEATURES Added: hbase/branches/0.90_master_rewrite/BRANCH_TODO.txt URL: http://svn.apache.org/viewvc/hbase/branches/0.90_master_rewrite/BRANCH_TODO.txt?rev=963935&view=auto ============================================================================== --- hbase/branches/0.90_master_rewrite/BRANCH_TODO.txt (added) +++ hbase/branches/0.90_master_rewrite/BRANCH_TODO.txt Wed Jul 14 03:41:11 2010 @@ -0,0 +1,38 @@ +List of things todo for branch, including comments from reviews not yet +implemented. + + +Now: + +* synchronize all access to the boolean in ActiveMasterManager + + +Think about: + +* renaming master file manager? MasterFS/MasterFileSystem + + +Later: + +* ServerStatus/MasterStatus + + - These need new names to be more descriptive (ServerControl?) + - They should have a very clear purpose that adds value beyond passing + HMaster directly + - Current idea is these things would just have accessors/setters to + the server status booleans and abort() methods (like closed, closing, + abortRequested) + +* HBaseEventHandler/HBaseEventType/HBaseExecutorService + + - After ZK changes, renamed to EventHandler/EventType + - Currently multiple types map to a single handler, we may want 1-to-1 + - Need to do a full review of the semantics of these once bulk of + master rewrite is done + +* LoadBalancer + + - Need to finish or back out code related to block locations + (if finish, need to use files not directory, and use right location) + - Put notes from reviewboard/jira into LB javadoc or hbase "book" + Added: hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/ActiveMasterManager.java URL: http://svn.apache.org/viewvc/hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/ActiveMasterManager.java?rev=963935&view=auto ============================================================================== --- hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/ActiveMasterManager.java (added) +++ hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/ActiveMasterManager.java Wed Jul 14 03:41:11 2010 @@ -0,0 +1,154 @@ +/** + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase.master; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.hbase.HServerAddress; +import org.apache.hadoop.hbase.zookeeper.ZKUtil; +import org.apache.hadoop.hbase.zookeeper.ZooKeeperListener; +import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; +import org.apache.zookeeper.KeeperException; + +/** + * Handles everything on master-side related to master election. + * + * Listens and responds to ZooKeeper notifications on the master znode, + * both nodeCreated and nodeDeleted. + * + * Contains blocking methods which will hold up backup masters, waiting + * for the active master to fail. + * + * This class is instantiated in the HMaster constructor and the method + * {@link #blockUntilBecomingActiveMaster()} is called to wait until becoming + * the active master of the cluster. + */ +public class ActiveMasterManager extends ZooKeeperListener { + private static final Log LOG = LogFactory.getLog(ActiveMasterManager.class); + + final AtomicBoolean clusterHasActiveMaster = new AtomicBoolean(false); + + private final HServerAddress address; + private final MasterStatus status; + + ActiveMasterManager(ZooKeeperWatcher watcher, HServerAddress address, + MasterStatus status) { + super(watcher); + this.address = address; + this.status = status; + } + + @Override + public void nodeCreated(String path) { + if(path.equals(watcher.masterAddressZNode) && !status.isClosed()) { + handleMasterNodeChange(); + } + } + + @Override + public void nodeDeleted(String path) { + if(path.equals(watcher.masterAddressZNode) && !status.isClosed()) { + handleMasterNodeChange(); + } + } + + /** + * Handle a change in the master node. Doesn't matter whether this was called + * from a nodeCreated or nodeDeleted event because there are no guarantees + * that the current state of the master node matches the event at the time of + * our next ZK request. + * + * Uses the watchAndCheckExists method which watches the master address node + * regardless of whether it exists or not. If it does exist (there is an + * active master), it returns true. Otherwise it returns false. + * + * A watcher is set which guarantees that this method will get called again if + * there is another change in the master node. + */ + private void handleMasterNodeChange() { + // Watch the node and check if it exists. + try { + synchronized(clusterHasActiveMaster) { + if(ZKUtil.watchAndCheckExists(watcher, watcher.masterAddressZNode)) { + // A master node exists, there is an active master + LOG.debug("A master is now available"); + clusterHasActiveMaster.set(true); + } else { + // Node is no longer there, cluster does not have an active master + LOG.debug("No master available. notifying waiting threads"); + clusterHasActiveMaster.set(false); + // Notify any thread waiting to become the active master + clusterHasActiveMaster.notifyAll(); + } + } + } catch (KeeperException ke) { + LOG.fatal("Received an unexpected KeeperException, aborting", ke); + status.abortServer(); + } + } + + /** + * Block until becoming the active master. + * + * Method blocks until there is not another active master and our attempt + * to become the new active master is successful. + * + * This also makes sure that we are watching the master znode so will be + * notified if another master dies. + */ + void blockUntilBecomingActiveMaster() { + // Try to become the active master, watch if there is another master + try { + if(ZKUtil.setAddressAndWatch(watcher, watcher.masterAddressZNode, + address)) { + // We are the master, return + clusterHasActiveMaster.set(true); + return; + } + } catch (KeeperException ke) { + LOG.fatal("Received an unexpected KeeperException, aborting", ke); + status.abortServer(); + return; + } + // There is another active master, this is not a cluster startup + // and we must wait until the active master dies + LOG.info("Another master is already the active master, waiting to become " + + "the next active master"); + clusterHasActiveMaster.set(true); + status.setClusterStartup(false); + synchronized(clusterHasActiveMaster) { + while(clusterHasActiveMaster.get() && !status.isClosed()) { + try { + clusterHasActiveMaster.wait(); + } catch (InterruptedException e) { + // We expect to be interrupted when a master dies, will fall out if so + LOG.debug("Interrupted waiting for master to die", e); + } + } + if(status.isClosed()) { + return; + } + // Try to become active master again now that there is no active master + blockUntilBecomingActiveMaster(); + } + } +} Modified: hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/FileSystemManager.java URL: http://svn.apache.org/viewvc/hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/FileSystemManager.java?rev=963935&r1=963934&r2=963935&view=diff ============================================================================== --- hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/FileSystemManager.java (original) +++ hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/master/FileSystemManager.java Wed Jul 14 03:41:11 2010 @@ -72,12 +72,23 @@ public class FileSystemManager { // We're supposed to run on 0.20 and 0.21 anyways. conf.set("fs.default.name", this.rootdir.toString()); conf.set("fs.defaultFS", this.rootdir.toString()); + // setup the filesystem variable this.fs = FileSystem.get(conf); - + // set up the archived logs path + this.oldLogDir = new Path(this.rootdir, HConstants.HREGION_OLDLOGDIR_NAME); + } + + /** + *
Used by the Master. Waits on the master address ZNode delete event. When - * multiple masters are brought up, they race to become master by writing their - * address to ZooKeeper. Whoever wins becomes the master, and the rest wait for - * that ephemeral node in ZooKeeper to evaporate (meaning the master went down), - * at which point they try to write their own address to become the new master. - */ -class ZKMasterAddressWatcher implements Watcher { - private static final Log LOG = LogFactory.getLog(ZKMasterAddressWatcher.class); - - private ZooKeeperWrapper zookeeper; - private final AtomicBoolean requestShutdown; - - /** - * Create this watcher using passed ZooKeeperWrapper instance. - * @param zk ZooKeeper - * @param flag Flag to set to request shutdown. - */ - ZKMasterAddressWatcher(final ZooKeeperWrapper zk, final AtomicBoolean flag) { - this.requestShutdown = flag; - this.zookeeper = zk; - } - - /** - * @see org.apache.zookeeper.Watcher#process(org.apache.zookeeper.WatchedEvent) - */ - @Override - public synchronized void process (WatchedEvent event) { - EventType type = event.getType(); - LOG.debug(("Got event " + type + " with path " + event.getPath())); - if (type.equals(EventType.NodeDeleted)) { - if (event.getPath().equals(this.zookeeper.clusterStateZNode)) { - LOG.info("Cluster shutdown while waiting, shutting down" + - " this master."); - this.requestShutdown.set(true); - } else { - LOG.debug("Master address ZNode deleted, notifying waiting masters"); - notifyAll(); - } - } else if(type.equals(EventType.NodeCreated) && - event.getPath().equals(this.zookeeper.clusterStateZNode)) { - LOG.debug("Resetting watch on cluster state node."); - this.zookeeper.setClusterStateWatch(); - } - } - - /** - * Wait for master address to be available. This sets a watch in ZooKeeper and - * blocks until the master address ZNode gets deleted. - */ - public synchronized void waitForMasterAddressAvailability() { - while (zookeeper.readMasterAddress(this) != null) { - try { - LOG.debug("Waiting for master address ZNode to be deleted " + - "(Also watching cluster state node)"); - this.zookeeper.setClusterStateWatch(); - wait(); - } catch (InterruptedException e) { - } - } - } - - /** - * Write address to zookeeper. Parks here until we successfully write our - * address (or until cluster shutdown). - * @param address Address whose format is HServerAddress.toString - */ - boolean writeAddressToZooKeeper( - final HServerAddress address, boolean retry) { - do { - waitForMasterAddressAvailability(); - // Check if we need to shutdown instead of taking control - if (this.requestShutdown.get()) { - LOG.debug("Won't start Master because cluster is shuting down"); - return false; - } - if(this.zookeeper.writeMasterAddress(address)) { - this.zookeeper.setClusterState(true); - this.zookeeper.setClusterStateWatch(); - // Watch our own node - this.zookeeper.readMasterAddress(this); - return true; - } - } while(retry); - return false; - } - - /** - * Reset the ZK in case a new connection is required - * @param zookeeper new instance - */ - public void setZookeeper(ZooKeeperWrapper zookeeper) { - this.zookeeper = zookeeper; - } -} \ No newline at end of file Modified: hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java URL: http://svn.apache.org/viewvc/hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java?rev=963935&r1=963934&r2=963935&view=diff ============================================================================== --- hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (original) +++ hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java Wed Jul 14 03:41:11 2010 @@ -327,7 +327,7 @@ public class HRegionServer implements HR zooKeeper = new ZooKeeperWatcher(conf, serverInfo.getServerName(), this); // create the master address manager, register with zk, and start it - masterAddressManager = new MasterAddressManager(zooKeeper); + masterAddressManager = new MasterAddressManager(zooKeeper, this); zooKeeper.registerListener(masterAddressManager); masterAddressManager.monitorMaster(); } Modified: hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/regionserver/MasterAddressManager.java URL: http://svn.apache.org/viewvc/hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/regionserver/MasterAddressManager.java?rev=963935&r1=963934&r2=963935&view=diff ============================================================================== --- hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/regionserver/MasterAddressManager.java (original) +++ hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/regionserver/MasterAddressManager.java Wed Jul 14 03:41:11 2010 @@ -22,21 +22,23 @@ package org.apache.hadoop.hbase.regionse import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hbase.HServerAddress; +import org.apache.hadoop.hbase.ServerStatus; import org.apache.hadoop.hbase.zookeeper.ZKUtil; import org.apache.hadoop.hbase.zookeeper.ZooKeeperListener; import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; +import org.apache.zookeeper.KeeperException; /** * Manages the location of the current active Master for this RegionServer. - * - * Listens for ZooKeeper events related to the master address. The node /master - * will contain the address of the current master. This listener is interested + * + * Listens for ZooKeeper events related to the master address. The node /master + * will contain the address of the current master. This listener is interested * in NodeDeleted and NodeCreated events on /master. - * + * * This class is thread-safe and takes care of re-setting all watchers to * ensure it always knows the up-to-date master. To kick it off, instantiate * the class and run the {@link #monitorMaster()} method. - * + * * You can get the current master via {@link #getMasterAddress()} or the * blocking method {@link #waitMasterAddress()}. */ @@ -45,25 +47,29 @@ public class MasterAddressManager extend // Address of the current primary master, null if no primary master private HServerAddress masterAddress; - + + // Status and controller for the regionserver + private ServerStatus status; + /** * Construct a master address listener with the specified zookeeper reference. - * + * * This constructor does not trigger any actions, you must call methods * explicitly. Normally you will just want to execute {@link #monitorMaster()} - * and you will ensure to - * + * and you will ensure to + * * @param watcher zk reference and watcher */ - public MasterAddressManager(ZooKeeperWatcher watcher) { + public MasterAddressManager(ZooKeeperWatcher watcher, ServerStatus status) { super(watcher); - masterAddress = null; + this.status = status; + this.masterAddress = null; } - + /** * Get the address of the current master if one is available. Returns null * if no current master. - * + * * Use {@link #waitMasterAddress} if you want to block until the master is * available. * @return server address of current active master, or null if none available @@ -71,7 +77,7 @@ public class MasterAddressManager extend public synchronized HServerAddress getMasterAddress() { return masterAddress; } - + /** * Check if there is a master available. * @return true if there is a master set, false if not. @@ -79,14 +85,14 @@ public class MasterAddressManager extend public synchronized boolean hasMaster() { return masterAddress != null; } - + /** * Get the address of the current master. If no master is available, method * will block until one is available, the thread is interrupted, or timeout * has passed. - * + * * TODO: Make this work, currently unused, kept with existing retry semantics. - * + * * @return server address of current active master, null if timed out * @throws InterruptedException if the thread is interrupted while waiting */ @@ -94,22 +100,28 @@ public class MasterAddressManager extend throws InterruptedException { return masterAddress; } - + /** * Setup to watch for the primary master of the cluster. - * + * * If the master is already available in ZooKeeper, this method will ensure * it gets set and that any further changes are also watched for. - * + * * If no master is available, this method ensures we become aware of it and * will take care of setting it. */ public void monitorMaster() { - if(ZKUtil.watchAndCheckExists(watcher, watcher.masterAddressZNode)) { - handleNewMaster(); + try { + if(ZKUtil.watchAndCheckExists(watcher, watcher.masterAddressZNode)) { + handleNewMaster(); + } + } catch(KeeperException ke) { + // If we have a ZK exception trying to find the master we must abort + LOG.fatal("Unexpected ZooKeeper exception", ke); + status.abortServer(); } } - + @Override public void nodeCreated(String path) { LOG.info("nodeCreated(" + path + ")"); @@ -118,7 +130,7 @@ public class MasterAddressManager extend } monitorMaster(); } - + @Override public void nodeDeleted(String path) { if(path.equals(watcher.masterAddressZNode)) { @@ -126,7 +138,7 @@ public class MasterAddressManager extend } monitorMaster(); } - + /** * Set the master address to the specified address. This operation is * idempotent, a master will only be set if there is currently no master set. @@ -137,7 +149,7 @@ public class MasterAddressManager extend masterAddress = address; } } - + /** * Unsets the master address. Used when the master goes offline so none is * available. @@ -148,34 +160,40 @@ public class MasterAddressManager extend masterAddress = null; } } - + /** * Handle a new master being set. - * + * * This method should be called to check if there is a new master. If there * is already a master set, this method returns immediately. If none is set, * this will attempt to grab the master location from ZooKeeper and will set * it. - * - * This method uses an atomic operation to ensure a new master is only set + * + * This method uses an atomic operation to ensure a new master is only set * once. */ private void handleNewMaster() { if(hasMaster()) { return; } - HServerAddress address = - ZKUtil.getDataAsAddress(watcher, watcher.masterAddressZNode); + HServerAddress address = null; + try { + address = ZKUtil.getDataAsAddress(watcher, watcher.masterAddressZNode); + } catch (KeeperException ke) { + // If we have a ZK exception trying to find the master we must abort + LOG.fatal("Unexpected ZooKeeper exception", ke); + status.abortServer(); + } if(address != null) { setMasterAddress(address); } } - + /** * Handle a master failure. - * + * * Triggered when a master node is deleted. - * + * * TODO: Other ways we figure master is "dead"? What do we do if set in ZK * but we can't communicate with TCP? */ Modified: hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKUtil.java URL: http://svn.apache.org/viewvc/hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKUtil.java?rev=963935&r1=963934&r2=963935&view=diff ============================================================================== --- hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKUtil.java (original) +++ hbase/branches/0.90_master_rewrite/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKUtil.java Wed Jul 14 03:41:11 2010 @@ -20,6 +20,7 @@ package org.apache.hadoop.hbase.zookeeper; import java.io.IOException; +import java.util.List; import java.util.Properties; import org.apache.commons.logging.Log; @@ -27,28 +28,34 @@ import org.apache.commons.logging.LogFac import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HServerAddress; import org.apache.hadoop.hbase.util.Bytes; +import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.data.Stat; /** * Internal HBase utility class for ZooKeeper. - * - * Contains only static methods and constants. + * + *
Contains only static methods and constants. + * + *
Methods all throw {@link KeeperException} if there is an unexpected
+ * zookeeper exception, so callers of these methods must handle appropriately.
+ * If ZK is required for the operation, the server will need to be aborted.
*/
public class ZKUtil {
private static final Log LOG = LogFactory.getLog(ZKUtil.class);
// TODO: Replace this with ZooKeeper constant when ZOOKEEPER-277 is resolved.
private static final char ZNODE_PATH_SEPARATOR = '/';
-
+
/**
* Creates a new connection to ZooKeeper, pulling settings and quorum config
* from the specified configuration object using methods from {@link ZKConfig}.
- *
+ *
* Sets the connection status monitoring watcher to the specified watcher.
- *
+ *
* @param conf configuration to pull quorum and other settings from
* @param watcher watcher to monitor connection changes
* @return connection to zookeeper
@@ -66,12 +73,16 @@ public class ZKUtil {
return new ZooKeeper(quorum, timeout, watcher);
}
+ //
+ // Helper methods
+ //
+
/**
* Join the prefix znode name with the suffix znode name to generate a proper
* full znode name.
- *
+ *
* Assumes prefix does not end with slash and suffix does not begin with it.
- *
+ *
* @param prefix beginning of znode name
* @param suffix ending of znode name
* @return result of properly joining prefix with suffix
@@ -80,16 +91,22 @@ public class ZKUtil {
return prefix + ZNODE_PATH_SEPARATOR + suffix;
}
+ //
+ // Existence checks and watches
+ //
+
/**
* Watch the specified znode for delete/create/change events. The watcher is
* set whether or not the node exists. If the node already exists, the method
* returns true. If the node does not exist, the method returns false.
- *
+ *
* @param zkw zk reference
* @param znode path of node to watch
* @return true if znode exists, false if does not exist or error
+ * @throws KeeperException if unexpected zookeeper exception
*/
- public static boolean watchAndCheckExists(ZooKeeperWatcher zkw, String znode) {
+ public static boolean watchAndCheckExists(ZooKeeperWatcher zkw, String znode)
+ throws KeeperException {
try {
Stat s = zkw.getZooKeeper().exists(znode, zkw);
zkw.debug("Set watcher on existing znode (" + znode + ")");
@@ -104,21 +121,103 @@ public class ZKUtil {
return false;
}
}
-
+
+ //
+ // Znode listings
+ //
+
+ /**
+ * Lists the children znodes of the specified znode. Also sets a watch on
+ * the specified znode which will capture a NodeDeleted event on the specified
+ * znode as well as NodeChildrenChanged if any children of the specified znode
+ * are created or deleted.
+ *
+ * Returns null if the specified node does not exist. Otherwise returns a
+ * list of children of the specified node. If the node exists but it has no
+ * children, an empty list will be returned.
+ *
+ * @param zkw zk reference
+ * @param znode path of node to list and watch children of
+ * @returns list of children of the specified node, an empty list if the node
+ * exists but has no children, and null if the node does not exist
+ * @throws KeeperException if unexpected zookeeper exception
+ */
+ public static List