private boolean createSnapshot(List<TsFileResource> resources, String snapshotId) {
    try {
      for (TsFileResource resource : resources) {
        if (!resource.isClosed()) {
          continue;
        }
        File tsFile = resource.getTsFile();
        if (!resource.isClosed()) {
          continue;
        }
        File snapshotTsFile = getSnapshotFilePathForTsFile(tsFile, snapshotId);
        File snapshotResourceFile =
            new File(snapshotTsFile.getAbsolutePath() + TsFileResource.RESOURCE_SUFFIX);
        File snapshotDir = snapshotTsFile.getParentFile();
        // create hard link for tsfile, resource, mods
        createHardLink(snapshotTsFile, tsFile);

        if (resource.exclusiveModFileExists()) {
          copyFile(
              ModificationFile.getExclusiveMods(snapshotTsFile),
              ModificationFile.getExclusiveMods(tsFile));
        }

        if (resource.sharedModFileExists()) {
          File sharedModFile = resource.getSharedModFile().getFile();
          File snapshotSharedModFile = new File(snapshotDir, sharedModFile.getName());
          if (!snapshotSharedModFile.exists()) {
            copyFile(snapshotSharedModFile, sharedModFile);
          }

          // rewrite the resource in snapshot to update the mod file path
          ModificationFile sharedModFileTemp = resource.getSharedModFile();
          resource.setSharedModFile(new ModificationFile(snapshotSharedModFile, false), false);
          resource.serialize(snapshotResourceFile.getAbsolutePath());
          resource.setSharedModFile(sharedModFileTemp, false);
        } else {
          createHardLink(
              snapshotResourceFile,
              new File(tsFile.getAbsolutePath() + TsFileResource.RESOURCE_SUFFIX));
        }
      }
      return true;
    } catch (IOException e) {
      LOGGER.error("Catch IOException when creating snapshot", e);
      return false;
    }
  }
SnapshotTaker takes data snapshot for a DataRegion in one time. It does so by creating hard link
for files or copying them. SnapshotTaker supports two different ways of snapshot: Full Snapshot
and Incremental Snapshot. The former takes a snapshot for all files in an empty directory, and
the latter takes a snapshot based on the snapshot that took before.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/snapshot/SnapshotTaker.java