@Override
  public void nodeChildrenChanged(final String path) {
    waitUntilStarted();
    if (path.equals(aclZNode)) {
      // preempt any existing nodeChildrenChanged event processing
      if (childrenChangedFuture != null && !childrenChangedFuture.isDone()) {
        boolean cancelled = childrenChangedFuture.cancel(true);
        if (!cancelled) {
          // task may have finished between our check and attempted cancel, this is fine.
          if (!childrenChangedFuture.isDone()) {
            LOG.warn("Could not cancel processing node children changed event, "
              + "please file a JIRA and attach logs if possible.");
          }
        }
      }
      childrenChangedFuture = asyncProcessNodeUpdate(() -> {
        try {
          final List<ZKUtil.NodeAndData> nodeList =
            ZKUtil.getChildDataAndWatchForNewChildren(watcher, aclZNode, false);
          refreshNodes(nodeList);
        } catch (KeeperException ke) {
          String msg = "ZooKeeper error while reading node children data for path " + path;
          LOG.error(msg, ke);
          watcher.abort(msg, ke);
        }
      });
    }
  }
Handles synchronization of access control list entries and updates throughout all nodes in the
cluster. The {@link AccessController} instance on the {@code _acl_} table regions, creates a
znode for each table as {@code /hbase/acl/tablename}, with the znode data containing a serialized
list of the permissions granted for the table. The {@code AccessController} instances on all
other cluster hosts watch the znodes for updates, which trigger updates in the
{@link AuthManager} permission cache.
hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/ZKPermissionWatcher.java