This is an automated email from the ASF dual-hosted git repository.
tanxinyu 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 44f1d1813b [IOTDB-3589] Fix dataRegion cannot recover from snapshot
(#6376)
44f1d1813b is described below
commit 44f1d1813be3c1b6be5c591c3073d6764dd94c9c
Author: Liu Xuxin <[email protected]>
AuthorDate: Wed Jun 22 14:05:55 2022 +0800
[IOTDB-3589] Fix dataRegion cannot recover from snapshot (#6376)
* take snapshot in form of directory
* load snapshot with directory snapshot
* fix error when loading snapshot
---
.../iotdb/db/engine/snapshot/SnapshotLoader.java | 137 +++++++++++++++------
.../iotdb/db/engine/snapshot/SnapshotTaker.java | 47 ++++---
2 files changed, 127 insertions(+), 57 deletions(-)
diff --git
a/server/src/main/java/org/apache/iotdb/db/engine/snapshot/SnapshotLoader.java
b/server/src/main/java/org/apache/iotdb/db/engine/snapshot/SnapshotLoader.java
index 476a645533..7283e621ba 100644
---
a/server/src/main/java/org/apache/iotdb/db/engine/snapshot/SnapshotLoader.java
+++
b/server/src/main/java/org/apache/iotdb/db/engine/snapshot/SnapshotLoader.java
@@ -34,6 +34,7 @@ import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.List;
public class SnapshotLoader {
@@ -78,22 +79,10 @@ public class SnapshotLoader {
}
// move the snapshot data to data dir
- String seqBaseDir =
- IoTDBConstant.SEQUENCE_FLODER_NAME
- + File.separator
- + storageGroupName
- + File.separator
- + dataRegionId;
- String unseqBaseDir =
- IoTDBConstant.UNSEQUENCE_FLODER_NAME
- + File.separator
- + storageGroupName
- + File.separator
- + dataRegionId;
File sourceDataDir = new File(snapshotPath);
if (sourceDataDir.exists()) {
try {
- createLinksFromSnapshotDirToDataDir(sourceDataDir, seqBaseDir,
unseqBaseDir);
+ createLinksFromSnapshotDirToDataDir(sourceDataDir);
} catch (IOException | DiskSpaceInsufficientException e) {
LOGGER.error(
"Exception occurs when creating links from snapshot directory to
data directory", e);
@@ -158,38 +147,104 @@ public class SnapshotLoader {
}
}
- private void createLinksFromSnapshotDirToDataDir(
- File sourceDir, String seqBaseDir, String unseqBaseDir)
+ private void createLinksFromSnapshotDirToDataDir(File sourceDir)
throws IOException, DiskSpaceInsufficientException {
- File[] files = sourceDir.listFiles();
- if (files == null) {
- return;
+ File seqFileDir = new File(sourceDir, "sequence" + File.separator +
storageGroupName);
+ File unseqFileDir = new File(sourceDir, "unsequence" + File.separator +
storageGroupName);
+ if (!seqFileDir.exists() && !unseqFileDir.exists()) {
+ throw new IOException(
+ String.format(
+ "Cannot find %s or %s",
+ seqFileDir.getAbsolutePath(), unseqFileDir.getAbsolutePath()));
}
- for (File sourceFile : files) {
- String[] fileInfo =
sourceFile.getName().split(SnapshotTaker.SNAPSHOT_FILE_INFO_SEP_STR);
- if (fileInfo.length != 5) {
- continue;
- }
- boolean seq = fileInfo[0].equals("seq");
- String timePartition = fileInfo[3];
- String fileName = fileInfo[4];
- String nextDataDir =
- seq
- ? DirectoryManager.getInstance().getNextFolderForSequenceFile()
- :
DirectoryManager.getInstance().getNextFolderForUnSequenceFile();
- File baseDir = new File(nextDataDir, seq ? seqBaseDir : unseqBaseDir);
- File targetDirForThisTimePartition = new File(baseDir, timePartition);
- if (!targetDirForThisTimePartition.exists() &&
!targetDirForThisTimePartition.mkdirs()) {
- throw new IOException(
- String.format("Failed to make directory %s",
targetDirForThisTimePartition));
+
+ File[] seqRegionDirs = seqFileDir.listFiles();
+ if (seqRegionDirs != null && seqRegionDirs.length > 0) {
+ for (File seqRegionDir : seqRegionDirs) {
+ if (!seqRegionDir.isDirectory()) {
+ LOGGER.info("Skip {}, because it is not a directory", seqRegionDir);
+ continue;
+ }
+ File[] seqPartitionDirs = seqRegionDir.listFiles();
+ if (seqPartitionDirs != null && seqPartitionDirs.length > 0) {
+ for (File seqPartitionDir : seqPartitionDirs) {
+ String[] splitPath =
+ seqPartitionDir
+ .getAbsolutePath()
+ .split(File.separator.equals("\\") ? "\\\\" :
File.separator);
+ long timePartition = Long.parseLong(splitPath[splitPath.length -
1]);
+ File[] files = seqPartitionDir.listFiles();
+ if (files != null && files.length > 0) {
+ Arrays.sort(files, Comparator.comparing(File::getName));
+ String currDir =
DirectoryManager.getInstance().getNextFolderForSequenceFile();
+ for (File file : files) {
+ if (file.getName().endsWith(".tsfile")) {
+ currDir =
DirectoryManager.getInstance().getNextFolderForSequenceFile();
+ }
+ File targetFile =
+ new File(
+ currDir,
+ storageGroupName
+ + File.separator
+ + dataRegionId
+ + File.separator
+ + timePartition
+ + File.separator
+ + file.getName());
+ if (!targetFile.getParentFile().exists() &&
!targetFile.getParentFile().mkdirs()) {
+ throw new IOException(
+ String.format("Failed to create dir %s",
targetFile.getParent()));
+ }
+ Files.createLink(targetFile.toPath(), file.toPath());
+ }
+ }
+ }
+ }
}
+ }
- File targetFile = new File(targetDirForThisTimePartition, fileName);
- try {
- Files.createLink(targetFile.toPath(), sourceFile.toPath());
- } catch (IOException e) {
- throw new IOException(
- String.format("Failed to create hard link from %s to %s",
sourceFile, targetFile), e);
+ File[] unseqRegionDirs = unseqFileDir.listFiles();
+ if (unseqRegionDirs != null && unseqRegionDirs.length > 0) {
+ for (File unseqRegionDir : unseqRegionDirs) {
+ if (!unseqRegionDir.isDirectory()) {
+ LOGGER.info("Skip {}, because it is not a directory",
unseqRegionDir);
+ continue;
+ }
+ File[] unseqPartitionDirs = unseqRegionDir.listFiles();
+ if (unseqPartitionDirs != null && unseqPartitionDirs.length > 0) {
+ for (File unseqPartitionDir : unseqPartitionDirs) {
+ String[] splitPath =
+ unseqPartitionDir
+ .getAbsolutePath()
+ .split(File.separator.equals("\\") ? "\\\\" :
File.separator);
+ long timePartition = Long.parseLong(splitPath[splitPath.length -
1]);
+ File[] files = unseqPartitionDir.listFiles();
+ if (files != null && files.length > 0) {
+ Arrays.sort(files, Comparator.comparing(File::getName));
+ String currDir =
DirectoryManager.getInstance().getNextFolderForUnSequenceFile();
+ for (File file : files) {
+ if (file.getName().endsWith(".tsfile")) {
+ currDir =
DirectoryManager.getInstance().getNextFolderForUnSequenceFile();
+ }
+ File targetFile =
+ new File(
+ currDir,
+ storageGroupName
+ + File.separator
+ + dataRegionId
+ + File.separator
+ + timePartition
+ + File.separator
+ + file.getName());
+ if (!targetFile.getParentFile().exists() &&
!targetFile.getParentFile().mkdirs()) {
+ throw new IOException(
+ String.format("Failed to create dir %s",
targetFile.getParent()));
+ }
+ Files.createLink(targetFile.toPath(), file.toPath());
+ }
+ }
+ }
+ }
}
}
}
diff --git
a/server/src/main/java/org/apache/iotdb/db/engine/snapshot/SnapshotTaker.java
b/server/src/main/java/org/apache/iotdb/db/engine/snapshot/SnapshotTaker.java
index a05f8f7182..02f69266c6 100644
---
a/server/src/main/java/org/apache/iotdb/db/engine/snapshot/SnapshotTaker.java
+++
b/server/src/main/java/org/apache/iotdb/db/engine/snapshot/SnapshotTaker.java
@@ -35,6 +35,7 @@ import java.io.IOException;
import java.nio.file.Files;
import java.util.LinkedList;
import java.util.List;
+import java.util.Objects;
/**
* SnapshotTaker takes data snapshot for a DataRegion in one time. It does so
by creating hard link
@@ -46,6 +47,8 @@ public class SnapshotTaker {
private static final Logger LOGGER =
LoggerFactory.getLogger(SnapshotTaker.class);
private final DataRegion dataRegion;
public static String SNAPSHOT_FILE_INFO_SEP_STR = "_";
+ private File seqBaseDir;
+ private File unseqBaseDir;
public SnapshotTaker(DataRegion dataRegion) {
this.dataRegion = dataRegion;
@@ -56,11 +59,27 @@ public class SnapshotTaker {
File snapshotDir = new File(snapshotDirPath);
if (snapshotDir.exists()
&& snapshotDir.listFiles() != null
- && snapshotDir.listFiles().length > 0) {
+ && Objects.requireNonNull(snapshotDir.listFiles()).length > 0) {
// the directory should be empty or not exists
throw new DirectoryNotLegalException(
String.format("%s already exists and is not empty",
snapshotDirPath));
}
+ seqBaseDir =
+ new File(
+ snapshotDir,
+ "sequence"
+ + File.separator
+ + dataRegion.getLogicalStorageGroupName()
+ + File.separator
+ + dataRegion.getDataRegionId());
+ unseqBaseDir =
+ new File(
+ snapshotDir,
+ "unsequence"
+ + File.separator
+ + dataRegion.getLogicalStorageGroupName()
+ + File.separator
+ + dataRegion.getDataRegionId());
if (!snapshotDir.exists() && !snapshotDir.mkdirs()) {
throw new IOException(String.format("Failed to create directory %s",
snapshotDir));
@@ -78,7 +97,7 @@ public class SnapshotTaker {
List<String> seqDataDirs = getAllDataDirOfOnePartition(true,
timePartition);
try {
- createFileSnapshot(seqDataDirs, snapshotDir, true, timePartition);
+ createFileSnapshot(seqDataDirs, true, timePartition);
} catch (IOException e) {
LOGGER.error("Fail to create snapshot", e);
cleanUpWhenFail(snapshotDir);
@@ -88,7 +107,7 @@ public class SnapshotTaker {
List<String> unseqDataDirs = getAllDataDirOfOnePartition(false,
timePartition);
try {
- createFileSnapshot(unseqDataDirs, snapshotDir, false, timePartition);
+ createFileSnapshot(unseqDataDirs, false, timePartition);
} catch (IOException e) {
LOGGER.error("Fail to create snapshot", e);
cleanUpWhenFail(snapshotDir);
@@ -124,9 +143,15 @@ public class SnapshotTaker {
return resultDirs;
}
- private void createFileSnapshot(
- List<String> sourceDirPaths, File targetDir, boolean sequence, long
timePartition)
+ private void createFileSnapshot(List<String> sourceDirPaths, boolean
sequence, long timePartition)
throws IOException {
+ File timePartitionDir =
+ new File(sequence ? seqBaseDir : unseqBaseDir,
String.valueOf(timePartition));
+ if (!timePartitionDir.exists() && !timePartitionDir.mkdirs()) {
+ throw new IOException(
+ String.format("%s not exists and cannot create it",
timePartitionDir.getAbsolutePath()));
+ }
+
for (String sourceDirPath : sourceDirPaths) {
File sourceDir = new File(sourceDirPath);
if (!sourceDir.exists()) {
@@ -149,17 +174,7 @@ public class SnapshotTaker {
}
for (File file : files) {
- String newFileName =
- (sequence ? "seq" : "unseq")
- + SNAPSHOT_FILE_INFO_SEP_STR
- + dataRegion.getLogicalStorageGroupName()
- + SNAPSHOT_FILE_INFO_SEP_STR
- + dataRegion.getDataRegionId()
- + SNAPSHOT_FILE_INFO_SEP_STR
- + timePartition
- + SNAPSHOT_FILE_INFO_SEP_STR
- + file.getName();
- File linkFile = new File(targetDir, newFileName);
+ File linkFile = new File(timePartitionDir, file.getName());
Files.createLink(linkFile.toPath(), file.toPath());
}
}