public void initialTree(String subtree, int depth, Set<ZkStateListener> receivers) throws InterruptedException {
        if (depth <= 0) return;
        if (subtree == null) subtree = "/";

        ZNodeState zNodeState = retrieveOrCreateZNodeState(subtree);
        zNodeState.acquire();
        Set<String> currentChildNames = new HashSet<String>();
        try {
            final List<String> children = zk.getChildren(subtree, true);

            for (String child : children) {
                currentChildNames.add(child);
            }
            zNodeState.setChildren(currentChildNames);
        } catch (KeeperException e) {
            // znode has gone away
            znodeStateCache.remove(subtree);
        } finally {
            zNodeState.release();
        }
        
        for (String child : currentChildNames) {
            final String childFQPath = subtree.equals("/") ? ("/" + child) : (subtree + "/" + child);
            Stat childStat;
            try {
                childStat = zk.exists(childFQPath, true);
            } catch (KeeperException e) {
                e.printStackTrace();
                continue;
            }
            propagateToListeners(new ZNodeMessage(childFQPath, ZNodeMessage.Type.U, childStat), receivers);
            initialTree(childFQPath, depth - 1, receivers);
        }
    }