summaryrefslogtreecommitdiff
path: root/src/main/java/com/keuin/kbackupfabric/util/backup
diff options
context:
space:
mode:
authorKeuin <[email protected]>2021-01-14 13:00:52 +0800
committerkeuin <[email protected]>2021-01-14 13:00:52 +0800
commit6baece29cccc906651331cbf8a90a06f8cee045b (patch)
tree37a33912b7b057376a4c2845738f076ac7da3467 /src/main/java/com/keuin/kbackupfabric/util/backup
parent5410762b8272feca0680f7a48f895714b91e3df7 (diff)
Fix a minor naming bug.
Code refactor. Improve test.
Diffstat (limited to 'src/main/java/com/keuin/kbackupfabric/util/backup')
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/BackupFilesystemUtil.java4
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/FileIdentifierProvider.java7
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256Identifier.java20
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/SingleHashIdentifier.java16
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/StorageObjectLoader.java25
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/incremental/manager/IncrementalBackupStorageManager.java52
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/name/BackupFileNameEncoder.java8
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/name/IncrementalBackupFileNameEncoder.java2
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/name/PrimitiveBackupFileNameEncoder.java2
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/provider/AvailableBackupProvider.java8
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/provider/IncrementalBackupInformation.java13
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/provider/PrimitiveBackupInformation.java14
12 files changed, 158 insertions, 13 deletions
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 837b638..7106ad2 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/BackupFilesystemUtil.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/BackupFilesystemUtil.java
@@ -23,10 +23,6 @@ public final class BackupFilesystemUtil {
return backupFileNamePrefix;
}
- @Deprecated
- public static String getBackupFileName(String backupName) {
- return backupFileNamePrefix + backupName + ".zip";
- }
// @Deprecated
// public static String getBackupName(String backupFileName) {
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/FileIdentifierProvider.java b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/FileIdentifierProvider.java
index 9a03371..3fbe284 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/FileIdentifierProvider.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/FileIdentifierProvider.java
@@ -4,5 +4,12 @@ import java.io.File;
import java.io.IOException;
public interface FileIdentifierProvider<T extends ObjectIdentifier> {
+ /**
+ * Generate file identifier from a random file. The file is not necessarily in the object base.
+ *
+ * @param file the file.
+ * @return the file identifier.
+ * @throws IOException when an I/O error occurs.
+ */
T fromFile(File file) throws IOException;
}
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256Identifier.java b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256Identifier.java
index cbf1bb9..c1c87e1 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256Identifier.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256Identifier.java
@@ -1,5 +1,7 @@
package com.keuin.kbackupfabric.util.backup.incremental.identifier;
+import com.keuin.kbackupfabric.util.BytesUtil;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -16,20 +18,34 @@ public class Sha256Identifier extends SingleHashIdentifier {
private static final int SHA256_LENGTH = 32;
private static final Sha256Identifier DUMMY = new Sha256Identifier(new byte[SHA256_LENGTH]); // only for using its hash method
private static final FileIdentifierProvider<Sha256Identifier> factory = Sha256Identifier::fromFile;
+ private static final String marker = "S2";
public static Sha256Identifier fromFile(File file) throws IOException {
- if (!Objects.requireNonNull(file).isFile()) {
+ if (!file.isFile()) {
throw new IllegalArgumentException("file is not a file");
}
return new Sha256Identifier(DUMMY.hash(file));
}
+ /**
+ * Load sha-256 from a named file. Only used in StorageObjectLoader.
+ *
+ * @param fileName the file name.
+ * @return identifier.
+ */
+ static Sha256Identifier fromFileName(String fileName) {
+ if (!fileName.matches(marker + "-[0-9A-Fa-f]{32}"))
+ return null;
+ String hexString = fileName.substring(marker.length() + 1);
+ return new Sha256Identifier(BytesUtil.hexToBytes(hexString));
+ }
+
public static FileIdentifierProvider<Sha256Identifier> getFactory() {
return factory;
}
protected Sha256Identifier(byte[] hash) {
- super(hash);
+ super(hash, marker);
Objects.requireNonNull(hash);
if (hash.length != SHA256_LENGTH) {
throw new IllegalStateException(String.format("SHA256 must be %d bytes", SHA256_LENGTH));
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/SingleHashIdentifier.java b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/SingleHashIdentifier.java
index 3b96f79..0f62f2b 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/SingleHashIdentifier.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/SingleHashIdentifier.java
@@ -5,6 +5,7 @@ import com.keuin.kbackupfabric.util.BytesUtil;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
+import java.util.Objects;
/**
* A simple identifier based on a single hash function.
@@ -13,9 +14,13 @@ import java.util.Arrays;
public abstract class SingleHashIdentifier implements ObjectIdentifier {
private final byte[] hash;
+ private final String type;
- protected SingleHashIdentifier(byte[] hash) {
+ protected SingleHashIdentifier(byte[] hash, String type) {
+ Objects.requireNonNull(hash);
+ Objects.requireNonNull(type);
this.hash = Arrays.copyOf(hash, hash.length);
+ this.type = type;
}
/**
@@ -28,7 +33,7 @@ public abstract class SingleHashIdentifier implements ObjectIdentifier {
@Override
public String getIdentification() {
- return BytesUtil.bytesToHex(hash);
+ return type + "-" + BytesUtil.bytesToHex(hash);
}
@Override
@@ -38,4 +43,11 @@ public abstract class SingleHashIdentifier implements ObjectIdentifier {
}
return Arrays.equals(hash, ((SingleHashIdentifier) obj).hash);
}
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(type);
+ result = 31 * result + Arrays.hashCode(hash);
+ return result;
+ }
}
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/StorageObjectLoader.java b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/StorageObjectLoader.java
new file mode 100644
index 0000000..96bc295
--- /dev/null
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/StorageObjectLoader.java
@@ -0,0 +1,25 @@
+package com.keuin.kbackupfabric.util.backup.incremental.identifier;
+
+import java.io.File;
+import java.util.Objects;
+
+public class StorageObjectLoader {
+ /**
+ * Get identifier from storage file.
+ *
+ * @param file storage file.
+ * @return identifier. If failed, return null.
+ */
+ public static ObjectIdentifier asIdentifier(File file) {
+ Objects.requireNonNull(file);
+ String fileName = file.getName();
+ ObjectIdentifier identifier;
+
+ identifier = Sha256Identifier.fromFileName(fileName);
+ if (identifier != null)
+ return identifier;
+
+ // Add more identifiers.
+ return null;
+ }
+}
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 6c359c6..6fd339b 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
@@ -3,6 +3,8 @@ 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 com.keuin.kbackupfabric.util.backup.incremental.identifier.ObjectIdentifier;
+import com.keuin.kbackupfabric.util.backup.incremental.identifier.StorageObjectLoader;
import java.io.File;
import java.io.FileNotFoundException;
@@ -10,14 +12,15 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
import static org.apache.commons.io.FileUtils.forceDelete;
public class IncrementalBackupStorageManager {
private final Path backupStorageBase;
+ private final Map<ObjectIdentifier, File> map = new HashMap<>();
+ private boolean loaded = false;
public IncrementalBackupStorageManager(Path backupStorageBase) {
this.backupStorageBase = backupStorageBase;
@@ -127,8 +130,31 @@ public class IncrementalBackupStorageManager {
return copyCount;
}
+ public int cleanUnusedObjects(Iterable<ObjectCollection> collectionIterable) {
+ // construct object list in memory
+ Set<String> objects = new HashSet<>();
+// backupStorageBase
+
+ for (ObjectCollection collection : collectionIterable) {
+ for (ObjectElement ele : collection.getElementMap().values()) {
+
+ }
+ }
+ throw new RuntimeException("not impl");
+ }
+
+ /**
+ * Check all objects, return unused ones.
+ *
+ * @return the unused ones.
+ */
+ private Map<ObjectIdentifier, File> markUnusedObjects() {
+ throw new RuntimeException("not impl");
+ }
+
/**
* Check if the backup base contains given element.
+ *
* @param objectElement the element.
* @return true or false.
*/
@@ -137,4 +163,26 @@ public class IncrementalBackupStorageManager {
return (new File(backupStorageBase.toFile(), objectElement.getIdentifier().getIdentification())).exists();
}
+ private void lazyLoadStorage() throws IOException {
+ if (!loaded) {
+ loadStorage();
+ loaded = true;
+ }
+ }
+
+ private synchronized void loadStorage() throws IOException {
+ map.clear();
+ Files.walk(backupStorageBase, 1).forEach(path -> {
+ File file = path.toFile();
+ ObjectIdentifier identifier = StorageObjectLoader.asIdentifier(file);
+ if (identifier == null) {
+ map.clear();
+ throw new IllegalStateException(String.format(
+ "Bad storage object %s: cannot recognize identifier.", file.getName()
+ ));
+ }
+ map.put(identifier, file);
+ });
+ }
+
}
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/name/BackupFileNameEncoder.java b/src/main/java/com/keuin/kbackupfabric/util/backup/name/BackupFileNameEncoder.java
index 972403b..8ebc7ff 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/name/BackupFileNameEncoder.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/name/BackupFileNameEncoder.java
@@ -18,13 +18,19 @@ public interface BackupFileNameEncoder {
/**
* Extract custom and backup time from backup file name.
+ *
* @param fileName the backup file name.
* @return the information. If the given file name is invalid, return null.
*/
BackupBasicInformation decode(String fileName);
+ default boolean isValidFileName(String fileName) {
+ return decode(fileName) != null;
+ }
+
/**
* Check if the given string is a valid custom backup name.
+ *
* @param customName the custom backup name.
* @return if the name is valid.
*/
@@ -45,7 +51,7 @@ public interface BackupFileNameEncoder {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm.ss");
- BackupBasicInformation(String customName, LocalDateTime time) {
+ protected BackupBasicInformation(String customName, LocalDateTime time) {
this.customName = customName;
this.time = time;
}
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 3c35201..926f47c 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
@@ -24,7 +24,7 @@ public class IncrementalBackupFileNameEncoder implements BackupFileNameEncoder {
@Override
public BackupFileNameEncoder.BackupBasicInformation decode(String fileName) {
Pattern pattern = Pattern.compile(
- backupFileNamePrefix + "-" + "([0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2})_(.+)\\.kbi"
+ "^" + backupFileNamePrefix + "-" + "([0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2})_(.+)\\.kbi" + "$"
);
Matcher matcher = pattern.matcher(fileName);
if (matcher.find()) {
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/name/PrimitiveBackupFileNameEncoder.java b/src/main/java/com/keuin/kbackupfabric/util/backup/name/PrimitiveBackupFileNameEncoder.java
index bcba114..ef15ae7 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/name/PrimitiveBackupFileNameEncoder.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/name/PrimitiveBackupFileNameEncoder.java
@@ -20,7 +20,7 @@ public class PrimitiveBackupFileNameEncoder implements BackupFileNameEncoder {
@Override
public BackupBasicInformation decode(String fileName) {
Pattern pattern = Pattern.compile(
- backupFileNamePrefix + "-" + "([0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2})_(.+)\\.zip"
+ "^" + backupFileNamePrefix + "-" + "([0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2})_(.+)\\.zip" + "$"
);
Matcher matcher = pattern.matcher(fileName);
if (matcher.find()) {
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/provider/AvailableBackupProvider.java b/src/main/java/com/keuin/kbackupfabric/util/backup/provider/AvailableBackupProvider.java
new file mode 100644
index 0000000..caa0e84
--- /dev/null
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/provider/AvailableBackupProvider.java
@@ -0,0 +1,8 @@
+package com.keuin.kbackupfabric.util.backup.provider;
+
+/**
+ * List all backup in disk. Provide their basic information as soon as possible.
+ */
+public class AvailableBackupProvider {
+ // TODO: remove obsolete impl. in command user interface. Use this instead.
+}
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/provider/IncrementalBackupInformation.java b/src/main/java/com/keuin/kbackupfabric/util/backup/provider/IncrementalBackupInformation.java
new file mode 100644
index 0000000..861d210
--- /dev/null
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/provider/IncrementalBackupInformation.java
@@ -0,0 +1,13 @@
+package com.keuin.kbackupfabric.util.backup.provider;
+
+import com.keuin.kbackupfabric.util.backup.name.BackupFileNameEncoder;
+
+import java.time.LocalDateTime;
+
+public class IncrementalBackupInformation extends BackupFileNameEncoder.BackupBasicInformation {
+ // TODO: show total size for incremental backup
+
+ public IncrementalBackupInformation(String customName, LocalDateTime time) {
+ super(customName, time);
+ }
+}
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/provider/PrimitiveBackupInformation.java b/src/main/java/com/keuin/kbackupfabric/util/backup/provider/PrimitiveBackupInformation.java
new file mode 100644
index 0000000..d3d2db8
--- /dev/null
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/provider/PrimitiveBackupInformation.java
@@ -0,0 +1,14 @@
+package com.keuin.kbackupfabric.util.backup.provider;
+
+import com.keuin.kbackupfabric.util.backup.name.BackupFileNameEncoder;
+
+import java.time.LocalDateTime;
+
+public class PrimitiveBackupInformation extends BackupFileNameEncoder.BackupBasicInformation {
+ public final long sizeBytes;
+
+ public PrimitiveBackupInformation(String customName, LocalDateTime time, long sizeBytes) {
+ super(customName, time);
+ this.sizeBytes = sizeBytes;
+ }
+}