Example usage for org.apache.zookeeper Watcher Watcher

List of usage examples for org.apache.zookeeper Watcher Watcher

Introduction

In this page you can find the example usage for org.apache.zookeeper Watcher Watcher.

Prototype

Watcher

Source Link

Usage

From source file:com.bigdata.zookeeper.DumpZookeeper.java

License:Open Source License

/**
 * Dumps the zookeeper znodes for the bigdata federation.
 * /*from   w ww.  ja va 2  s. c  o  m*/
 * @param args
 *            A {@link Configuration} and optional overrides.
 * 
 * @throws IOException
 * @throws InterruptedException
 * @throws KeeperException
 * @throws ConfigurationException 
 * 
 * TODO Add a listener mode (tail zk events).
 */
public static void main(final String[] args)
        throws IOException, InterruptedException, KeeperException, ConfigurationException {

    final Configuration config = ConfigurationProvider.getInstance(args);

    final ZookeeperClientConfig zooClientConfig = new ZookeeperClientConfig(config);

    /*
     * Note: You may temporarily uncomment this to set the zookeeper
     * configuration via -D parameters.
     */
    //        final ZookeeperClientConfig zooClientConfig = new ZookeeperClientConfig();

    System.out.println(zooClientConfig.toString());

    //        System.err.println(ZooHelper.dump(InetAddress.getLocalHost(),
    //                clientPort));

    final boolean showData = true;

    final ZooKeeper z = new ZooKeeper(zooClientConfig.servers, 2000/* sessionTimeout */, new Watcher() {

        public void process(WatchedEvent event) {

            log.info(event);

        }
    });

    /*
     * The sessionTimeout as negotiated (effective sessionTimeout).
     * 
     * Note: This is not available until we actually request something
     * from zookeeper. 
     */
    {

        try {
            z.getData(zooClientConfig.zroot, false/* watch */, null/* stat */);
        } catch (NoNodeException ex) {
            // Ignore.
        } catch (KeeperException ex) {
            // Oops.
            log.error(ex, ex);
        }

        System.out.println("Negotiated sessionTimeout=" + z.getSessionTimeout() + "ms");
    }

    final PrintWriter w = new PrintWriter(System.out);
    try {

        // recursive dump.
        new DumpZookeeper(z).dump(w, showData, zooClientConfig.zroot, 0/* depth */);

        w.println("----");

        w.flush();

    } finally {

        z.close();
        w.close();

    }

}

From source file:com.bigdata.zookeeper.TestZookeeperSessionSemantics.java

License:Open Source License

public void test_handleExpiredSession() throws InterruptedException, KeeperException, IOException {

    final String hosts = "localhost:" + clientPort;

    final Lock lock = new ReentrantLock();
    final Condition expireCond = lock.newCondition();
    final Condition connectCond = lock.newCondition();
    final Condition disconnectCond = lock.newCondition();
    final AtomicBoolean didExpire = new AtomicBoolean(false);
    final AtomicBoolean didDisconnect = new AtomicBoolean(false);

    /*//from  w ww.j  a v  a  2 s  .  co m
     * Start an instance and run until it gets an assigned sessionId.
     */
    {
        final ZooKeeper zk1a = new ZooKeeper(hosts, requestedSessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                log.warn(event);
            }
        });
        int i = 0;
        while (i < 10) {
            boolean done = false;
            if (zk1a.getState() == ZooKeeper.States.CONNECTED) {
                done = true;
            }
            log.info("zk.getState()=" + zk1a.getState() + ", zk.getSessionId()=" + zk1a.getSessionId());
            if (done)
                break;
            Thread.sleep(500);
            i++;
        }
        if (zk1a.getState() != ZooKeeper.States.CONNECTED) {
            fail("Did not connect.");
        }
        zk1a.close();
    }

    final ZooKeeper zk1 = new ZooKeeper(hosts, requestedSessionTimeout, new Watcher() {
        /**
         * Note: The default watcher will not receive any events
         * after a session expire. A {@link Zookeeper#close()}
         * causes an immediate session expire. Thus, no events
         * (include the session expire) will be received after a
         * close().
         */
        @Override
        public void process(final WatchedEvent event) {
            log.warn(event);
            switch (event.getState()) {
            case AuthFailed:
                break;
            case Disconnected:
                lock.lock();
                try {
                    didDisconnect.set(true);
                    disconnectCond.signalAll();
                } finally {
                    lock.unlock();
                }
                break;
            case Expired:
                lock.lock();
                try {
                    didExpire.set(true);
                    expireCond.signalAll();
                } finally {
                    lock.unlock();
                }
                break;
            //                        case ConnectedReadOnly: // not in 3.3.3
            //                            break;
            //                        case NoSyncConnected: // not in 3.3.3
            //                            break;
            //                        case SaslAuthenticated: // not in 3.3.3
            //                            break;
            case SyncConnected:
                lock.lock();
                try {
                    connectCond.signalAll();
                } finally {
                    lock.unlock();
                }
                break;
            case Unknown:
                break;
            }

        }
    });

    /*
     * Note: You can not obtain the negotiated session timeout until the
     * zookeeper client has connected to a zookeeper service (or rather,
     * it will return ZERO until it is connected).
     */
    final int negotiatedSessionTimeout;
    lock.lock();
    try {
        log.info("Waiting zk connected.");
        connectCond.await(10, TimeUnit.SECONDS);
        negotiatedSessionTimeout = zk1.getSessionTimeout();
        if (log.isInfoEnabled())
            log.info("Negotiated sessionTimeout=" + negotiatedSessionTimeout);
        assertNotSame(0, negotiatedSessionTimeout);
        assertTrue(negotiatedSessionTimeout > 0);
    } finally {
        lock.unlock();
    }

    assertTrue(zk1.getState().isAlive());

    assertFalse(didDisconnect.get());

    assertFalse(didExpire.get());

    // clear out test znodes.
    destroyZNodes(zk1, "/test");

    // ensure root /test znode exists.
    try {
        zk1.create("/test", new byte[] {}, acl, CreateMode.PERSISTENT);
    } catch (KeeperException.NodeExistsException ex) {
        log.warn("Ignoring: " + ex);
    }

    // look at that znode, establishing a watcher.
    zk1.getData("/test", true/* watch */, null/* stat */);

    // update the znode's data.
    zk1.setData("/test", new byte[] { 1 }, -1/* version */);

    // create an ephemeral sequential znode that is a child of /test.
    final String foozpath = zk1.create("/test/foo", new byte[] {}, acl, CreateMode.EPHEMERAL_SEQUENTIAL);

    // create a 2nd ephemeral sequential znode that is a child of /test.
    final String foozpath2 = zk1.create("/test/foo", new byte[] {}, acl, CreateMode.EPHEMERAL_SEQUENTIAL);

    /*
     * Look at that znode, establishing a watcher.
     * 
     * Note: We appear to see node deleted events for the ephemeral znodes
     * if the client connection is closed, but the state is still reported
     * as SyncConnected rather than SessionExpired.
     * 
     * Note: If we do not establish a watcher for an ephemeral znode, then
     * we DO NOT see an node deleted event when the client is closed!
     */
    zk1.getData(foozpath, true/* watch */, null/* stat */);
    //        zk1.getData(foozpath2, true/* watch */, null/* stat */);

    ////      close the existing instance.
    //        log.info("Closing ZK client");
    //        zk1.close();

    //        log.fatal("killing local zookeeper service.");
    //        killZKServer();
    //        Thread.sleep(5000);
    //        fail("done");

    if (false) {
        log.info("Spin loop awaiting !isAlive() for client.");
        final long begin = System.currentTimeMillis();
        while (zk1.getState().isAlive()) {
            log.info("zk.getState()=" + zk1.getState() + ", zk.getSessionId()=" + zk1.getSessionId());
            final long elapsed = System.currentTimeMillis() - begin;
            if (elapsed > 60000 * 2)
                fail("Client still isAlive().");
            Thread.sleep(1000);
        }
        log.info("Continuing");
    }

    if (true) {
        log.error("KILL ZOOKEEPER.");
        Thread.sleep(5000);
        log.info("Spin loop on ephemeral znode getData() for client.");
        while (true) {
            try {
                zk1.getData(foozpath, true/* watch */, null/* stat */);
            } catch (KeeperException ex) {
                log.error(ex, ex);
                Thread.sleep(1000);
                continue;
            }
            log.info("zk.getState()=" + zk1.getState() + ", zk.getSessionId()=" + zk1.getSessionId());
            break;
            //                final long elapsed = System.currentTimeMillis() - begin;
            //                if (elapsed > 60000 * 2)
            //                    fail("Client still isAlive().");
            //                Thread.sleep(1000);
        }
        log.info("Continuing");
        final byte[] a = zk1.getData(foozpath, true/* watch */, null/* stat */);
        assertTrue("Expected " + Arrays.toString(new byte[] { 1 }) + ", not " + Arrays.toString(a),
                BytesUtil.bytesEqual(new byte[] { 1 }, a));
    }

    // // The disconnect event should be immediate.
    // lock.lock();
    // try {
    // disconnectCond.await(100, TimeUnit.MILLISECONDS);
    // } finally {
    // lock.unlock();
    // }
    //
    // assertTrue(didDisconnect.get());

    assertFalse(didDisconnect.get());
    assertFalse(didExpire.get());

    assertFalse(zk1.getState().isAlive());

    /*
     * Wait up to a little more than the negotiated session timeout for the
     * session to be expired.
     */
    lock.lock();
    try {
        // Attempt to get the znode again.
        new Thread(new Runnable() {
            public void run() {
                try {
                    final byte[] tmp = zk1.getData("/test", true/* watch */, null/* stat */);
                } catch (KeeperException e) {
                    log.error(e, e);
                } catch (InterruptedException e) {
                    log.error(e, e);
                }
            }
        }).start();
        expireCond.await(negotiatedSessionTimeout + 10000, TimeUnit.MILLISECONDS);
        /*
         * Note: No events are ever delivered to the watcher with
         * KeeperStates:=SessionExpired. This appears to be a design
         * decision.
         */
        assertFalse(didExpire.get());
    } finally {
        lock.unlock();
    }

    /*
     * Now obtain a new session.
     */
    {
        log.warn("Starting new ZK connection");
        final ZooKeeper zk2 = new ZooKeeper(hosts, requestedSessionTimeout, new Watcher() {

            @Override
            public void process(WatchedEvent event) {
                log.warn(event);
            }
        });

        assertTrue(zk2.getState().isAlive());

    }

}

From source file:com.blackberry.logdriver.locks.LockUtil.java

License:Apache License

private static ZooKeeper getClient(String zkConnectString) throws IOException {
    ZooKeeper zk = new ZooKeeper(zkConnectString, SESSION_TIMEOUT, new Watcher() {
        @Override/* ww  w .ja va 2  s. co  m*/
        public void process(WatchedEvent event) {
        }
    });
    return zk;
}

From source file:com.blackberry.logdriver.locks.LockUtil.java

License:Apache License

public void acquireReadLock(String lockPath) throws Exception {
    final SynchronousQueue<Byte> gate = new SynchronousQueue<Byte>();

    LOG.info("Getting read lock on {}", lockPath);

    // There is a possibility here that the node we're working on will be
    // deleting while we try all this. So catch any NoNode exceptions and retry
    // if that happens.
    while (true) {
        try {/*from   w  w w  .  j  a  v  a 2s  .  co  m*/
            // Ensure the parent exists
            ensureNodeExists(lockPath);

            String node = null;

            // Do we already have a node?
            LOG.debug("Checking for an existing lock");
            Stat stat = new Stat();
            for (String child : zk.getChildren(lockPath, false)) {
                if (!child.startsWith("read-")) {
                    LOG.debug("  {} does not start with read-", child);
                    continue;
                }

                // Sometimes someone else will delete their node while I'm searching
                // through them for mine. That's okay!
                try {
                    zk.getData(lockPath + "/" + child, false, stat);
                } catch (KeeperException.NoNodeException e) {
                    LOG.debug("Node was deleted before I could check if I own it: {}", child, e);
                    continue;
                }

                if (zk.getSessionId() == stat.getEphemeralOwner()) {
                    LOG.debug("  {} is owned by me!", child);
                    node = lockPath + "/" + child;
                    break;
                }
            }

            // Create a sequential node under the parent
            if (node == null) {
                LOG.debug("Creating a new node");
                node = zk.create(lockPath + "/read-", new byte[0], Ids.OPEN_ACL_UNSAFE,
                        CreateMode.EPHEMERAL_SEQUENTIAL);
            }

            List<String> children;

            // The node number is 10 digits at the end of the node name
            String nodeNumber = node.substring(node.length() - 10);
            String previousNode = null;
            String previousNodeNumber = null;
            String childNodeNumber = null;

            while (true) {
                previousNode = null;
                children = zk.getChildren(lockPath, false);
                LOG.debug("Children = {}", children);

                for (String child : children) {
                    // Skip anything that is not a write lock.
                    if (!child.startsWith("write-")) {
                        continue;
                    }

                    // So get the number, and if it's less, then wait on it. Otherwise,
                    // we
                    // have the lock.
                    childNodeNumber = child.substring(child.length() - 10);
                    if (nodeNumber.compareTo(childNodeNumber) > 0) {
                        // This child comes before me.
                        if (previousNode == null) {
                            previousNode = child;
                            previousNodeNumber = childNodeNumber;
                        } else if (previousNodeNumber.compareTo(childNodeNumber) < 0) {
                            previousNode = child;
                            previousNodeNumber = childNodeNumber;
                        }
                    }
                    LOG.debug("Previous node={}", previousNode);
                }

                Watcher watcher = new Watcher() {
                    @Override
                    public void process(WatchedEvent event) {
                        try {
                            gate.put((byte) 0);
                        } catch (InterruptedException e) {
                            // If this happens, this method will never return.
                        }
                    }
                };

                if (previousNode == null) {
                    // No previous node? We have the lock!
                    LOG.debug("No previous node - got lock");
                    break;
                }
                stat = zk.exists(lockPath + "/" + previousNode, watcher);
                if (stat == null) {
                    continue;
                }

                // wait for the watcher to get news
                gate.take();
            }
        } catch (KeeperException.NoNodeException e) {
            LOG.warn("Node was deleted while trying to acquire lock.  Retrying.");
            continue;
        }
        break;
    }

    LOG.info("Got read lock on {}", lockPath);
}

From source file:com.blackberry.logdriver.locks.LockUtil.java

License:Apache License

public void acquireWriteLock(String lockPath) throws Exception {
    final SynchronousQueue<Byte> gate = new SynchronousQueue<Byte>();

    LOG.info("Getting write lock on {}", lockPath);

    // There is a possibility here that the node we're working on will be
    // deleting while we try all this. So catch any NoNode exceptions and retry
    // if that happens.
    while (true) {
        try {// www  .ja  v  a  2s  .  co  m
            // Ensure the parent exists
            ensureNodeExists(lockPath);

            String node = null;

            // Do we already have a node?
            LOG.debug("Checking for an existing lock");
            Stat stat = new Stat();
            for (String child : zk.getChildren(lockPath, false)) {
                if (!child.startsWith("write-")) {
                    LOG.debug("  {} does not start with write-", child);
                    continue;
                }

                // Sometimes someone else will delete their node while I'm searching
                // through them for mine. That's okay!
                try {
                    zk.getData(lockPath + "/" + child, false, stat);
                } catch (KeeperException.NoNodeException e) {
                    LOG.debug("Node was deleted before I could check if I own it: {}", child, e);
                    continue;
                }

                if (zk.getSessionId() == stat.getEphemeralOwner()) {
                    LOG.debug("  {} is owned by me!", child);
                    node = lockPath + "/" + child;
                    break;
                }
            }

            // Create a sequential node under the parent
            if (node == null) {
                LOG.debug("Creating a new node");
                node = zk.create(lockPath + "/write-", new byte[0], Ids.OPEN_ACL_UNSAFE,
                        CreateMode.EPHEMERAL_SEQUENTIAL);
            }

            List<String> children;

            // The node number is 10 digits at the end of the node name
            String nodeNumber = node.substring(node.length() - 10);
            String previousNode = null;
            String previousNodeNumber = null;
            String childNodeNumber = null;

            while (true) {
                previousNode = null;
                children = zk.getChildren(lockPath, false);
                LOG.debug("Children = {}", children);

                for (String child : children) {
                    // So get the number, and if it's less, then wait on it. Otherwise,
                    // we
                    // have the lock.
                    childNodeNumber = child.substring(child.length() - 10);
                    if (nodeNumber.compareTo(childNodeNumber) > 0) {
                        // This child comes before me.
                        if (previousNode == null) {
                            previousNode = child;
                            previousNodeNumber = childNodeNumber;
                        } else if (previousNodeNumber.compareTo(childNodeNumber) < 0) {
                            previousNode = child;
                            previousNodeNumber = childNodeNumber;
                        }
                    }
                    LOG.debug("Previous node={}", previousNode);
                }

                Watcher watcher = new Watcher() {
                    @Override
                    public void process(WatchedEvent event) {
                        try {
                            gate.put((byte) 0);
                        } catch (InterruptedException e) {
                            // If this happens, this method will never return.
                        }
                    }
                };

                if (previousNode == null) {
                    // No previous node? We have the lock!
                    LOG.debug("No previous node - got lock");
                    break;
                }
                stat = zk.exists(lockPath + "/" + previousNode, watcher);
                if (stat == null) {
                    continue;
                }

                // wait for the watcher to get news
                gate.take();
            }
        } catch (KeeperException.NoNodeException e) {
            LOG.warn("Node was deleted while trying to acquire lock.  Retrying.");
            continue;
        }
        break;
    }

    LOG.info("Got write lock on {}", lockPath);
}

From source file:com.bloomreach.bstore.highavailability.zookeeper.ZKConnectionManager.java

License:Apache License

/**
 * Attempts to randomly connect to a zookeeper node in an ensemble
 * with a maximum of 3 retries.//from w ww.j  ava 2 s  . c o  m
 *
 * @param host
 * @return
 */
public static ZooKeeper connectToZookeeper(final String host) {

    Callable<ZooKeeper> callable = new Callable<ZooKeeper>() {
        String[] hosts = host.split(",");
        Random r = new Random();
        final String randomZkHost = hosts[r.nextInt(hosts.length)];

        public ZooKeeper call() throws Exception {
            //Make a synchronized connect to ZooKeeper
            ZooKeeper zk = new ZooKeeper(randomZkHost, 120000, new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    if (event.getState() == Watcher.Event.KeeperState.SyncConnected) {
                        connectedSignal.countDown();
                    }
                }
            });
            return zk;
        }
    };

    ZooKeeper zk = null;
    Retryer<ZooKeeper> retryer = RetryerBuilder.<ZooKeeper>newBuilder()
            .retryIfResult(Predicates.<ZooKeeper>isNull()).retryIfExceptionOfType(Exception.class)
            .retryIfRuntimeException().withStopStrategy(StopStrategies.stopAfterAttempt(3)).build();
    try {
        zk = retryer.call(callable);
    } catch (RetryException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
    return zk;
}

From source file:com.bloomreach.zk.replicate.ZKConnectionManager.java

License:Apache License

public static ZooKeeper connectToZookeeper(final String host) {

    Callable<ZooKeeper> callable = new Callable<ZooKeeper>() {
        ArrayList<String> hostLists = new ArrayList(Arrays.asList(host.split(",")));

        public ZooKeeper call() throws Exception {
            while (hostLists.size() > 0) {
                Random r = new Random();
                int tempHostPosition = r.nextInt(hostLists.size());
                final String randomZkHost = hostLists.get(tempHostPosition);
                try {
                    // Make a synchronized connect to ZooKeeper
                    ZooKeeper zk = new ZooKeeper(randomZkHost, 120000, new Watcher() {
                        @Override
                        public void process(WatchedEvent event) {
                            if (event.getState() == Watcher.Event.KeeperState.SyncConnected) {
                                connectedSignal.countDown();
                            }//from   w ww .ja v a2  s  . c o  m
                        }
                    });
                    connectedSignal.await(1L, TimeUnit.SECONDS);
                    //Check if the zk connection is good by fetching files
                    zk.getData("/zookeeper", null, null);
                    return zk;
                } catch (Exception e) {
                    hostLists.remove(tempHostPosition);
                }
            }
            return null;
        }
    };

    ZooKeeper zk = null;
    Retryer<ZooKeeper> retryer = RetryerBuilder.<ZooKeeper>newBuilder()
            .retryIfResult(Predicates.<ZooKeeper>isNull()).retryIfExceptionOfType(Exception.class)
            .retryIfRuntimeException().withStopStrategy(StopStrategies.stopAfterAttempt(3)).build();
    try {
        zk = retryer.call(callable);
    } catch (RetryException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
    return zk;
}

From source file:com.boundary.zoocreeper.CommonOptions.java

License:Apache License

/**
 * Creates a connection to ZooKeeper (waiting for the connection to be made).
 * @param logger Logger used for informational messages.
 * @return A ZooKeeper client (in SyncConnected state).
 * @throws IOException If the connection couldn't be made.
 * @throws InterruptedException If interrupted while waiting for connection to be made.
 */// w  ww. j a  v  a  2s.c om
public ZooKeeper createZooKeeper(Logger logger) throws IOException, InterruptedException {
    final CountDownLatch connected = new CountDownLatch(1);
    logger.info("Connecting to ZooKeeper: {}", zkConnect);
    final ZooKeeper zk = new ZooKeeper(zkConnect, Ints.checkedCast(zkSessionTimeoutMs), new Watcher() {
        @Override
        public void process(WatchedEvent event) {
            if (event.getState() == Event.KeeperState.SyncConnected) {
                connected.countDown();
            }
        }
    });
    try {
        if (!connected.await(zkConnectTimeoutMs, TimeUnit.MILLISECONDS)) {
            throw new IOException("Timeout out connecting to: " + zkConnect);
        }
        logger.info("Connected");
        return zk;
    } catch (InterruptedException e) {
        try {
            zk.close();
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        throw e;
    }
}

From source file:com.cc.zk.common.ZkStateReader.java

License:Apache License

/**
 * TODO ??/*from w ww  . ja va  2 s  . co m*/
 * @throws KeeperException
 * @throws InterruptedException
 */
public void getRemoteLiveNodes() throws KeeperException, InterruptedException {
    List<String> nodes = zkClient.getChildren(ZkStateReader.LIVE_NODES_ZKNODE, new Watcher() {

        @Override
        public void process(WatchedEvent event) {
            // session events are not change events,
            // and do not remove the watcher
            if (EventType.None.equals(event.getType())) {
                return;
            }
            try {
                System.out.println("ZkStateReader.getLiveNodes().new Watcher() {...}.process()----------");
                synchronized (ZkStateReader.this.getUpdateLock()) {
                    List<String> nodes = zkClient.getChildren(LIVE_NODES_ZKNODE, this, true);

                    ZkStateReader.this.liveNodes.addAll(nodes);

                }
            } catch (KeeperException e) {
                if (e.code() == KeeperException.Code.SESSIONEXPIRED
                        || e.code() == KeeperException.Code.CONNECTIONLOSS) {
                    log.warn("ZooKeeper watch triggered, but Solr cannot talk to ZK");
                    return;
                }
                log.error("", e);
                throw new ZooKeeperException(CeException.ErrorCode.SERVER_ERROR, "", e);
            } catch (InterruptedException e) {
                // Restore the interrupted status
                Thread.currentThread().interrupt();
                log.warn("", e);
                return;
            }
        }

    }, true);

    ZkStateReader.this.liveNodes.addAll(nodes);

}

From source file:com.cloudera.flume.master.TestZKBackedConfigStore.java

License:Apache License

/**
 * This test creates a zkcs and then hijacks its session through another
 * client. Then we try to use the zkcs to make sure that it's reconnected
 * correctly./*ww  w.j  a  v  a  2s .  c om*/
 */
@Test
@Ignore("Timing issue prevents this succeeding on Hudson")
public void testLostSessionOK() throws IOException, InterruptedException, KeeperException {
    File tmp = FileUtil.mktempdir();
    FlumeConfiguration cfg = FlumeConfiguration.createTestableConfiguration();
    cfg.set(FlumeConfiguration.MASTER_ZK_LOGDIR, tmp.getAbsolutePath());
    cfg.set(FlumeConfiguration.MASTER_ZK_SERVERS, "localhost:2181:3181:4181");
    cfg.setInt(FlumeConfiguration.MASTER_SERVER_ID, 0);

    ZooKeeperService zk = new ZooKeeperService();
    zk.init(cfg);

    ZooKeeperConfigStore store = new ZooKeeperConfigStore(zk);
    store.init();
    String defaultFlowName = cfg.getDefaultFlowName();
    store.setConfig("foo", defaultFlowName, "bar", "baz");
    long sessionid = store.client.zk.getSessionId();
    byte[] sessionpass = store.client.zk.getSessionPasswd();

    // Force session expiration
    Watcher watcher = new Watcher() {

        @Override
        public void process(WatchedEvent event) {
        }

    };
    ZooKeeper zkClient = new ZooKeeper("localhost:2181", 1000, watcher, sessionid, sessionpass);
    zkClient.close();

    ZKClient updatingClient = new ZKClient("localhost:2181");
    updatingClient.init();
    Stat stat = new Stat();

    store.client.getChildren("/flume-cfgs", false);

    byte[] bytes = updatingClient.getData("/flume-cfgs/cfg-0000000000", false, stat);

    String badCfg = new String(bytes) + "\n1,1,default-flow@@bur : null | null;";

    // Force a cfg into ZK to be reloaded by the (hopefully functioning) store
    updatingClient.create("/flume-cfgs/cfg-", badCfg.getBytes(), Ids.OPEN_ACL_UNSAFE,
            CreateMode.PERSISTENT_SEQUENTIAL);

    assertTrue(store.client.zk.getSessionId() != sessionid);

    // This sleep is ugly, but we have to wait for the watch to fire
    Clock.sleep(2000);

    assertEquals("null", store.getConfig("bur").getSinkConfig());
}