2021SC@SDUSC
我们接着上一篇继续分析AclEnforcement类。
代码分析
verifyParentWithTopoChildrenDeleteDead()方法
首先该方法传入的参数有:
CuratorFramework zk :zookeeper的客户端框架
ACL superUserAcl:用户权限
String path:路径
Map<String, Id> topoToZkCreds:id
boolean fixUp: 如果要修复则传入的fixUp为true,否的话为false
private static void verifyParentWithTopoChildrenDeleteDead(CuratorFramework zk, ACL superUserAcl, String path,
Map<String, Id> topoToZkCreds, boolean fixUp,int perms) throws Exception {
if (zk.checkExists().forPath(path) != null) {
verifyAclStrict(zk, Arrays.asList(superUserAcl), path, fixUp);
//可能是坏节点的id的集合
Set<String> possiblyBadIds = new HashSet<>();
//通过一个for循环来将坏节点的id加入集合中
for (String topoId : zk.getChildren().forPath(path)) {
String childPath = path + ClusterUtils.ZK_SEPERATOR + topoId;
if (!topoToZkCreds.containsKey(topoId)) {
//topoToZkCreds中不存在topoId键值
possiblyBadIds.add(topoId);
} else {
List<ACL> rwAcl = getTopoAcl(path, topoId, topoToZkCreds, superUserAcl, fixUp, perms);
verifyAclStrictRecursive(zk, rwAcl, childPath, fixUp);
}
}
1、首先zk.checkExists().forPath(path)判断是否存在该节点。
如果该节点存在,则调用verifyAclStrict()方法,验证该节点的acl权限。
2、通过一个for循环将坏节点的id加入到一个集合中,topoToZkCreds.containsKey(topoId)如果在topoToZkCreds中不存在topoId键值,则将他的id加入集合。存在的话就获取acl权限,然后通过verifyAclStrictRecursive()方法校验acl严格递归。
if (!possiblyBadIds.isEmpty()) {
//Lets reread the children in STORMS as the source of truth and see if a new one was created in the background
possiblyBadIds.removeAll(zk.getChildren().forPath(ClusterUtils.STORMS_SUBTREE));
for (String topoId : possiblyBadIds) {
//Now we know for sure that this is a bad id
String childPath = path + ClusterUtils.ZK_SEPERATOR + topoId;
zk.delete().deletingChildrenIfNeeded().forPath(childPath);
}
}
}
}
3、如果possiblyBadIds集合为空,就重新查看一边子节点,看看是否在背景中创建了一个新的。
4、移除符合zk.getChildren().forPath(ClusterUtils.STORMS_SUBTREE)的子节点的id。通过for循环遍历集合中剩下的id,然后删除childPath路径的节点。
各种校验方法
private static void verifyParentWithTopoChildren(CuratorFramework zk, ACL superUserAcl, String path,
Map<String, Id> topoToZkCreds, boolean fixUp, int perms) throws Exception {
if (zk.checkExists().forPath(path) != null) {
verifyAclStrict(zk, Arrays.asList(superUserAcl), path, fixUp);
for (String topoId : zk.getChildren().forPath(path)) {
String childPath = path + ClusterUtils.ZK_SEPERATOR + topoId;
List<ACL> rwAcl = getTopoAcl(path, topoId, topoToZkCreds, superUserAcl, fixUp, perms);
verifyAclStrictRecursive(zk, rwAcl, childPath, fixUp);
}
}
}
👆校验有子节点的父节点。
private static void verifyParentWithReadOnlyTopoChildren(CuratorFramework zk, ACL superUserAcl, String path,
Map<String, Id> topoToZkCreds, boolean fixUp) throws Exception {
verifyParentWithTopoChildren(zk, superUserAcl, path, topoToZkCreds, fixUp, ZooDefs.Perms.READ);
}
private static void verifyParentWithReadWriteTopoChildren(CuratorFramework zk, ACL superUserAcl, String path,
Map<String, Id> topoToZkCreds, boolean fixUp) throws Exception {
verifyParentWithTopoChildren(zk, superUserAcl, path, topoToZkCreds, fixUp, ZooDefs.Perms.ALL);
}
👆校验只读的子节点的父子点。
👆校验有读写的子节点的父节点。
private static void verifyAclStrictRecursive(CuratorFramework zk, List<ACL> strictAcl, String path, boolean fixUp) throws Exception {
verifyAclStrict(zk, strictAcl, path, fixUp);
for (String child : zk.getChildren().forPath(path)) {
String newPath = path + ClusterUtils.ZK_SEPERATOR + child;
verifyAclStrictRecursive(zk, strictAcl, newPath, fixUp);
}
}
👆递归校验acl。
private static void verifyAclStrict(CuratorFramework zk, List<ACL> strictAcl, String path, boolean fixUp) throws Exception {
try {
List<ACL> foundAcl = zk.getACL().forPath(path);
if (!equivalent(foundAcl, strictAcl)) {
if (fixUp) {
LOG.warn("{} expected to have ACL {}, but has {}. Fixing...", path, strictAcl, foundAcl);
zk.setACL().withACL(strictAcl).forPath(path);
} else {
throw new IllegalStateException(path + " did not have the correct ACL found " + foundAcl + " expected " + strictAcl);
}
}
} catch (KeeperException.NoNodeException ne) {
LOG.debug("{} removed in the middle of checking it", ne);
}
}
👆校验acl。
private static boolean equivalent(List<ACL> a, List<ACL> b) {
if (a.size() == b.size()) {
for (ACL acl : a) {
if (!b.contains(acl)) {
return false;
}
}
return true;
}
return false;
}
👆判断两个acl权限列表是否相等。
到这里AclEnforcement类就结束了。