@Override
 public Set<NodeId> getAvailableNodes(NodeType type) {
   Set<NodeId> result = Sets.newHashSet();
   ZNode typeNode = rootNode.child(CoordinationUtil.nodeNameOf(type));
   for (ZNode node : typeNode.children()) {
     if (node.hasChild(CoordinationUtil.AVAILABLE_NODE_NAME)) {
       result.add(NodeId.of(type, node.getShortPath()));
     }
   }
   return result;
 }
  @Override
  public boolean canExecuteCommands(NodeId nodeId, Set<Qualifier<?>> qualifiers) {
    ZNode typeNode = rootNode.child(CoordinationUtil.nodeNameOf(nodeId.getType()));
    String identifier = nodeId.getIdentifier();
    if (!typeNode.hasChild(identifier)) {
      throw new CoordinatorException("Node with id " + nodeId + " is not found");
    }

    ZNode node = typeNode.child(identifier);

    if (!node.hasChild(CoordinationUtil.AVAILABLE_NODE_NAME)) {
      return false;
    }
    for (Qualifier<?> qualifier : qualifiers) {
      if (!node.hasChild(nodeNameOf(qualifier))) {
        return false;
      }
    }
    return true;
  }
  @Override
  public void waitForInitialization() {
    log.info("Waiting for coordination znode structure structure initialization");
    while (true) {
      boolean initialized =
          rootNode.exists() && rootNode.hasChild(CoordinationUtil.STATUSES_NODE_NAME);

      if (initialized) {
        log.info("Coordination znode structure initialized");
        break;
      }

      try {
        Thread.sleep(INITIALIZATION_SLEEP_PERIOD);
        log.info("Znode structure is not initialized. Waiting {} ms", INITIALIZATION_SLEEP_PERIOD);
      } catch (InterruptedException e) {
        log.warn("Sleep interrupted", e);
      }
    }
  }