summaryrefslogtreecommitdiff
path: root/src/main/java/com/keuin/kbackupfabric/util/backup/incremental
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/keuin/kbackupfabric/util/backup/incremental')
-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
5 files changed, 114 insertions, 6 deletions
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);
+ });
+ }
+
}