public synchronized void initFolders() {
    try {
      String strategyName = Class.forName(config.getMultiDirStrategyClassName()).getSimpleName();
      if (strategyName.equals(MaxDiskUsableSpaceFirstStrategy.class.getSimpleName())) {
        directoryStrategyType = DirectoryStrategyType.MAX_DISK_USABLE_SPACE_FIRST_STRATEGY;
      } else if (strategyName.equals(MinFolderOccupiedSpaceFirstStrategy.class.getSimpleName())) {
        directoryStrategyType = DirectoryStrategyType.MIN_FOLDER_OCCUPIED_SPACE_FIRST_STRATEGY;
      } else if (strategyName.equals(RandomOnDiskUsableSpaceStrategy.class.getSimpleName())) {
        directoryStrategyType = DirectoryStrategyType.RANDOM_ON_DISK_USABLE_SPACE_STRATEGY;
      }
    } catch (Exception e) {
      logger.error(
          "Can't find strategy {} for mult-directories.", config.getMultiDirStrategyClassName(), e);
    }

    config.updatePath();
    String[][] tierDirs = config.getTierDataDirs();
    for (int i = 0; i < tierDirs.length; ++i) {
      for (int j = 0; j < tierDirs[i].length; ++j) {
        switch (FSUtils.getFSType(tierDirs[i][j])) {
          case LOCAL:
            try {
              tierDirs[i][j] = new File(tierDirs[i][j]).getCanonicalPath();
            } catch (IOException e) {
              logger.error("Fail to get canonical path of data dir {}", tierDirs[i][j], e);
            }
            break;
          case OBJECT_STORAGE:
          case HDFS:
          default:
            break;
        }
      }
    }

    for (int tierLevel = 0; tierLevel < tierDirs.length; ++tierLevel) {
      List<String> seqDirs =
          Arrays.stream(tierDirs[tierLevel])
              .filter(Objects::nonNull)
              .map(
                  v ->
                      FSFactoryProducer.getFSFactory()
                          .getFile(v, IoTDBConstant.SEQUENCE_FOLDER_NAME)
                          .getPath())
              .collect(Collectors.toList());
      mkDataDirs(seqDirs);
      try {
        seqTiers.add(new FolderManager(seqDirs, directoryStrategyType));
      } catch (DiskSpaceInsufficientException e) {
        logger.error("All disks of tier {} are full.", tierLevel, e);
      }
      for (String dir : seqDirs) {
        seqDir2TierLevel.put(dir, tierLevel);
      }

      List<String> unSeqDirs =
          Arrays.stream(tierDirs[tierLevel])
              .filter(Objects::nonNull)
              .map(
                  v ->
                      FSFactoryProducer.getFSFactory()
                          .getFile(v, IoTDBConstant.UNSEQUENCE_FOLDER_NAME)
                          .getPath())
              .collect(Collectors.toList());
      mkDataDirs(unSeqDirs);
      try {
        unSeqTiers.add(new FolderManager(unSeqDirs, directoryStrategyType));
      } catch (DiskSpaceInsufficientException e) {
        logger.error("All disks of tier {} are full.", tierLevel, e);
      }
      for (String dir : unSeqDirs) {
        unSeqDir2TierLevel.put(dir, tierLevel);
      }
    }

    tierDiskTotalSpace = getTierDiskSpace(DiskSpaceType.TOTAL);
  }
total space of each tier, Long.MAX_VALUE when one tier contains remote storage
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/TierManager.java