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 4bbfa51c3c9 Fix RegionGroup limits for same-name tree and table 
databases (#18990)
4bbfa51c3c9 is described below

commit 4bbfa51c3c92b4b0a8c531fa3f0290a78f00cf1f
Author: d-wang-commit <[email protected]>
AuthorDate: Fri Oct 23 10:38:00 2026 +0800

    Fix RegionGroup limits for same-name tree and table databases (#18990)
    
    Use schema names to retain both models and count every database.
    Preserve audit database filtering and add focused unit coverage.
---
 .../iotdb/confignode/manager/ConfigManager.java    |  4 +-
 .../persistence/schema/ClusterSchemaInfo.java      |  8 +-
 .../manager/ClusterSchemaManagerTest.java          | 90 ++++++++++++++++++++++
 .../manager/ConfigManagerDatabaseDeletionTest.java | 65 ++++++++++++++++
 4 files changed, 163 insertions(+), 4 deletions(-)

diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
index a08b4e87ba1..360a50a24d5 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
@@ -313,6 +313,7 @@ import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
 import static 
org.apache.iotdb.commons.conf.IoTDBConstant.ONE_LEVEL_PATH_WILDCARD;
+import static 
org.apache.iotdb.commons.schema.table.Audit.TABLE_MODEL_AUDIT_DATABASE;
 import static 
org.apache.iotdb.commons.schema.table.Audit.TREE_MODEL_AUDIT_DATABASE;
 
 /** Entry of all management, AssignPartitionManager, AssignRegionManager. */
@@ -826,8 +827,9 @@ public class ConfigManager implements IManager {
               .getMatchedDatabaseSchemasByName(
                   deletedPaths, tDeleteReq.isSetIsTableModel() && 
tDeleteReq.isIsTableModel());
 
-      // remove root.__audit
+      // remove audit databases
       deleteDatabaseSchemaMap.remove(TREE_MODEL_AUDIT_DATABASE);
+      deleteDatabaseSchemaMap.remove(TABLE_MODEL_AUDIT_DATABASE);
 
       if (deleteDatabaseSchemaMap.isEmpty()) {
         return RpcUtils.getStatus(
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java
index c5736dfa4cf..723634cefe0 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java
@@ -607,7 +607,7 @@ public class ClusterSchemaInfo implements SnapshotProcessor 
{
    * Only leader use this interface. Get the matched DatabaseSchemas.
    *
    * @param rawPathList Databases' path patterns or full paths
-   * @return All DatabaseSchemas that matches to the specific Database patterns
+   * @return All matching DatabaseSchemas keyed by their database names
    */
   public Map<String, TDatabaseSchema> getMatchedDatabaseSchemasByName(
       final List<String> rawPathList, final Boolean isTableModel) {
@@ -638,8 +638,10 @@ public class ClusterSchemaInfo implements 
SnapshotProcessor {
       final List<PartialPath> matchedPaths =
           mTree.getMatchedDatabases(patternPath, ALL_MATCH_SCOPE, false);
       for (final PartialPath path : matchedPaths) {
-        schemaMap.put(
-            path.getFullPath(), 
mTree.getDatabaseNodeByPath(path).getAsMNode().getDatabaseSchema());
+        final TDatabaseSchema schema =
+            mTree.getDatabaseNodeByPath(path).getAsMNode().getDatabaseSchema();
+        // Table database "pg" and tree database "root.pg" share the same 
internal path.
+        schemaMap.put(schema.getName(), schema);
       }
     }
   }
diff --git 
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/manager/ClusterSchemaManagerTest.java
 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/manager/ClusterSchemaManagerTest.java
index c63ea9a98d6..b86f62dec5e 100644
--- 
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/manager/ClusterSchemaManagerTest.java
+++ 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/manager/ClusterSchemaManagerTest.java
@@ -18,6 +18,8 @@
  */
 package org.apache.iotdb.confignode.manager;
 
+import org.apache.iotdb.common.rpc.thrift.TConsensusGroupType;
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.exception.table.ColumnInAlterException;
 import org.apache.iotdb.commons.exception.table.ColumnInDeletionException;
 import org.apache.iotdb.commons.exception.table.TableInDeletionException;
@@ -25,13 +27,20 @@ import org.apache.iotdb.commons.schema.table.TsTable;
 import org.apache.iotdb.commons.schema.table.TsTableInternalRPCUtil;
 import org.apache.iotdb.commons.schema.table.column.FieldColumnSchema;
 import org.apache.iotdb.commons.schema.table.column.TsTableColumnSchema;
+import org.apache.iotdb.confignode.conf.ConfigNodeConfig;
+import org.apache.iotdb.confignode.conf.ConfigNodeDescriptor;
 import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlanType;
+import 
org.apache.iotdb.confignode.consensus.request.write.database.AdjustMaxRegionGroupNumPlan;
 import 
org.apache.iotdb.confignode.consensus.request.write.database.DatabaseSchemaPlan;
 import 
org.apache.iotdb.confignode.consensus.request.write.table.CommitCreateTablePlan;
 import 
org.apache.iotdb.confignode.consensus.request.write.table.PreAlterColumnDataTypePlan;
 import 
org.apache.iotdb.confignode.consensus.request.write.table.PreCreateTablePlan;
 import 
org.apache.iotdb.confignode.consensus.request.write.table.PreDeleteColumnPlan;
 import 
org.apache.iotdb.confignode.consensus.request.write.table.PreDeleteTablePlan;
+import org.apache.iotdb.confignode.manager.consensus.ConsensusManager;
+import org.apache.iotdb.confignode.manager.node.NodeManager;
+import org.apache.iotdb.confignode.manager.partition.PartitionManager;
+import 
org.apache.iotdb.confignode.manager.partition.RegionGroupExtensionPolicy;
 import org.apache.iotdb.confignode.manager.schema.ClusterSchemaManager;
 import org.apache.iotdb.confignode.manager.schema.ClusterSchemaQuotaStatistics;
 import org.apache.iotdb.confignode.persistence.schema.ClusterSchemaInfo;
@@ -47,6 +56,7 @@ import org.junit.Test;
 import org.mockito.Mockito;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -70,6 +80,86 @@ public class ClusterSchemaManagerTest {
     Assert.assertEquals(20, ClusterSchemaManager.calcMaxRegionGroupNum(3, 1.0, 
120, 2, 3, 5));
   }
 
+  @Test
+  public void testAdjustMaxRegionGroupNumWithMixedModels() throws Exception {
+    final ConfigNodeConfig conf = ConfigNodeDescriptor.getInstance().getConf();
+    final int originalSchemaQuota = conf.getSchemaRegionPerDataNode();
+    final int originalDataQuota = conf.getDataRegionPerDataNode();
+    final RegionGroupExtensionPolicy originalSchemaPolicy =
+        conf.getSchemaRegionGroupExtensionPolicy();
+    final RegionGroupExtensionPolicy originalDataPolicy = 
conf.getDataRegionGroupExtensionPolicy();
+    try {
+      conf.setSchemaRegionPerDataNode(12);
+      conf.setDataRegionPerDataNode(12);
+      
conf.setSchemaRegionGroupExtensionPolicy(RegionGroupExtensionPolicy.PROACTIVE);
+      
conf.setDataRegionGroupExtensionPolicy(RegionGroupExtensionPolicy.PROACTIVE);
+
+      final ClusterSchemaInfo clusterSchemaInfo = new ClusterSchemaInfo();
+      final IManager configManager = Mockito.mock(IManager.class);
+      final NodeManager nodeManager = Mockito.mock(NodeManager.class);
+      final PartitionManager partitionManager = 
Mockito.mock(PartitionManager.class);
+      final ConsensusManager consensusManager = 
Mockito.mock(ConsensusManager.class);
+      Mockito.when(configManager.getNodeManager()).thenReturn(nodeManager);
+      
Mockito.when(configManager.getPartitionManager()).thenReturn(partitionManager);
+      
Mockito.when(configManager.getConsensusManager()).thenReturn(consensusManager);
+      Mockito.when(nodeManager.getRegisteredDataNodeCount()).thenReturn(1);
+      Mockito.when(nodeManager.getDataNodeCpuCoreCount()).thenReturn(1);
+      Mockito.when(
+              partitionManager.getRegionGroupCount(
+                  Mockito.anyString(), Mockito.any(TConsensusGroupType.class)))
+          .thenReturn(0);
+      
Mockito.when(consensusManager.write(Mockito.any(AdjustMaxRegionGroupNumPlan.class)))
+          .thenAnswer(
+              invocation -> {
+                final TSStatus status =
+                    
clusterSchemaInfo.adjustMaxRegionGroupCount(invocation.getArgument(0));
+                
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
+                return status;
+              });
+      final ClusterSchemaManager clusterSchemaManager =
+          new ClusterSchemaManager(
+              configManager, clusterSchemaInfo, 
Mockito.mock(ClusterSchemaQuotaStatistics.class));
+
+      final List<String> databases = Arrays.asList("pg", "root.pg", 
"root.control");
+      final int[] expectedLimits = {12, 6, 4};
+      for (int i = 0; i < databases.size(); i++) {
+        final String database = databases.get(i);
+        final TDatabaseSchema databaseSchema =
+            new TDatabaseSchema(database)
+                .setIsTableModel(i == 0)
+                .setSchemaReplicationFactor(1)
+                .setDataReplicationFactor(1)
+                .setMinSchemaRegionGroupNum(1)
+                .setMaxSchemaRegionGroupNum(1)
+                .setMinDataRegionGroupNum(2)
+                .setMaxDataRegionGroupNum(2);
+        Assert.assertEquals(
+            TSStatusCode.SUCCESS_STATUS.getStatusCode(),
+            clusterSchemaInfo
+                .createDatabase(
+                    new 
DatabaseSchemaPlan(ConfigPhysicalPlanType.CreateDatabase, databaseSchema))
+                .getCode());
+        
Mockito.when(partitionManager.isDatabaseExist(database)).thenReturn(true);
+
+        clusterSchemaManager.adjustMaxRegionGroupNum();
+
+        for (final String createdDatabase : databases.subList(0, i + 1)) {
+          final TDatabaseSchema adjustedSchema =
+              
clusterSchemaInfo.getMatchedDatabaseSchemaByName(createdDatabase);
+          Assert.assertEquals(
+              createdDatabase, expectedLimits[i], 
adjustedSchema.getMaxSchemaRegionGroupNum());
+          Assert.assertEquals(
+              createdDatabase, expectedLimits[i], 
adjustedSchema.getMaxDataRegionGroupNum());
+        }
+      }
+    } finally {
+      conf.setSchemaRegionPerDataNode(originalSchemaQuota);
+      conf.setDataRegionPerDataNode(originalDataQuota);
+      conf.setSchemaRegionGroupExtensionPolicy(originalSchemaPolicy);
+      conf.setDataRegionGroupExtensionPolicy(originalDataPolicy);
+    }
+  }
+
   @Test
   public void testNeedLastCacheDefaultsToTrueWhenUnset() {
     final TDatabaseSchema unsetSchema = new TDatabaseSchema();
diff --git 
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/manager/ConfigManagerDatabaseDeletionTest.java
 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/manager/ConfigManagerDatabaseDeletionTest.java
new file mode 100644
index 00000000000..10770df247b
--- /dev/null
+++ 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/manager/ConfigManagerDatabaseDeletionTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.confignode.manager;
+
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.confignode.manager.schema.ClusterSchemaManager;
+import org.apache.iotdb.confignode.rpc.thrift.TDatabaseSchema;
+import org.apache.iotdb.confignode.rpc.thrift.TDeleteDatabasesReq;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static 
org.apache.iotdb.commons.schema.table.Audit.TABLE_MODEL_AUDIT_DATABASE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ConfigManagerDatabaseDeletionTest {
+
+  @Test
+  public void testTableAuditDatabaseIsExcludedFromDeletion() {
+    final ConfigManager manager = mock(ConfigManager.class);
+    final ClusterSchemaManager schemaManager = 
mock(ClusterSchemaManager.class);
+    when(manager.confirmLeader())
+        .thenReturn(new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()));
+    when(manager.getClusterSchemaManager()).thenReturn(schemaManager);
+
+    final Map<String, TDatabaseSchema> schemas = new HashMap<>();
+    schemas.put(
+        TABLE_MODEL_AUDIT_DATABASE,
+        new TDatabaseSchema(TABLE_MODEL_AUDIT_DATABASE).setIsTableModel(true));
+    when(schemaManager.getMatchedDatabaseSchemasByName(
+            Collections.singletonList(TABLE_MODEL_AUDIT_DATABASE), true))
+        .thenReturn(schemas);
+    final TDeleteDatabasesReq request =
+        new 
TDeleteDatabasesReq(Collections.singletonList(TABLE_MODEL_AUDIT_DATABASE))
+            .setIsTableModel(true);
+    when(manager.deleteDatabases(request)).thenCallRealMethod();
+
+    assertEquals(
+        TSStatusCode.PATH_NOT_EXIST.getStatusCode(), 
manager.deleteDatabases(request).getCode());
+    assertTrue(schemas.isEmpty());
+  }
+}

Reply via email to