|
@@ -346,8 +346,13 @@ public class ActiveStandbyElector implements StatCallback, StringCallback {
|
|
|
createWithRetries(prefixPath, new byte[]{}, zkAcl, CreateMode.PERSISTENT);
|
|
|
} catch (KeeperException e) {
|
|
|
if (isNodeExists(e.code())) {
|
|
|
- // This is OK - just ensuring existence.
|
|
|
- continue;
|
|
|
+ // Set ACLs for parent node, if they do not exist or are different
|
|
|
+ try {
|
|
|
+ setAclsWithRetries(prefixPath);
|
|
|
+ } catch (KeeperException e1) {
|
|
|
+ throw new IOException("Couldn't set ACLs on parent ZNode: " +
|
|
|
+ prefixPath, e1);
|
|
|
+ }
|
|
|
} else {
|
|
|
throw new IOException("Couldn't create " + prefixPath, e);
|
|
|
}
|
|
@@ -1066,14 +1071,36 @@ public class ActiveStandbyElector implements StatCallback, StringCallback {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ private void setAclsWithRetries(final String path)
|
|
|
+ throws KeeperException, InterruptedException {
|
|
|
+ Stat stat = new Stat();
|
|
|
+ zkDoWithRetries(new ZKAction<Void>() {
|
|
|
+ @Override
|
|
|
+ public Void run() throws KeeperException, InterruptedException {
|
|
|
+ List<ACL> acl = zkClient.getACL(path, stat);
|
|
|
+ if (acl == null || !acl.containsAll(zkAcl) ||
|
|
|
+ !zkAcl.containsAll(acl)) {
|
|
|
+ zkClient.setACL(path, zkAcl, stat.getVersion());
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }, Code.BADVERSION);
|
|
|
+ }
|
|
|
+
|
|
|
private <T> T zkDoWithRetries(ZKAction<T> action) throws KeeperException,
|
|
|
InterruptedException {
|
|
|
+ return zkDoWithRetries(action, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ private <T> T zkDoWithRetries(ZKAction<T> action, Code retryCode)
|
|
|
+ throws KeeperException, InterruptedException {
|
|
|
int retry = 0;
|
|
|
while (true) {
|
|
|
try {
|
|
|
return action.run();
|
|
|
} catch (KeeperException ke) {
|
|
|
- if (shouldRetry(ke.code()) && ++retry < maxRetryNum) {
|
|
|
+ if ((shouldRetry(ke.code()) || shouldRetry(ke.code(), retryCode))
|
|
|
+ && ++retry < maxRetryNum) {
|
|
|
continue;
|
|
|
}
|
|
|
throw ke;
|
|
@@ -1189,6 +1216,10 @@ public class ActiveStandbyElector implements StatCallback, StringCallback {
|
|
|
private static boolean shouldRetry(Code code) {
|
|
|
return code == Code.CONNECTIONLOSS || code == Code.OPERATIONTIMEOUT;
|
|
|
}
|
|
|
+
|
|
|
+ private static boolean shouldRetry(Code code, Code retryIfCode) {
|
|
|
+ return (retryIfCode == null ? false : retryIfCode == code);
|
|
|
+ }
|
|
|
|
|
|
@Override
|
|
|
public String toString() {
|