private <C extends Command<R>, R extends Serializable> void registerExecutor(
      final NodeContext nodeContext, final CommandExecutor<C, R> executor, ZNode node) {
    final ZNode executorNode =
        node.createChild(znode().withPath(nodeNameOf(executor.getQualifier())));
    final ZNode queueNode = executorNode.createChild(znode().withPath("queue"));
    executorNode.createChild(znode().withPath("result"));

    log.debug("Created znodes for executor {}", executorNode.getPath());

    queueNode.addChildrenWatcher(
        new Watcher() {
          @Override
          public void process(WatchedEvent event) {
            if (event.getType() != Event.EventType.NodeChildrenChanged) {
              return;
            }

            synchronized (lock) {
              if (log.isDebugEnabled()) {
                log.debug(
                    "Children changed {} event type {}", queueNode.getPath(), event.getType());
              }

              List<QueueEntry<C, R>> entries = getEntries(queueNode, this);

              for (final QueueEntry<C, R> entry : entries) {
                Runnable run =
                    new Runnable() {

                      @Override
                      public void run() {
                        executeCommand(executor, executorNode, entry, nodeContext);
                      }
                    };

                ZookeeperCoordinator.this.executor.execute(run);
              }
            }
          }
        });
  }
    @Override
    public void process(WatchedEvent event) {
      if (event.getType() != Event.EventType.NodeChildrenChanged) {
        return;
      }

      Runnable runnable =
          new Runnable() {
            public void run() {
              lock.lock();

              try {
                List<ZNode> children = node.children();
                Collection<NodeId> newIds = Sets.newHashSet();
                for (ZNode child : children) {
                  newIds.add(child.getObject(NodeId.class));
                }

                Collection<NodeId> copy = Sets.newHashSet(newIds);
                newIds.removeAll(currentIds);
                currentIds.removeAll(copy);

                for (NodeId newId : newIds) {
                  statusChangeListener.onNodeStatusChanged(newId, NodeStatus.AVAILABLE);
                }

                for (NodeId newId : currentIds) {
                  statusChangeListener.onNodeStatusChanged(newId, NodeStatus.DISCONNECTED);
                }

                currentIds = copy;
              } finally {
                lock.unlock();
              }
            }
          };

      new Thread(runnable).run();
      node.addChildrenWatcher(this);
    }