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

jt2594838 pushed a commit to branch dev/1.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/dev/1.3 by this push:
     new 4bc6ba6ff2b Fix stale space quota usage update on DataNode (#18668)
4bc6ba6ff2b is described below

commit 4bc6ba6ff2b9e24cdc5565e176ea19bf47b9c21f
Author: Caideyipi <[email protected]>
AuthorDate: Thu Sep 17 18:40:06 2026 +0800

    Fix stale space quota usage update on DataNode (#18668)
---
 .../rescon/quotas/DataNodeSpaceQuotaManager.java   | 26 ++++++-----
 .../quotas/DataNodeSpaceQuotaManagerTest.java      | 50 ++++++++++++++++++++++
 2 files changed, 65 insertions(+), 11 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/quotas/DataNodeSpaceQuotaManager.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/quotas/DataNodeSpaceQuotaManager.java
index c448febf3b7..ea6d576ac3d 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/quotas/DataNodeSpaceQuotaManager.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/quotas/DataNodeSpaceQuotaManager.java
@@ -31,29 +31,31 @@ import org.apache.iotdb.rpc.TSStatusCode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 public class DataNodeSpaceQuotaManager {
 
   private static final Logger LOGGER = 
LoggerFactory.getLogger(DataNodeSpaceQuotaManager.class);
 
-  private Map<String, TSpaceQuota> spaceQuotaLimit;
-  private Map<String, TSpaceQuota> spaceQuotaUsage;
+  private ConcurrentMap<String, TSpaceQuota> spaceQuotaLimit;
+  private ConcurrentMap<String, TSpaceQuota> spaceQuotaUsage;
   private DataNodeSizeStore dataNodeSizeStore;
 
   public DataNodeSpaceQuotaManager() {
-    spaceQuotaLimit = new HashMap<>();
-    spaceQuotaUsage = new HashMap<>();
+    spaceQuotaLimit = new ConcurrentHashMap<>();
+    spaceQuotaUsage = new ConcurrentHashMap<>();
     dataNodeSizeStore = new DataNodeSizeStore();
     recover();
   }
 
   public DataNodeSpaceQuotaManager(
       Map<String, TSpaceQuota> spaceQuotaLimit, Map<String, TSpaceQuota> 
spaceQuotaUsage) {
-    this.spaceQuotaLimit = spaceQuotaLimit;
-    this.spaceQuotaUsage = spaceQuotaUsage;
+    this.spaceQuotaLimit = new ConcurrentHashMap<>(spaceQuotaLimit);
+    this.spaceQuotaUsage = new ConcurrentHashMap<>(spaceQuotaUsage);
   }
 
   /** SingleTon */
@@ -69,8 +71,8 @@ public class DataNodeSpaceQuotaManager {
 
   public TSStatus setSpaceQuota(TSetSpaceQuotaReq req) {
     for (String database : req.getDatabase()) {
-      spaceQuotaLimit.put(database, req.getSpaceLimit());
       spaceQuotaUsage.put(database, new TSpaceQuota());
+      spaceQuotaLimit.put(database, req.getSpaceLimit());
     }
     return RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS);
   }
@@ -81,8 +83,8 @@ public class DataNodeSpaceQuotaManager {
       if (spaceQuota.getStatus().getCode() == 
TSStatusCode.SUCCESS_STATUS.getStatusCode()
           && spaceQuota.getSpaceQuota() != null) {
         for (String database : spaceQuota.getSpaceQuota().keySet()) {
-          spaceQuotaLimit.put(database, 
spaceQuota.getSpaceQuota().get(database));
           spaceQuotaUsage.put(database, new TSpaceQuota());
+          spaceQuotaLimit.put(database, 
spaceQuota.getSpaceQuota().get(database));
         }
       }
       LOGGER.info("Space quota limit restored succeeded. " + 
spaceQuotaLimit.toString());
@@ -107,7 +109,9 @@ public class DataNodeSpaceQuotaManager {
   }
 
   public void updateSpaceQuotaUsage(Map<String, TSpaceQuota> spaceQuotaUsage) {
-    this.spaceQuotaUsage = spaceQuotaUsage;
+    if (Objects.nonNull(spaceQuotaUsage)) {
+      this.spaceQuotaUsage.putAll(spaceQuotaUsage);
+    }
   }
 
   public boolean checkTimeSeriesNum(String database) {
@@ -148,6 +152,6 @@ public class DataNodeSpaceQuotaManager {
   }
 
   public void setSpaceQuotaLimit(Map<String, TSpaceQuota> spaceQuotaLimit) {
-    this.spaceQuotaLimit = spaceQuotaLimit;
+    this.spaceQuotaLimit = new ConcurrentHashMap<>(spaceQuotaLimit);
   }
 }
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/rescon/quotas/DataNodeSpaceQuotaManagerTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/rescon/quotas/DataNodeSpaceQuotaManagerTest.java
new file mode 100644
index 00000000000..5965107e064
--- /dev/null
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/rescon/quotas/DataNodeSpaceQuotaManagerTest.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.storageengine.rescon.quotas;
+
+import org.apache.iotdb.common.rpc.thrift.TSetSpaceQuotaReq;
+import org.apache.iotdb.common.rpc.thrift.TSpaceQuota;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+
+public class DataNodeSpaceQuotaManagerTest {
+
+  @Test
+  public void testSpaceQuotaUsageUpdatePreservesNewDatabase() {
+    final DataNodeSpaceQuotaManager quotaManager =
+        new DataNodeSpaceQuotaManager(new HashMap<>(), new HashMap<>());
+    final TSpaceQuota spaceQuota = new TSpaceQuota();
+    spaceQuota.setDeviceNum(2);
+    spaceQuota.setTimeserieNum(0);
+    spaceQuota.setDiskSize(0);
+    final TSetSpaceQuotaReq request = new TSetSpaceQuotaReq();
+    request.setDatabase(Collections.singletonList("root.sg1"));
+    request.setSpaceLimit(spaceQuota);
+
+    quotaManager.setSpaceQuota(request);
+    quotaManager.updateSpaceQuotaUsage(Collections.singletonMap("root.sg0", 
new TSpaceQuota()));
+
+    Assert.assertTrue(quotaManager.checkDeviceLimit("sg1"));
+  }
+}

Reply via email to