private void updateACL(RegionCoprocessorEnvironment e, final Map<byte[], List<Cell>> familyMap) {
    Set<byte[]> entries = new TreeSet<>(Bytes.BYTES_RAWCOMPARATOR);
    for (Map.Entry<byte[], List<Cell>> f : familyMap.entrySet()) {
      List<Cell> cells = f.getValue();
      for (Cell cell : cells) {
        if (CellUtil.matchingFamily(cell, PermissionStorage.ACL_LIST_FAMILY)) {
          entries.add(CellUtil.cloneRow(cell));
        }
      }
    }
    Configuration conf = regionEnv.getConfiguration();
    byte[] currentEntry = null;
    // TODO: Here we are already on the ACL region. (And it is single
    // region) We can even just get the region from the env and do get
    // directly. The short circuit connection would avoid the RPC overhead
    // so no socket communication, req write/read .. But we have the PB
    // to and fro conversion overhead. get req is converted to PB req
    // and results are converted to PB results 1st and then to POJOs
    // again. We could have avoided such at least in ACL table context..
    try (Table t = e.getConnection().getTable(PermissionStorage.ACL_TABLE_NAME)) {
      for (byte[] entry : entries) {
        currentEntry = entry;
        ListMultimap<String, UserPermission> perms =
          PermissionStorage.getPermissions(conf, entry, t, null, null, null, false);
        byte[] serialized = PermissionStorage.writePermissionsAsBytes(perms, conf);
        zkPermissionWatcher.writeToZookeeper(entry, serialized);
      }
    } catch (IOException ex) {
      LOG.error("Failed updating permissions mirror for '"
        + (currentEntry == null ? "null" : Bytes.toString(currentEntry)) + "'", ex);
    }
  }
Writes all table ACLs for the tables in the given Map up into ZooKeeper znodes. This is called
to synchronize ACL changes following {@code _acl_} table updates.
hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java