From 8b05c48d76bbb05c2b440e57df1d9b3323edc598 Mon Sep 17 00:00:00 2001 From: Keuin Date: Thu, 17 Dec 2020 00:21:13 +0800 Subject: Implementing incremental backup. (in progress) --- .../java/com/keuin/kbackupfabric/KBCommands.java | 13 +++++---- .../kbackupfabric/operation/BackupOperation.java | 8 ++---- .../util/backup/BackupFilesystemUtil.java | 2 +- .../builder/ObjectTreeBackupFileNameBuilder.java | 4 +-- .../builder/PrimitiveZipBackupFileNameBuilder.java | 4 +-- .../util/backup/inc/ObjectCollectionManager.java | 11 ++++++++ .../backup/inc/identifier/ObjectIdentifier.java | 9 ++++++ .../inc/identifier/SingleHashIdentifier.java | 32 ++++++++++++++++++++++ 8 files changed, 67 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/keuin/kbackupfabric/util/backup/inc/ObjectCollectionManager.java create mode 100644 src/main/java/com/keuin/kbackupfabric/util/backup/inc/identifier/ObjectIdentifier.java create mode 100644 src/main/java/com/keuin/kbackupfabric/util/backup/inc/identifier/SingleHashIdentifier.java diff --git a/src/main/java/com/keuin/kbackupfabric/KBCommands.java b/src/main/java/com/keuin/kbackupfabric/KBCommands.java index bc04291..571333f 100644 --- a/src/main/java/com/keuin/kbackupfabric/KBCommands.java +++ b/src/main/java/com/keuin/kbackupfabric/KBCommands.java @@ -8,21 +8,24 @@ import com.keuin.kbackupfabric.operation.abstracts.i.Invokable; import com.keuin.kbackupfabric.operation.backup.BackupMethod; import com.keuin.kbackupfabric.operation.backup.IncrementalBackupMethod; import com.keuin.kbackupfabric.operation.backup.PrimitiveBackupMethod; +import com.keuin.kbackupfabric.util.PrintUtil; import com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil; +import com.keuin.kbackupfabric.util.backup.BackupNameTimeFormatter; import com.keuin.kbackupfabric.util.backup.BackupType; import com.keuin.kbackupfabric.util.backup.suggestion.BackupNameSuggestionProvider; -import com.keuin.kbackupfabric.util.backup.BackupNameTimeFormatter; -import com.keuin.kbackupfabric.util.PrintUtil; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.ServerCommandSource; import java.io.File; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; -import static com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil.*; import static com.keuin.kbackupfabric.util.PrintUtil.*; +import static com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil.*; public final class KBCommands { @@ -298,7 +301,7 @@ public final class KBCommands { } else { ++i; } - msgInfo(context, String.format("The most recent backup: [%d] %s , size: %s", i, backupName, humanFileSize(prevBackupFile.length()))); + msgInfo(context, String.format("The most recent backup: [%d] %s , size: %s", i, backupName, getFriendlyFileSizeString(prevBackupFile.length()))); } catch (NullPointerException e) { msgInfo(context, "There are no backups available."); } catch (SecurityException ignored) { diff --git a/src/main/java/com/keuin/kbackupfabric/operation/BackupOperation.java b/src/main/java/com/keuin/kbackupfabric/operation/BackupOperation.java index d03c347..465b293 100644 --- a/src/main/java/com/keuin/kbackupfabric/operation/BackupOperation.java +++ b/src/main/java/com/keuin/kbackupfabric/operation/BackupOperation.java @@ -1,12 +1,8 @@ package com.keuin.kbackupfabric.operation; -import com.keuin.kbackupfabric.exception.ZipUtilException; -import com.keuin.kbackupfabric.metadata.BackupMetadata; import com.keuin.kbackupfabric.operation.abstracts.InvokableAsyncBlockingOperation; import com.keuin.kbackupfabric.operation.backup.BackupMethod; import com.keuin.kbackupfabric.util.PrintUtil; -import com.keuin.kbackupfabric.util.backup.builder.BackupFileNameBuilder; -import com.keuin.kbackupfabric.util.backup.formatter.BackupFileNameFormatter; import com.mojang.brigadier.context.CommandContext; import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.ServerCommandSource; @@ -17,8 +13,8 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import static com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil.*; import static com.keuin.kbackupfabric.util.PrintUtil.msgInfo; +import static com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil.*; public class BackupOperation extends InvokableAsyncBlockingOperation { @@ -64,7 +60,7 @@ public class BackupOperation extends InvokableAsyncBlockingOperation { long timeElapsedMillis = System.currentTimeMillis() - startTime; String msgText = String.format("Backup finished. Time elapsed: %.2fs.", timeElapsedMillis / 1000.0); File backupZipFile = new File(backupSaveDirectory, backupFileName); - msgText += String.format(" File size: %s.", humanFileSize(result.getBackupSizeBytes())); + msgText += String.format(" File size: %s.", getFriendlyFileSizeString(result.getBackupSizeBytes())); PrintUtil.msgInfo(context, msgText, true); } else { // failed 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 54c2f58..d0c7500 100644 --- a/src/main/java/com/keuin/kbackupfabric/util/backup/BackupFilesystemUtil.java +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/BackupFilesystemUtil.java @@ -70,7 +70,7 @@ public final class BackupFilesystemUtil { return -1; } - public static String humanFileSize(long size) { + public static String getFriendlyFileSizeString(long size) { double fileSize = size * 1.0 / 1024 / 1024; // Default unit is MB if (fileSize > 1000) //msgInfo(context, String.format("File size: %.2fGB", fileSize / 1024)); diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/builder/ObjectTreeBackupFileNameBuilder.java b/src/main/java/com/keuin/kbackupfabric/util/backup/builder/ObjectTreeBackupFileNameBuilder.java index 3c15741..c3d8257 100644 --- a/src/main/java/com/keuin/kbackupfabric/util/backup/builder/ObjectTreeBackupFileNameBuilder.java +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/builder/ObjectTreeBackupFileNameBuilder.java @@ -8,13 +8,13 @@ import java.time.LocalDateTime; public class ObjectTreeBackupFileNameBuilder implements BackupFileNameBuilder { private static final ObjectTreeBackupFileNameBuilder instance = new ObjectTreeBackupFileNameBuilder(); - public static ObjectTreeBackupFileNameBuilder getInstance() { + public static ObjectTreeBackupFileNameBuilder getInstance() { return instance; } @Override public String build(LocalDateTime time, String backupName) { String timeString = BackupNameTimeFormatter.localDateTimeToString(time); - return String.format("%s%s_%s%s", BackupFilesystemUtil.getBackupFileNamePrefix(),timeString,backupName,".json"); + return String.format("%s%s_%s%s", BackupFilesystemUtil.getBackupFileNamePrefix(), timeString, backupName, ".json"); } } diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/builder/PrimitiveZipBackupFileNameBuilder.java b/src/main/java/com/keuin/kbackupfabric/util/backup/builder/PrimitiveZipBackupFileNameBuilder.java index f910c37..6d8b5f5 100644 --- a/src/main/java/com/keuin/kbackupfabric/util/backup/builder/PrimitiveZipBackupFileNameBuilder.java +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/builder/PrimitiveZipBackupFileNameBuilder.java @@ -9,14 +9,14 @@ public class PrimitiveZipBackupFileNameBuilder implements BackupFileNameBuilder private static final PrimitiveZipBackupFileNameBuilder instance = new PrimitiveZipBackupFileNameBuilder(); - public static PrimitiveZipBackupFileNameBuilder getInstance() { + public static PrimitiveZipBackupFileNameBuilder getInstance() { return instance; } @Override public String build(LocalDateTime time, String backupName) { String timeString = BackupNameTimeFormatter.localDateTimeToString(time); - return String.format("%s%s_%s%s", BackupFilesystemUtil.getBackupFileNamePrefix(),timeString,backupName,".zip"); + return String.format("%s%s_%s%s", BackupFilesystemUtil.getBackupFileNamePrefix(), timeString, backupName, ".zip"); } } diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/inc/ObjectCollectionManager.java b/src/main/java/com/keuin/kbackupfabric/util/backup/inc/ObjectCollectionManager.java new file mode 100644 index 0000000..9560261 --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/inc/ObjectCollectionManager.java @@ -0,0 +1,11 @@ +package com.keuin.kbackupfabric.util.backup.inc; + +/** + * Incremental backup is implemented as git-like file collection. + * Files are called `objects`, the collection contains all files distinguished by their + * identifiers. Usually, identifier is the combination of hash and other short information (such as size and another hash). + * The identifier should use hashes that are strong enough, to prevent possible collisions. + */ +public class ObjectCollectionManager { + +} diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/inc/identifier/ObjectIdentifier.java b/src/main/java/com/keuin/kbackupfabric/util/backup/inc/identifier/ObjectIdentifier.java new file mode 100644 index 0000000..079f49d --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/inc/identifier/ObjectIdentifier.java @@ -0,0 +1,9 @@ +package com.keuin.kbackupfabric.util.backup.inc.identifier; + +/** + * The identifier distinguishing files in the object collection. + * It should be based on cryptographic hash function in order to prevent possible attacks to the backup system. + * All identifiers should be immutable and implement their own equals method. + */ +public interface ObjectIdentifier { +} diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/inc/identifier/SingleHashIdentifier.java b/src/main/java/com/keuin/kbackupfabric/util/backup/inc/identifier/SingleHashIdentifier.java new file mode 100644 index 0000000..50b23bb --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/inc/identifier/SingleHashIdentifier.java @@ -0,0 +1,32 @@ +package com.keuin.kbackupfabric.util.backup.inc.identifier; + +import java.io.File; +import java.util.Arrays; + +/** + * A simple identifier based on a single hash function. + */ +public abstract class SingleHashIdentifier implements ObjectIdentifier { + + private final byte[] hash; + + protected SingleHashIdentifier(byte[] hash) { + this.hash = Arrays.copyOf(hash, hash.length); + } + + /** + * The hash function. + * + * @param file the file to be hashed. + * @return the hash bytes. + */ + protected abstract byte[] hash(File file); + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof SingleHashIdentifier)) { + return false; + } + return Arrays.equals(hash, ((SingleHashIdentifier) obj).hash); + } +} -- cgit v1.2.3