This is an automated email from the ASF dual-hosted git repository.

CRZbulabula pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 6042c4f909f Fix the issue where `list user` throws an error when 
executed concurrently with `create user`. (#17583)
6042c4f909f is described below

commit 6042c4f909f2be09fe2ce54412e6aafe1df747d7
Author: wenyanshi-123 <[email protected]>
AuthorDate: Wed May 6 10:54:21 2026 +0800

    Fix the issue where `list user` throws an error when executed concurrently 
with `create user`. (#17583)
---
 .../db/auth/user/LocalFileUserManagerTest.java     | 49 ++++++++++++++++++++++
 .../iotdb/commons/auth/role/BasicRoleManager.java  |  6 +--
 2 files changed, 52 insertions(+), 3 deletions(-)

diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/user/LocalFileUserManagerTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/user/LocalFileUserManagerTest.java
index 06fc8ae3e02..3043c4a638a 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/user/LocalFileUserManagerTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/user/LocalFileUserManagerTest.java
@@ -32,8 +32,15 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.io.File;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 public class LocalFileUserManagerTest {
@@ -78,4 +85,46 @@ public class LocalFileUserManagerTest {
     User user = manager.getEntity("testRaw");
     Assert.assertEquals(user.getPassword(), 
AuthUtils.encryptPassword("password1"));
   }
+
+  @Test
+  public void testConcurrentListAndCreateDropUser() throws Exception {
+    AtomicReference<Throwable> error = new AtomicReference<>();
+    AtomicBoolean running = new AtomicBoolean(true);
+    CyclicBarrier barrier = new CyclicBarrier(2);
+    ExecutorService pool = Executors.newFixedThreadPool(2);
+
+    pool.submit(
+        () -> {
+          try {
+            barrier.await();
+            while (running.get()) {
+              manager.listAllEntities();
+              manager.listAllEntitiesInfo();
+            }
+          } catch (Throwable t) {
+            error.compareAndSet(null, t);
+          }
+        });
+
+    pool.submit(
+        () -> {
+          try {
+            barrier.await();
+            for (int i = 0; i < 500; i++) {
+              String name = "user_" + i;
+              manager.createUser(name, "password_" + i, false);
+              manager.deleteEntity(name);
+            }
+          } catch (Throwable t) {
+            error.compareAndSet(null, t);
+          } finally {
+            running.set(false);
+          }
+        });
+
+    pool.shutdown();
+    assertTrue(pool.awaitTermination(30, TimeUnit.SECONDS));
+    assertNull(
+        "ConcurrentModificationException during concurrent list/create/drop 
user", error.get());
+  }
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/role/BasicRoleManager.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/role/BasicRoleManager.java
index f6804d3055c..b5fc900c003 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/role/BasicRoleManager.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/role/BasicRoleManager.java
@@ -36,9 +36,9 @@ import org.slf4j.LoggerFactory;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Comparator;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * This class reads roles from local files through LocalFileRoleAccessor and 
manages them in a hash
@@ -63,12 +63,12 @@ public abstract class BasicRoleManager implements 
IEntityManager, SnapshotProces
   }
 
   protected BasicRoleManager() {
-    this.entityMap = new HashMap<>();
+    this.entityMap = new ConcurrentHashMap<>();
     this.lock = new HashLock();
   }
 
   protected BasicRoleManager(IEntityAccessor accessor) {
-    this.entityMap = new HashMap<>();
+    this.entityMap = new ConcurrentHashMap<>();
     this.accessor = accessor;
     this.lock = new HashLock();
     this.accessor.reset();

Reply via email to