summaryrefslogtreecommitdiff
path: root/src/main/java/com/keuin/kbackupfabric/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/keuin/kbackupfabric/util')
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/FilesystemUtil.java38
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/BackupFilesystemUtil.java9
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactory.java15
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/incremental/manager/IncrementalBackupStorageManager.java43
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/name/IncrementalBackupFileNameEncoder.java2
5 files changed, 97 insertions, 10 deletions
diff --git a/src/main/java/com/keuin/kbackupfabric/util/FilesystemUtil.java b/src/main/java/com/keuin/kbackupfabric/util/FilesystemUtil.java
index 7f74725..f245cff 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/FilesystemUtil.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/FilesystemUtil.java
@@ -1,6 +1,9 @@
package com.keuin.kbackupfabric.util;
import java.io.File;
+import java.io.IOException;
+
+import static org.apache.commons.io.FileUtils.forceDelete;
public class FilesystemUtil {
@@ -22,12 +25,43 @@ public class FilesystemUtil {
public static long getFileSizeBytes(String filePath) {
long fileSize = -1;
- try{
+ try {
File backupZipFile = new File(filePath);
fileSize = backupZipFile.length();
- } catch (SecurityException ignored){
+ } catch (SecurityException ignored) {
}
return fileSize;
}
+ public static boolean forceDeleteDirectory(File levelDirFile) throws IOException {
+ int failedCounter = 0;
+ final int MAX_RETRY_TIMES = 20;
+ IOException exception = null;
+ while (failedCounter < MAX_RETRY_TIMES) {
+ System.gc();
+ if (!levelDirFile.delete() && levelDirFile.exists()) {
+ System.gc();
+ try {
+ forceDelete(levelDirFile); // Try to force delete.
+ } catch (IOException e) {
+ exception = e;
+ }
+ }
+ if (!levelDirFile.exists())
+ break;
+ ++failedCounter;
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException ignored) {
+ }
+ }
+ if (exception != null)
+ throw exception;
+ if (levelDirFile.exists()) {
+ PrintUtil.error(String.format("Cannot restore: failed to delete old level %s .", levelDirFile.getName()));
+ return false;
+ }
+ return true;
+ }
+
}
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/BackupFilesystemUtil.java b/src/main/java/com/keuin/kbackupfabric/util/backup/BackupFilesystemUtil.java
index c1aa5fe..837b638 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/BackupFilesystemUtil.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/BackupFilesystemUtil.java
@@ -14,7 +14,8 @@ import java.util.regex.Pattern;
*/
public final class BackupFilesystemUtil {
- private static final String backupSaveDirectoryName = "backups";
+ private static final String BACKUP_SAVE_DIRECTORY_NAME = "backups";
+ private static final String INCREMENTAL_BASE_DIRECTORY_NAME = "incremental";
private static final String backupFileNamePrefix = "kbackup-";
@Deprecated
@@ -43,7 +44,11 @@ public final class BackupFilesystemUtil {
}
public static File getBackupSaveDirectory(MinecraftServer server) {
- return new File(server.getRunDirectory(), backupSaveDirectoryName);
+ return new File(server.getRunDirectory(), BACKUP_SAVE_DIRECTORY_NAME);
+ }
+
+ public static File getIncrementalBackupBaseDirectory(MinecraftServer server) {
+ return new File(server.getRunDirectory(), INCREMENTAL_BASE_DIRECTORY_NAME);
}
public static String getLevelPath(MinecraftServer server) {
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactory.java b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactory.java
index 627cb5c..2f3761c 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactory.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactory.java
@@ -1,5 +1,6 @@
package com.keuin.kbackupfabric.util.backup.incremental;
+import com.keuin.kbackupfabric.util.PrintUtil;
import com.keuin.kbackupfabric.util.backup.incremental.identifier.FileIdentifierProvider;
import com.keuin.kbackupfabric.util.backup.incremental.identifier.ObjectIdentifier;
@@ -23,26 +24,32 @@ public class ObjectCollectionFactory<T extends ObjectIdentifier> {
this.identifierFactory = identifierFactory;
}
- public ObjectCollection fromDirectory(File directory) throws IOException {
+ public ObjectCollection fromDirectory(File directory, Set<String> ignoredFiles) throws IOException {
final Set<ObjectElement> subFiles = new HashSet<>();
final Map<String, ObjectCollection> subCollections = new HashMap<>();
if (!Objects.requireNonNull(directory).isDirectory())
throw new IllegalArgumentException("given file is not a directory");
- for (Iterator<Path> iter = Files.walk(directory.toPath(), 1).iterator(); iter.hasNext();) {
+ for (Iterator<Path> iter = Files.walk(directory.toPath(), 1).iterator(); iter.hasNext(); ) {
Path path = iter.next();
if (Files.isSameFile(path, directory.toPath()))
continue;
File file = path.toFile();
if (file.isDirectory()) {
- subCollections.put(file.getName(), fromDirectory(file));
- } else {
+ subCollections.put(file.getName(), fromDirectory(file, ignoredFiles));
+ } else if (!ignoredFiles.contains(file.getName())) {
subFiles.add(new ObjectElement(file.getName(), identifierFactory.fromFile(file)));
+ } else {
+ PrintUtil.info(String.format("Skipping file %s.", file.getName()));
}
}
return new ObjectCollection(directory.getName(), subFiles, subCollections);
}
+ public ObjectCollection fromDirectory(File directory) throws IOException {
+ return fromDirectory(directory, Collections.emptySet());
+ }
+
}
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/manager/IncrementalBackupStorageManager.java b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/manager/IncrementalBackupStorageManager.java
index cd15499..a4271c6 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/manager/IncrementalBackupStorageManager.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/manager/IncrementalBackupStorageManager.java
@@ -1,9 +1,11 @@
package com.keuin.kbackupfabric.util.backup.incremental.manager;
+import com.keuin.kbackupfabric.util.PrintUtil;
import com.keuin.kbackupfabric.util.backup.incremental.ObjectCollection;
import com.keuin.kbackupfabric.util.backup.incremental.ObjectElement;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -11,6 +13,8 @@ import java.nio.file.Paths;
import java.util.Map;
import java.util.Objects;
+import static org.apache.commons.io.FileUtils.forceDelete;
+
public class IncrementalBackupStorageManager {
private final Path backupStorageBase;
@@ -63,13 +67,50 @@ public class IncrementalBackupStorageManager {
int copyCount = 0;
+ // touch directory
+ if (!collectionBasePath.exists()) {
+ int retryCounter = 0;
+ boolean success = false;
+ while (retryCounter++ < 5) {
+ if (collectionBasePath.mkdirs()) {
+ success = true;
+ break;
+ }
+ }
+ if (!success) {
+ throw new IOException("Failed to create directory " + collectionBasePath.getAbsolutePath());
+ }
+ }
+
// copy sub files
for (Map.Entry<String, ObjectElement> entry : collection.getElementMap().entrySet()) {
File copySource = new File(backupStorageBase.toFile(), entry.getValue().getIdentifier().getIdentification());
+ File copyTarget = new File(collectionBasePath.getAbsolutePath(), entry.getKey());
+
if (!baseContainsObject(entry.getValue())) {
throw new IOException(String.format("File %s does not exist in the base.", copySource.getName()));
}
- Files.copy(copySource.toPath(), Paths.get(collectionBasePath.getAbsolutePath(), entry.getKey()));
+ if (copyTarget.exists()) {
+ boolean successDeleting = false;
+ for (int i = 0; i < 5; ++i) {
+ try {
+ forceDelete(copyTarget);
+ successDeleting = true;
+ break;
+ } catch (FileNotFoundException ignored) {
+ break;
+ } catch (IOException e) {
+ PrintUtil.error(String.format("Failed to delete file %s, retry.", copyTarget.getName()));
+ }
+ }
+ if (!successDeleting) {
+ String msg = String.format("Failed to delete file %s.", copyTarget.getName());
+ PrintUtil.error(msg);
+ throw new IOException(msg);
+ }
+ }
+
+ Files.copy(copySource.toPath(), copyTarget.toPath());
++copyCount;
}
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/name/IncrementalBackupFileNameEncoder.java b/src/main/java/com/keuin/kbackupfabric/util/backup/name/IncrementalBackupFileNameEncoder.java
index a0d4128..3c35201 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/name/IncrementalBackupFileNameEncoder.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/name/IncrementalBackupFileNameEncoder.java
@@ -6,7 +6,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class IncrementalBackupFileNameEncoder implements BackupFileNameEncoder {
- private static final String backupFileNamePrefix = "incremental-";
+ private static final String backupFileNamePrefix = "incremental";
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss");
// TODO: make this private and use singleton pattern