diff options
Diffstat (limited to 'src/main/java/com/keuin/kbackupfabric/util/backup/incremental')
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); + }); + } + } |