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

xingtanzjr 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 5cc3581d26 [IOTDB-3455] Make data_region_num takes effect in new 
standalone (#7136)
5cc3581d26 is described below

commit 5cc3581d2600713e6721772a8ed3d3d62307a665
Author: Liu Xuxin <[email protected]>
AuthorDate: Wed Sep 14 17:21:48 2022 +0800

    [IOTDB-3455] Make data_region_num takes effect in new standalone (#7136)
---
 .../resources/conf/iotdb-datanode.properties       |  20 ++-
 .../iotdb/db/localconfignode/LocalConfigNode.java  |  57 +++-----
 .../db/localconfignode/LocalDataPartitionInfo.java | 110 ++++++++++++++
 .../localconfignode/LocalDataPartitionTable.java   | 158 ++++++++++-----------
 .../LocalConfigNodeMultiDataRegionTest.java        |  98 +++++++++++++
 .../plan/scheduler/StandaloneSchedulerTest.java    |   2 +
 6 files changed, 321 insertions(+), 124 deletions(-)

diff --git a/server/src/assembly/resources/conf/iotdb-datanode.properties 
b/server/src/assembly/resources/conf/iotdb-datanode.properties
index c230f7771b..92d93508d7 100644
--- a/server/src/assembly/resources/conf/iotdb-datanode.properties
+++ b/server/src/assembly/resources/conf/iotdb-datanode.properties
@@ -414,12 +414,6 @@ timestamp_precision=ms
 # Datatype: boolean
 # enable_partial_insert=true
 
-# number of data regions per user-defined storage group
-# a data region is the unit of parallelism in memory as all ingestions in one 
data region are serialized
-# recommended value is [data region number] = [CPU core number] / 
[user-defined storage group number]
-# Datatype: int
-# data_region_num = 1
-
 # the interval to log recover progress of each vsg when starting iotdb
 # Datatype: int
 # recovery_log_interval_in_ms=5000
@@ -1110,6 +1104,17 @@ trigger_forward_http_pool_max_per_route=20
 trigger_forward_mqtt_pool_size=4
 
 
+
+#######################
+### LocalConfigNode ###
+#######################
+
+# number of data regions per user-defined storage group
+# a data region is the unit of parallelism in memory as all ingestions in one 
data region are serialized
+# recommended value is [data region number] = [CPU core number] / 
[user-defined storage group number]
+# Datatype: int
+# data_region_num=1
+
 ####################
 ### External Lib Configuration
 ####################
@@ -1130,4 +1135,5 @@ trigger_forward_mqtt_pool_size=4
 # external_limiter_dir=ext\\limiter
 # For Linux platform
 # If its prefix is "/", then the path is absolute. Otherwise, it is relative.
-# external_limiter_dir=ext/limiter
\ No newline at end of file
+# external_limiter_dir=ext/limiter
+
diff --git 
a/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalConfigNode.java 
b/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalConfigNode.java
index 25c1c9332d..dff123cbb2 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalConfigNode.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalConfigNode.java
@@ -127,7 +127,7 @@ public class LocalConfigNode {
   private static final Logger logger = 
LoggerFactory.getLogger(LocalConfigNode.class);
 
   private static final IoTDBConfig config = 
IoTDBDescriptor.getInstance().getConfig();
-  private static final long STANDALONE_MOCK_TIME_SLOT_START_TIME = 0L;
+  public static final long STANDALONE_MOCK_TIME_SLOT_START_TIME = 0L;
   private volatile boolean initialized = false;
 
   private ScheduledExecutorService timedForceMLogThread;
@@ -141,7 +141,7 @@ public class LocalConfigNode {
 
   private final StorageEngineV2 storageEngine = StorageEngineV2.getInstance();
 
-  private final LocalDataPartitionTable dataPartitionTable = 
LocalDataPartitionTable.getInstance();
+  private final LocalDataPartitionInfo dataPartitionInfo = 
LocalDataPartitionInfo.getInstance();
 
   private final SeriesPartitionExecutor executor =
       SeriesPartitionExecutor.getSeriesPartitionExecutor(
@@ -212,7 +212,7 @@ public class LocalConfigNode {
       if (config.isMppMode() && !config.isClusterMode()) {
         Map<String, List<DataRegionId>> recoveredLocalDataRegionInfo =
             storageEngine.getLocalDataRegionInfo();
-        dataPartitionTable.init(recoveredLocalDataRegionInfo);
+        dataPartitionInfo.init(recoveredLocalDataRegionInfo);
       }
     } catch (MetadataException | IOException e) {
       logger.error(
@@ -239,7 +239,7 @@ public class LocalConfigNode {
       storageGroupSchemaManager.clear();
       templateManager.clear();
 
-      dataPartitionTable.clear();
+      dataPartitionInfo.clear();
 
     } catch (IOException e) {
       logger.error("Error occurred when clearing LocalConfigNode:", e);
@@ -283,8 +283,8 @@ public class LocalConfigNode {
 
     if (config.isMppMode() && !config.isClusterMode()) {
       deleteDataRegionsInStorageGroup(
-          dataPartitionTable.getDataRegionIdsByStorageGroup(storageGroup));
-      dataPartitionTable.deleteStorageGroup(storageGroup);
+          dataPartitionInfo.getDataRegionIdsByStorageGroup(storageGroup));
+      dataPartitionInfo.deleteStorageGroup(storageGroup);
     }
 
     deleteSchemaRegionsInStorageGroup(
@@ -367,8 +367,7 @@ public class LocalConfigNode {
 
   public void setTTL(PartialPath storageGroup, long dataTTL) throws 
MetadataException, IOException {
     if (config.isMppMode() && !config.isClusterMode()) {
-      storageEngine.setTTL(
-          dataPartitionTable.getDataRegionIdsByStorageGroup(storageGroup), 
dataTTL);
+      
storageEngine.setTTL(dataPartitionInfo.getDataRegionIdsByStorageGroup(storageGroup),
 dataTTL);
     }
     storageGroupSchemaManager.setTTL(storageGroup, dataTTL);
   }
@@ -855,7 +854,7 @@ public class LocalConfigNode {
   public DataRegionId getBelongedDataRegionId(PartialPath path)
       throws MetadataException, DataRegionException {
     PartialPath storageGroup = 
storageGroupSchemaManager.getBelongedStorageGroup(path);
-    DataRegionId dataRegionId = 
dataPartitionTable.getDataRegionId(storageGroup, path);
+    DataRegionId dataRegionId = 
dataPartitionInfo.getDataRegionId(storageGroup, path);
     if (dataRegionId == null) {
       return null;
     }
@@ -870,13 +869,13 @@ public class LocalConfigNode {
   }
 
   // This interface involves storage group and data region auto creation
-  public DataRegionId getBelongedDataRegionIdWithAutoCreate(PartialPath path)
+  public DataRegionId getBelongedDataRegionIdWithAutoCreate(PartialPath 
devicePath)
       throws MetadataException, DataRegionException {
-    PartialPath storageGroup = 
storageGroupSchemaManager.getBelongedStorageGroup(path);
-    DataRegionId dataRegionId = 
dataPartitionTable.getDataRegionId(storageGroup, path);
+    PartialPath storageGroup = 
storageGroupSchemaManager.getBelongedStorageGroup(devicePath);
+    DataRegionId dataRegionId = 
dataPartitionInfo.getDataRegionId(storageGroup, devicePath);
     if (dataRegionId == null) {
-      dataPartitionTable.setDataPartitionInfo(storageGroup);
-      dataRegionId = dataPartitionTable.getDataRegionId(storageGroup, path);
+      dataPartitionInfo.registerStorageGroup(storageGroup);
+      dataRegionId = 
dataPartitionInfo.allocateDataRegionForNewSlot(storageGroup, devicePath);
     }
     DataRegion dataRegion = storageEngine.getDataRegion(dataRegionId);
     if (dataRegion == null) {
@@ -885,14 +884,6 @@ public class LocalConfigNode {
     return dataRegionId;
   }
 
-  public List<DataRegionId> getDataRegionIdsByStorageGroup(PartialPath 
storageGroup) {
-    return dataPartitionTable.getDataRegionIdsByStorageGroup(storageGroup);
-  }
-
-  // endregion
-
-  // region Interfaces for StandaloneSchemaFetcher
-
   public Map<String, Map<TSeriesPartitionSlot, TRegionReplicaSet>> 
getSchemaPartition(
       PathPatternTree patternTree) {
 
@@ -950,8 +941,6 @@ public class LocalConfigNode {
     return partitionSlotsMap;
   }
 
-  // endregion
-
   // region Interfaces for StandalonePartitionFetcher
   public DataPartition getDataPartition(
       Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap)
@@ -1023,22 +1012,22 @@ public class LocalConfigNode {
       for (DataPartitionQueryParam dataPartitionQueryParam : 
dataPartitionQueryParams) {
         // for each device
         String deviceId = dataPartitionQueryParam.getDevicePath();
-        DataRegionId dataRegionId =
-            getBelongedDataRegionIdWithAutoCreate(new PartialPath(deviceId));
-        Map<TTimePartitionSlot, List<TRegionReplicaSet>> 
timePartitionToRegionsMap =
-            deviceToRegionsMap.getOrDefault(
-                executor.getSeriesPartitionSlot(deviceId), new HashMap<>());
-        for (TTimePartitionSlot timePartitionSlot :
-            dataPartitionQueryParam.getTimePartitionSlotList()) {
-          // for each time partition
+        List<TTimePartitionSlot> timePartitionSlotList =
+            dataPartitionQueryParam.getTimePartitionSlotList();
+        for (TTimePartitionSlot timePartitionSlot : timePartitionSlotList) {
+          DataRegionId dataRegionId =
+              getBelongedDataRegionIdWithAutoCreate(new PartialPath(deviceId));
+          Map<TTimePartitionSlot, List<TRegionReplicaSet>> 
timePartitionToRegionsMap =
+              deviceToRegionsMap.getOrDefault(
+                  executor.getSeriesPartitionSlot(deviceId), new HashMap<>());
           timePartitionToRegionsMap.put(
               timePartitionSlot,
               Collections.singletonList(
                   genStandaloneRegionReplicaSet(
                       TConsensusGroupType.DataRegion, dataRegionId.getId())));
+          deviceToRegionsMap.put(
+              executor.getSeriesPartitionSlot(deviceId), 
timePartitionToRegionsMap);
         }
-        deviceToRegionsMap.put(
-            executor.getSeriesPartitionSlot(deviceId), 
timePartitionToRegionsMap);
       }
       dataPartitionMap.put(storageGroupName, deviceToRegionsMap);
     }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalDataPartitionInfo.java
 
b/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalDataPartitionInfo.java
new file mode 100644
index 0000000000..0802bfc4d8
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalDataPartitionInfo.java
@@ -0,0 +1,110 @@
+/*
+ * 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.localconfignode;
+
+import org.apache.iotdb.commons.consensus.DataRegionId;
+import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.path.PartialPath;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+// This class is used for data partition maintaining the map between storage 
group and
+// dataRegionIds.
+public class LocalDataPartitionInfo {
+
+  // storageGroup -> LocalDataPartitionTable
+  private Map<PartialPath, LocalDataPartitionTable> partitionTableMap;
+
+  private static class LocalDataPartitionTableHolder {
+    private static final LocalDataPartitionInfo INSTANCE = new 
LocalDataPartitionInfo();
+
+    private LocalDataPartitionTableHolder() {}
+  }
+
+  private LocalDataPartitionInfo() {}
+
+  public static LocalDataPartitionInfo getInstance() {
+    return LocalDataPartitionTableHolder.INSTANCE;
+  }
+
+  public synchronized void init(Map<String, List<DataRegionId>> regionInfos)
+      throws IllegalPathException {
+    partitionTableMap = new ConcurrentHashMap<>();
+    for (Map.Entry<String, List<DataRegionId>> entry : regionInfos.entrySet()) 
{
+      String storageGroupName = entry.getKey();
+      List<DataRegionId> regionIds = entry.getValue();
+      LocalDataPartitionTable table = new 
LocalDataPartitionTable(storageGroupName, regionIds);
+      partitionTableMap.put(new PartialPath(storageGroupName), table);
+    }
+  }
+
+  public synchronized void clear() {
+    if (partitionTableMap != null) {
+      partitionTableMap.clear();
+      partitionTableMap = null;
+    }
+  }
+
+  public DataRegionId getDataRegionId(PartialPath storageGroup, PartialPath 
path) {
+    if (!partitionTableMap.containsKey(storageGroup)) {
+      return null;
+    }
+    LocalDataPartitionTable table = partitionTableMap.get(storageGroup);
+    return table.getDataRegionId(path);
+  }
+
+  /**
+   * Try to allocate a data region for the new time partition slot. This 
function will try to create
+   * new data region to make expansion if the existing data regions meet some 
condition.
+   *
+   * @param storageGroup The path for the storage group.
+   * @param path The full path for the series.
+   * @return The data region id for the time partition slot.
+   */
+  public DataRegionId allocateDataRegionForNewSlot(PartialPath storageGroup, 
PartialPath path) {
+    LocalDataPartitionTable table = partitionTableMap.get(storageGroup);
+    return table.getDataRegionWithAutoExtension(path);
+  }
+
+  public List<DataRegionId> getDataRegionIdsByStorageGroup(PartialPath 
storageGroup) {
+    if (partitionTableMap.containsKey(storageGroup)) {
+      LocalDataPartitionTable partitionTable = 
partitionTableMap.get(storageGroup);
+      return partitionTable.getAllDataRegionId();
+    }
+    return Collections.emptyList();
+  }
+
+  public synchronized void registerStorageGroup(PartialPath storageGroup) {
+    if (partitionTableMap.containsKey(storageGroup)) {
+      return;
+    }
+    partitionTableMap.put(storageGroup, new 
LocalDataPartitionTable(storageGroup.getFullPath()));
+  }
+
+  public synchronized void deleteStorageGroup(PartialPath storageGroup) {
+    LocalDataPartitionTable partitionTable = 
partitionTableMap.remove(storageGroup);
+    if (partitionTable != null) {
+      partitionTable.clear();
+    }
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalDataPartitionTable.java
 
b/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalDataPartitionTable.java
index 52662e3f9d..d52afe32cf 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalDataPartitionTable.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalDataPartitionTable.java
@@ -19,116 +19,108 @@
 
 package org.apache.iotdb.db.localconfignode;
 
+import org.apache.iotdb.commons.consensus.ConsensusGroupId;
 import org.apache.iotdb.commons.consensus.DataRegionId;
-import org.apache.iotdb.commons.exception.IllegalPathException;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.utils.TestOnly;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
 
-import java.util.ArrayList;
-import java.util.Collections;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
+import java.util.Comparator;
 import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicInteger;
 
-// This class is used for data partition maintaining the map between storage 
group and
-// dataRegionIds.
 public class LocalDataPartitionTable {
-
-  private AtomicInteger dataRegionIdGenerator;
-
-  private Map<PartialPath, List<DataRegionId>> table;
-
-  private static class LocalDataPartitionTableHolder {
-    private static final LocalDataPartitionTable INSTANCE = new 
LocalDataPartitionTable();
-
-    private LocalDataPartitionTableHolder() {};
+  private static final Logger LOG = 
LoggerFactory.getLogger(LocalDataPartitionTable.class);
+
+  private String storageGroupName;
+  private final int regionNum;
+  private DataRegionId[] regionIds;
+
+  public LocalDataPartitionTable(String storageGroupName, List<DataRegionId> 
regions) {
+    this.storageGroupName = storageGroupName;
+    this.regionNum = regions.size();
+    regions.sort(Comparator.comparingInt(ConsensusGroupId::getId));
+    this.regionIds = new DataRegionId[regions.size()];
+    for (int i = 0; i < regions.size(); ++i) {
+      regionIds[i] = regions.get(i);
+      DataRegionIdGenerator.getInstance().setIfGreater(regionIds[i].getId());
+    }
   }
 
-  private LocalDataPartitionTable() {}
-
-  public static LocalDataPartitionTable getInstance() {
-    return LocalDataPartitionTableHolder.INSTANCE;
+  public LocalDataPartitionTable(String storageGroupName) {
+    this.storageGroupName = storageGroupName;
+    this.regionNum = 
IoTDBDescriptor.getInstance().getConfig().getDataRegionNum();
+    this.regionIds = new DataRegionId[regionNum];
   }
 
-  public synchronized void init(Map<String, List<DataRegionId>> 
recoveredLocalDataRegionInfo)
-      throws IllegalPathException {
-    table = new ConcurrentHashMap<>();
-    dataRegionIdGenerator = new AtomicInteger(0);
-    for (Map.Entry<String, List<DataRegionId>> entry : 
recoveredLocalDataRegionInfo.entrySet()) {
-      String storageGroup = entry.getKey();
-      List<DataRegionId> dataRegionIdList = new CopyOnWriteArrayList<>();
-      table.put(new PartialPath(storageGroup), dataRegionIdList);
-      for (DataRegionId dataRegionId : 
recoveredLocalDataRegionInfo.get(storageGroup)) {
-        dataRegionIdList.add(dataRegionId);
-
-        if (dataRegionId.getId() >= dataRegionIdGenerator.get()) {
-          dataRegionIdGenerator.set(dataRegionId.getId() + 1);
-        }
-      }
-    }
+  /**
+   * Get the data region id which the path located in.
+   *
+   * @param path The full path for the series.
+   * @return The region id for the path.
+   */
+  public DataRegionId getDataRegionId(PartialPath path) {
+    int idx = Math.abs(path.hashCode() % regionNum);
+    return regionIds[idx];
   }
 
-  public synchronized void clear() {
-    if (table != null) {
-      table.clear();
-      table = null;
-    }
+  /**
+   * Get all data region id of current storage group
+   *
+   * @return data region id in list
+   */
+  public List<DataRegionId> getAllDataRegionId() {
+    return Arrays.asList(regionIds);
+  }
 
-    if (dataRegionIdGenerator != null) {
-      dataRegionIdGenerator = null;
+  public DataRegionId getDataRegionWithAutoExtension(PartialPath path) {
+    int idx = Math.abs(path.hashCode() % regionNum);
+    if (regionIds[idx] == null) {
+      int nextId = DataRegionIdGenerator.getInstance().getNextId();
+      regionIds[idx] = new DataRegionId(nextId);
     }
+    return regionIds[idx];
   }
 
-  public synchronized void putDataRegionId(PartialPath storageGroup, 
DataRegionId dataRegionId) {
-    table.get(storageGroup).add(dataRegionId);
+  public void clear() {
+    // TODO: clear the table
+    regionIds = null;
   }
 
-  public synchronized void removeDataRegionId(PartialPath storageGroup, 
DataRegionId dataRegionId) {
-    table.get(storageGroup).remove(dataRegionId);
-  }
+  public static class DataRegionIdGenerator {
+    private static final DataRegionIdGenerator INSTANCE = new 
DataRegionIdGenerator();
+    private final AtomicInteger idCounter = new AtomicInteger(0);
 
-  public DataRegionId getDataRegionId(PartialPath storageGroup, PartialPath 
path) {
-    if (!table.containsKey(storageGroup)) {
-      return null;
+    public static DataRegionIdGenerator getInstance() {
+      return INSTANCE;
     }
-    return table.get(storageGroup).get(0);
-  }
 
-  public List<DataRegionId> getInvolvedDataRegionIds(
-      PartialPath storageGroup, PartialPath pathPattern, boolean 
isPrefixMatch) {
-    List<DataRegionId> result = new ArrayList<>();
-    if (table.containsKey(storageGroup)) {
-      result.addAll(table.get(storageGroup));
+    public void setCurrentId(int id) {
+      idCounter.set(id);
     }
-    return result;
-  }
-
-  public List<DataRegionId> getDataRegionIdsByStorageGroup(PartialPath 
storageGroup) {
-    return table.getOrDefault(storageGroup, Collections.emptyList());
-  }
 
-  public synchronized void setDataPartitionInfo(PartialPath storageGroup) {
-    List<DataRegionId> dataRegionIdList;
-    if (table.containsKey(storageGroup)) {
-      dataRegionIdList = table.get(storageGroup);
-    } else {
-      dataRegionIdList = new CopyOnWriteArrayList<>();
+    public int getNextId() {
+      return idCounter.getAndIncrement();
     }
-    dataRegionIdList.add(generateDataRegionId());
-    table.put(storageGroup, dataRegionIdList);
-  }
 
-  public synchronized List<DataRegionId> deleteStorageGroup(PartialPath 
storageGroup) {
-    if (table.containsKey(storageGroup)) {
-      return table.remove(storageGroup);
+    /**
+     * Update the id counter when recovering, make sure that after all data 
regions is recovered,
+     * the id counter is greater than any existed region id
+     */
+    public void setIfGreater(int id) {
+      int originVal = idCounter.get();
+      while (originVal <= id && !idCounter.compareAndSet(originVal, id + 1)) {
+        originVal = idCounter.get();
+      }
     }
-    return Collections.emptyList();
-  }
 
-  // This method may be extended to implement multi dataRegion for one 
storageGroup
-  // todo keep consistent with the partition method of config node in new 
cluster
-  private DataRegionId generateDataRegionId() {
-    return new DataRegionId(dataRegionIdGenerator.getAndIncrement());
+    @TestOnly
+    public void reset() {
+      this.idCounter.set(0);
+    }
   }
 }
diff --git 
a/server/src/test/java/org/apache/iotdb/db/localconfignode/LocalConfigNodeMultiDataRegionTest.java
 
b/server/src/test/java/org/apache/iotdb/db/localconfignode/LocalConfigNodeMultiDataRegionTest.java
new file mode 100644
index 0000000000..7fa637ca9b
--- /dev/null
+++ 
b/server/src/test/java/org/apache/iotdb/db/localconfignode/LocalConfigNodeMultiDataRegionTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.localconfignode;
+
+import org.apache.iotdb.commons.consensus.DataRegionId;
+import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.service.IoTDB;
+import org.apache.iotdb.db.utils.EnvironmentUtils;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+public class LocalConfigNodeMultiDataRegionTest {
+  int originDataRegionNum;
+  boolean isMppMode = false;
+  boolean isClusterMode = false;
+
+  @Before
+  public void setUp() throws IllegalPathException {
+    originDataRegionNum = 
IoTDBDescriptor.getInstance().getConfig().getDataRegionNum();
+    isMppMode = IoTDBDescriptor.getInstance().getConfig().isMppMode();
+    isClusterMode = IoTDBDescriptor.getInstance().getConfig().isClusterMode();
+    IoTDBDescriptor.getInstance().getConfig().setMppMode(true);
+    IoTDBDescriptor.getInstance().getConfig().setClusterMode(false);
+    IoTDB.configManager.init();
+    EnvironmentUtils.envSetUp();
+    LocalDataPartitionInfo.getInstance().init(Collections.EMPTY_MAP);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    
IoTDBDescriptor.getInstance().getConfig().setDataRegionNum(originDataRegionNum);
+    EnvironmentUtils.cleanEnv();
+    IoTDBDescriptor.getInstance().getConfig().setMppMode(isMppMode);
+    IoTDBDescriptor.getInstance().getConfig().setClusterMode(isClusterMode);
+  }
+
+  @Test
+  public void createMultiDataRegionTest() throws Exception {
+    IoTDBDescriptor.getInstance().getConfig().setDataRegionNum(3);
+    IoTDB.schemaProcessor.setStorageGroup(new PartialPath("root.test"));
+    LocalConfigNode configNode = LocalConfigNode.getInstance();
+    LocalDataPartitionInfo info = LocalDataPartitionInfo.getInstance();
+    info.registerStorageGroup(new PartialPath("root.test"));
+    configNode.getBelongedDataRegionIdWithAutoCreate(new 
PartialPath("root.test.d1"));
+    configNode.getBelongedDataRegionIdWithAutoCreate(new 
PartialPath("root.test.d2"));
+    configNode.getBelongedDataRegionIdWithAutoCreate(new 
PartialPath("root.test.d3"));
+    List<DataRegionId> regionIds =
+        info.getDataRegionIdsByStorageGroup(new PartialPath("root.test"));
+    Assert.assertEquals(3, regionIds.size());
+  }
+
+  @Test
+  public void recoverMultiDataRegionTest() throws Exception {
+    IoTDBDescriptor.getInstance().getConfig().setDataRegionNum(3);
+    IoTDB.schemaProcessor.setStorageGroup(new PartialPath("root.test"));
+    LocalConfigNode configNode = LocalConfigNode.getInstance();
+    LocalDataPartitionInfo info = LocalDataPartitionInfo.getInstance();
+    info.registerStorageGroup(new PartialPath("root.test"));
+    configNode.getBelongedDataRegionIdWithAutoCreate(new 
PartialPath("root.test.d1"));
+    configNode.getBelongedDataRegionIdWithAutoCreate(new 
PartialPath("root.test.d2"));
+    configNode.getBelongedDataRegionIdWithAutoCreate(new 
PartialPath("root.test.d3"));
+    LocalConfigNode.getInstance().clear();
+    LocalConfigNode.getInstance().init();
+    info = LocalDataPartitionInfo.getInstance();
+    info.registerStorageGroup(new PartialPath("root.test"));
+    configNode.getBelongedDataRegionIdWithAutoCreate(new 
PartialPath("root.test.d1"));
+    configNode.getBelongedDataRegionIdWithAutoCreate(new 
PartialPath("root.test.d2"));
+    configNode.getBelongedDataRegionIdWithAutoCreate(new 
PartialPath("root.test.d3"));
+    List<DataRegionId> regionIds =
+        info.getDataRegionIdsByStorageGroup(new PartialPath("root.test"));
+    Assert.assertEquals(3, regionIds.size());
+  }
+}
diff --git 
a/server/src/test/java/org/apache/iotdb/db/mpp/plan/scheduler/StandaloneSchedulerTest.java
 
b/server/src/test/java/org/apache/iotdb/db/mpp/plan/scheduler/StandaloneSchedulerTest.java
index 34e2a9e85f..94fac23509 100644
--- 
a/server/src/test/java/org/apache/iotdb/db/mpp/plan/scheduler/StandaloneSchedulerTest.java
+++ 
b/server/src/test/java/org/apache/iotdb/db/mpp/plan/scheduler/StandaloneSchedulerTest.java
@@ -34,6 +34,7 @@ import org.apache.iotdb.db.engine.flush.FlushManager;
 import org.apache.iotdb.db.engine.storagegroup.DataRegionTest;
 import org.apache.iotdb.db.exception.DataRegionException;
 import org.apache.iotdb.db.localconfignode.LocalConfigNode;
+import org.apache.iotdb.db.localconfignode.LocalDataPartitionTable;
 import org.apache.iotdb.db.mpp.common.MPPQueryContext;
 import org.apache.iotdb.db.mpp.common.PlanFragmentId;
 import org.apache.iotdb.db.mpp.common.QueryId;
@@ -86,6 +87,7 @@ public class StandaloneSchedulerTest {
     WALManager.getInstance().start();
     FlushManager.getInstance().start();
     StorageEngineV2.getInstance().start();
+    LocalDataPartitionTable.DataRegionIdGenerator.getInstance().reset();
   }
 
   @After

Reply via email to