This is an automated email from the ASF dual-hosted git repository.
hexiaoqiao pushed a commit to branch branch-3.3
in repository https://gitbox.apache.org/repos/asf/hadoop.git
The following commit(s) were added to refs/heads/branch-3.3 by this push:
new 78fc23ee5c9f HADOOP-18922. Race condition in ZKDelegationTokenSecretManager creating znode (#6150). Contributed by Kevin Risden. (#6179)
78fc23ee5c9f is described below
commit 78fc23ee5c9ff8d3ad058f72c609901e976d4071
Author: Kevin Risden <ri...@users.noreply.github.com>
AuthorDate: Tue Oct 17 05:33:41 2023 -0400
HADOOP-18922. Race condition in ZKDelegationTokenSecretManager creating znode (#6150). Contributed by Kevin Risden. (#6179)
Signed-off-by: He Xiaoqiao <he...@apache.org>
---
.../delegation/ZKDelegationTokenSecretManager.java | 8 ++--
.../TestZKDelegationTokenSecretManager.java | 55 ++++++++++++++++++++++
2 files changed, 58 insertions(+), 5 deletions(-)
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/ZKDelegationTokenSecretManager.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/ZKDelegationTokenSecretManager.java
index 2731adbf05e2..53d0642643be 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/ZKDelegationTokenSecretManager.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/ZKDelegationTokenSecretManager.java
@@ -59,7 +59,6 @@ import org.apache.zookeeper.ZooDefs.Perms;
import org.apache.zookeeper.client.ZKClientConfig;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
-import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -268,10 +267,9 @@ public abstract class ZKDelegationTokenSecretManager<TokenIdent extends Abstract
CuratorFramework nullNsFw = zkClient.usingNamespace(null);
try {
String nameSpace = "/" + zkClient.getNamespace();
- Stat stat = nullNsFw.checkExists().forPath(nameSpace);
- if (stat == null) {
- nullNsFw.create().creatingParentContainersIfNeeded().forPath(nameSpace);
- }
+ nullNsFw.create().creatingParentContainersIfNeeded().forPath(nameSpace);
+ } catch (KeeperException.NodeExistsException ignore) {
+ // We don't care if the znode already exists
} catch (Exception e) {
throw new IOException("Could not create namespace", e);
}
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/TestZKDelegationTokenSecretManager.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/TestZKDelegationTokenSecretManager.java
index 6dc8c59b25e4..0b0725cea7ee 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/TestZKDelegationTokenSecretManager.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/TestZKDelegationTokenSecretManager.java
@@ -20,8 +20,14 @@ package org.apache.hadoop.security.token.delegation;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
@@ -572,4 +578,53 @@ public class TestZKDelegationTokenSecretManager {
"KeeperErrorCode = NodeExists for "+workingPath,
() -> createModeStat.forPath(workingPath));
}
+
+ @Test
+ public void testMultipleInit() throws Exception {
+
+ String connectString = zkServer.getConnectString();
+ RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
+ Configuration conf = getSecretConf(connectString);
+ CuratorFramework curatorFramework =
+ CuratorFrameworkFactory.builder()
+ .connectString(connectString)
+ .retryPolicy(retryPolicy)
+ .build();
+ curatorFramework.start();
+ ZKDelegationTokenSecretManager.setCurator(curatorFramework);
+
+ DelegationTokenManager tm1 = new DelegationTokenManager(conf, new Text("foo"));
+ DelegationTokenManager tm2 = new DelegationTokenManager(conf, new Text("bar"));
+ // When the init method is called,
+ // the ZKDelegationTokenSecretManager#startThread method will be called,
+ // and the creatingParentContainersIfNeeded will be called to create the nameSpace.
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+
+ Callable<Boolean> tm1Callable = () -> {
+ tm1.init();
+ return true;
+ };
+ Callable<Boolean> tm2Callable = () -> {
+ tm2.init();
+ return true;
+ };
+ List<Future<Boolean>> futures = executorService.invokeAll(
+ Arrays.asList(tm1Callable, tm2Callable));
+ for(Future<Boolean> future : futures) {
+ Assert.assertTrue(future.get());
+ }
+ executorService.shutdownNow();
+ Assert.assertTrue(executorService.awaitTermination(1, TimeUnit.SECONDS));
+ tm1.destroy();
+ tm2.destroy();
+
+ String workingPath = "/" + conf.get(ZKDelegationTokenSecretManager.ZK_DTSM_ZNODE_WORKING_PATH,
+ ZKDelegationTokenSecretManager.ZK_DTSM_ZNODE_WORKING_PATH_DEAFULT) + "/ZKDTSMRoot";
+
+ // Check if the created NameSpace exists.
+ Stat stat = curatorFramework.checkExists().forPath(workingPath);
+ Assert.assertNotNull(stat);
+
+ curatorFramework.close();
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org