-
Notifications
You must be signed in to change notification settings - Fork 7.3k
ZOOKEEPER-4689: Fix inaccessible node due to inconsistent ACL index after SNAP sync #1997
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -446,21 +446,25 @@ public void createNode(final String path, byte[] data, List<ACL> acl, long ephem | |
| throw new NoNodeException(); | ||
| } | ||
| synchronized (parent) { | ||
| // Add the ACL to ACL cache first, to avoid the ACL not being | ||
| // created race condition during fuzzy snapshot sync. | ||
| // | ||
| // This is the simplest fix, which may add ACL reference count | ||
| // again if it's already counted in the ACL map of fuzzy | ||
| // snapshot, which might also happen for deleteNode txn, but | ||
| // at least it won't cause the ACL not exist issue. | ||
| // | ||
| // Later we can audit and delete all non-referenced ACLs from | ||
| // ACL map when loading the snapshot/txns from disk, like what | ||
| // we did for the global sessions. | ||
| Long acls = aclCache.convertAcls(acl); | ||
|
|
||
| Set<String> children = parent.getChildren(); | ||
| if (children.contains(childName)) { | ||
| DataNode child = nodes.get(path); | ||
| if (child == null) { | ||
| LOG.error("Parent claims child exists but it does not: " + path); | ||
| } else { | ||
| synchronized (child) { | ||
| // Due to fuzzy snapshot, it's possible that a node | ||
| // exists but its ACL is missing in the cache. This is | ||
| // because they serialized ACL cache before node is | ||
| // created but serialized nodes after creation. In this | ||
| // case, we'll replay node creation transaction. We | ||
| // should add it to cache and reset the ACL if the | ||
| // previous longval does not exist. | ||
| if (!aclCache.isLongCached(child.acl)) { | ||
| child.acl = aclCache.convertAcls(acl); | ||
| } | ||
| } | ||
| } | ||
| throw new NodeExistsException(); | ||
| } | ||
|
|
||
|
|
@@ -478,6 +482,7 @@ public void createNode(final String path, byte[] data, List<ACL> acl, long ephem | |
| parent.stat.setCversion(parentCVersion); | ||
| parent.stat.setPzxid(zxid); | ||
| } | ||
| Long acls = aclCache.convertAcls(acl); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given this patch, how bug#1 could happen ?
step#3 creates a new node with existing ACL, so that ACL will get ref count incremented. step#4 will not delete ACL 6. |
||
| DataNode child = new DataNode(data, acls, stat); | ||
| parent.addChild(childName); | ||
| nodes.postChange(parentName, parent); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -95,6 +95,19 @@ public synchronized List<ACL> convertLong(Long longVal) { | |||||||||||||
| return acls; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| /** | ||||||||||||||
| * checks if longval is cached (convertLong can convert it to ACLs). | ||||||||||||||
| * | ||||||||||||||
| * @param longVal | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. EmptyBlockTag: A block tag (@param, @return, @throws, @deprecated) has an empty description. Block tags without descriptions don't add much value for future readers of the code; consider removing the tag entirely or adding a description.
Suggested change
ℹ️ Expand to see all @sonatype-lift commandsYou can reply with the following commands. For example, reply with @sonatype-lift ignoreall to leave out all findings.
Note: When talking to LiftBot, you need to refresh the page to see its response. Help us improve LIFT! (Sonatype LiftBot external survey) Was this a good recommendation for you? Answering this survey will not impact your Lift settings. [ 🙁 Not relevant ] - [ 😕 Won't fix ] - [ 😑 Not critical, will fix ] - [ 🙂 Critical, will fix ] - [ 😊 Critical, fixing now ] |
||||||||||||||
| * @return true if it's cached. | ||||||||||||||
| */ | ||||||||||||||
| public synchronized boolean isLongCached(long longVal) { | ||||||||||||||
| if (longVal == OPEN_UNSAFE_ACL_ID) { | ||||||||||||||
| return true; | ||||||||||||||
| } | ||||||||||||||
| return longKeyMap.containsKey(longVal); | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. THREAD_SAFETY_VIOLATION: Read/Write race. Non-private method ℹ️ Expand to see all @sonatype-lift commandsYou can reply with the following commands. For example, reply with @sonatype-lift ignoreall to leave out all findings.
Note: When talking to LiftBot, you need to refresh the page to see its response. Help us improve LIFT! (Sonatype LiftBot external survey) Was this a good recommendation for you? Answering this survey will not impact your Lift settings. [ 🙁 Not relevant ] - [ 😕 Won't fix ] - [ 😑 Not critical, will fix ] - [ 🙂 Critical, will fix ] - [ 😊 Critical, fixing now ] |
||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| private long incrementIndex() { | ||||||||||||||
| return ++aclIndex; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the cause to bug#2 in this patch ?