private TSStatus autoExtendRegionGroupIfNecessary(
      final Map<String, Integer> unassignedPartitionSlotsCountMap,
      final TConsensusGroupType consensusGroupType)
      throws NotEnoughDataNodeException, DatabaseNotExistsException {

    // Map<Database, Region allotment>
    final Map<String, Integer> allotmentMap = new ConcurrentHashMap<>();

    for (Map.Entry<String, Integer> entry : unassignedPartitionSlotsCountMap.entrySet()) {
      final String database = entry.getKey();
      final int unassignedPartitionSlotsCount = entry.getValue();

      float allocatedRegionGroupCount =
          partitionInfo.getRegionGroupCount(database, consensusGroupType);
      // The slotCount equals to the sum of assigned slot count and unassigned slot count
      float slotCount =
          (float) partitionInfo.getAssignedSeriesPartitionSlotsCount(database)
              + unassignedPartitionSlotsCount;
      float maxRegionGroupNum =
          getClusterSchemaManager().getMaxRegionGroupNum(database, consensusGroupType);
      float maxSlotCount = CONF.getSeriesSlotNum();

      /* RegionGroup extension is required in the following cases */
      // 1. The number of current RegionGroup of the Database is less than the minimum number
      final int minRegionGroupNum =
          getClusterSchemaManager().getMinRegionGroupNum(database, consensusGroupType);
      if (allocatedRegionGroupCount < minRegionGroupNum
          // Ensure the number of RegionGroups is enough
          // for current SeriesPartitionSlots after extension
          // Otherwise, more RegionGroups should be extended through case 2.
          && slotCount <= (maxSlotCount / maxRegionGroupNum) * minRegionGroupNum) {

        // Let the sum of unassignedPartitionSlotsCount and allocatedRegionGroupCount
        // no less than the minRegionGroupNum
        int delta =
            (int)
                Math.min(
                    unassignedPartitionSlotsCount, minRegionGroupNum - allocatedRegionGroupCount);
        allotmentMap.put(database, delta);

      } else if (allocatedRegionGroupCount < maxRegionGroupNum
          && slotCount / allocatedRegionGroupCount > maxSlotCount / maxRegionGroupNum) {
        // 2. The average number of partitions held by each Region will be greater than the
        // expected average number after the partition allocation is completed.

        // The delta is equal to the smallest integer solution that satisfies the inequality:
        // slotCount / (allocatedRegionGroupCount + delta) < maxSlotCount / maxRegionGroupNum
        final int delta =
            Math.min(
                (int) (maxRegionGroupNum - allocatedRegionGroupCount),
                Math.max(
                    1,
                    (int)
                        Math.ceil(
                            slotCount * maxRegionGroupNum / maxSlotCount
                                - allocatedRegionGroupCount)));
        allotmentMap.put(database, delta);

      } else if (allocatedRegionGroupCount
              == filterRegionGroupThroughStatus(database, RegionGroupStatus.Disabled).size()
          && allocatedRegionGroupCount < maxRegionGroupNum) {
        // 3. All RegionGroups in the specified Database are disabled currently
        allotmentMap.put(database, 1);
      }
    }

    return generateAndAllocateRegionGroups(allotmentMap, consensusGroupType);
  }
Allocate more RegionGroup to the specified StorageGroups if necessary.

@param unassignedPartitionSlotsCountMap Map<StorageGroup, unassigned Partition count>
@param consensusGroupType SchemaRegion or DataRegion
@return SUCCESS_STATUS when RegionGroup extension successful; NOT_ENOUGH_DATA_NODE when there
    are not enough DataNodes; STORAGE_GROUP_NOT_EXIST when some StorageGroups don't exist
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java