diff --git a/src/dorkbox/util/storage/StorageType.java b/src/dorkbox/util/storage/StorageSystem.java similarity index 71% rename from src/dorkbox/util/storage/StorageType.java rename to src/dorkbox/util/storage/StorageSystem.java index da92456..296b35b 100644 --- a/src/dorkbox/util/storage/StorageType.java +++ b/src/dorkbox/util/storage/StorageSystem.java @@ -22,12 +22,13 @@ import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; +import org.slf4j.helpers.NOPLogger; import dorkbox.util.FileUtil; import dorkbox.util.SerializationManager; public -class StorageType { +class StorageSystem { @SuppressWarnings("SpellCheckingInspection") private static final Map storages = new HashMap(1); @@ -36,7 +37,7 @@ class StorageType { @Override public void run() { - StorageType.shutdown(); + StorageSystem.shutdown(); } }); @@ -46,21 +47,28 @@ class StorageType { .addShutdownHook(shutdownHook); } + /** + * Creates a persistent, on-disk storage system. Writes to disk are queued, so it is recommended to NOT edit/change an object after + * it has been put into storage, or whenever it does changes, make sure to put it back into storage (to update the saved record) + */ public static DiskMaker Disk() { return new DiskMaker(); } + /** + * Creates an in-memory only storage system + */ public static MemoryMaker Memory() { return new MemoryMaker(); } /** - * Closes the storage. + * Closes the specified storage system based on the file used */ public static - void close(File file) { + void close(final File file) { synchronized (storages) { Storage storage = storages.get(file); if (storage != null) { @@ -77,24 +85,27 @@ class StorageType { } /** - * Closes the storage. + * Closes the specified storage system */ public static - void close(Storage _storage) { + void close(final Storage storage) { synchronized (storages) { - File file = _storage.getFile(); + File file = storage.getFile(); close(file); } } + /** + * Saves and closes all open storage systems + */ public static void shutdown() { synchronized (storages) { Collection values = storages.values(); for (Storage storage : values) { if (storage instanceof DiskStorage) { - //noinspection StatementWithEmptyBody final DiskStorage diskStorage = (DiskStorage) storage; + //noinspection StatementWithEmptyBody while (!diskStorage.decrementReference()) { } diskStorage.close(); @@ -104,6 +115,11 @@ class StorageType { } } + /** + * Closes (if in use) and deletes the specified storage file. + *

+ * The file is checked to see if it is in use by the storage system first, and closes if so. + */ public static void delete(File file) { synchronized (storages) { @@ -116,13 +132,20 @@ class StorageType { } } + /** + * Closes (if in use) and deletes the specified storage. + */ public static void delete(Storage storage) { File file = storage.getFile(); delete(file); } - + /** + * Creates a persistent, on-disk storage system. Writes to disk are queued, so it is recommended to NOT edit/change an object after + * it has been put into storage, or whenever it does changes, make sure to put it back into storage (to update the saved record) + */ + @SuppressWarnings("unused") public static class DiskMaker { private File file; @@ -130,24 +153,64 @@ class StorageType { private boolean readOnly = false; private Logger logger = null; + /** + * Specify the file to write to on disk when saving objects + */ public DiskMaker file(File file) { this.file = FileUtil.normalize(file); return this; } + /** + * Specify the file to write to on disk when saving objects + */ public DiskMaker file(String file) { this.file = FileUtil.normalize(file); return this; } + /** + * Specify the serialization manager to use. This is what serializes the files (which are then saved to disk) + */ public DiskMaker serializer(SerializationManager serializationManager) { this.serializationManager = serializationManager; return this; } + /** + * Mark this storage system as read only + */ + public + DiskMaker readOnly() { + this.readOnly = true; + return this; + } + + /** + * Assigns a logger to use for the storage system. If null, then only errors will be logged to the error console. + */ + public + DiskMaker logger(final Logger logger) { + this.logger = logger; + return this; + } + + /** + * Assigns a No Operation (NOP) logger which will ignore everything. This is not recommended for normal use, as it will also + * suppress serialization errors. + */ + public + DiskMaker nologger() { + this.logger = NOPLogger.NOP_LOGGER; + return this; + } + + /** + * Makes the storage system + */ public Storage make() { if (this.file == null) { @@ -188,23 +251,18 @@ class StorageType { return storage; } } - - public - DiskMaker readOnly() { - this.readOnly = true; - return this; - } - - public - DiskMaker logger(final Logger logger) { - this.logger = logger; - return this; - } } + /** + * Creates an in-memory only storage system + */ public static class MemoryMaker { + + /** + * Makes the storage system + */ public MemoryStorage make() throws IOException { return new MemoryStorage(); diff --git a/test/dorkbox/util/StorageTest.java b/test/dorkbox/util/StorageTest.java index 68be44b..b7a2167 100644 --- a/test/dorkbox/util/StorageTest.java +++ b/test/dorkbox/util/StorageTest.java @@ -33,7 +33,7 @@ import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import dorkbox.util.storage.Storage; -import dorkbox.util.storage.StorageType; +import dorkbox.util.storage.StorageSystem; import io.netty.buffer.ByteBuf; @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -121,23 +121,23 @@ class StorageTest { @Before public void deleteDB() { - StorageType.delete(TEST_DB); + StorageSystem.delete(TEST_DB); } @After public void delete2DB() { - StorageType.delete(TEST_DB); + StorageSystem.delete(TEST_DB); } @Test public void testCreateDB() throws IOException { - Storage storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + Storage storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); int numberOfRecords1 = storage.size(); long size1 = storage.getFileSize(); @@ -145,12 +145,12 @@ class StorageTest { Assert.assertEquals("count is not correct", numberOfRecords1, 0); Assert.assertEquals("size is not correct", size1, initialSize); - StorageType.close(storage); + StorageSystem.close(storage); - storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); int numberOfRecords2 = storage.size(); long size2 = storage.getFileSize(); @@ -158,7 +158,7 @@ class StorageTest { Assert.assertEquals("Record count is not the same", numberOfRecords1, numberOfRecords2); Assert.assertEquals("size is not the same", size1, size2); - StorageType.close(storage); + StorageSystem.close(storage); } @@ -166,20 +166,20 @@ class StorageTest { public void testAddAsOne() throws IOException, ClassNotFoundException { try { - Storage storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + Storage storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); for (int i = 0; i < total; i++) { add(storage, i); } - StorageType.close(storage); - storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + StorageSystem.close(storage); + storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); for (int i = 0; i < total; i++) { String record1Data = createData(i); @@ -188,7 +188,7 @@ class StorageTest { Assert.assertEquals("Object is not the same", record1Data, readRecord); } - StorageType.close(storage); + StorageSystem.close(storage); } catch (Exception e) { e.printStackTrace(); Assert.fail("Error!"); @@ -204,10 +204,10 @@ class StorageTest { public void testAddNoKeyRecords() throws IOException, ClassNotFoundException { try { - Storage storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + Storage storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); for (int i = 0; i < total; i++) { log("adding record " + i + "..."); @@ -219,12 +219,12 @@ class StorageTest { Assert.assertEquals("Object is not the same", addRecord, readData); } - StorageType.close(storage); + StorageSystem.close(storage); - storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); String dataCheck = createData(total - 1); log("reading record " + (total - 1) + "..."); @@ -240,7 +240,7 @@ class StorageTest { Assert.assertEquals("size is not correct", size1, initialSize + sizePerRecord); - StorageType.close(storage); + StorageSystem.close(storage); } catch (Exception e) { e.printStackTrace(); Assert.fail("Error!"); @@ -251,10 +251,10 @@ class StorageTest { public void testAddRecords_DelaySaveA() throws IOException, ClassNotFoundException { try { - Storage storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + Storage storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); for (int i = 0; i < total; i++) { add(storage, i); @@ -272,12 +272,12 @@ class StorageTest { Assert.assertEquals("Object is not the same", record1Data, readRecord); } - StorageType.close(storage); + StorageSystem.close(storage); - storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); for (int i = 0; i < total; i++) { String dataCheck = createData(i); String readRecord = readRecord(storage, i); @@ -285,7 +285,7 @@ class StorageTest { Assert.assertEquals("Object is not the same", dataCheck, readRecord); } - StorageType.close(storage); + StorageSystem.close(storage); } catch (Exception e) { e.printStackTrace(); Assert.fail("Error!"); @@ -296,10 +296,10 @@ class StorageTest { public void testAddRecords_DelaySaveB() throws IOException, ClassNotFoundException { try { - Storage storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + Storage storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); for (int i = 0; i < total; i++) { add(storage, i); @@ -312,12 +312,12 @@ class StorageTest { Assert.assertEquals("Object is not the same", record1Data, readRecord); } - StorageType.close(storage); + StorageSystem.close(storage); - storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); for (int i = 0; i < total; i++) { String dataCheck = createData(i); @@ -326,7 +326,7 @@ class StorageTest { Assert.assertEquals("Object is not the same", dataCheck, readRecord); } - StorageType.close(storage); + StorageSystem.close(storage); } catch (Exception e) { e.printStackTrace(); Assert.fail("Error!"); @@ -337,10 +337,10 @@ class StorageTest { public void testLoadRecords() throws IOException, ClassNotFoundException { try { - Storage storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + Storage storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); for (int i = 0; i < total; i++) { String addRecord = add(storage, i); @@ -348,12 +348,12 @@ class StorageTest { Assert.assertEquals("Object is not the same", addRecord, readRecord); } - StorageType.close(storage); + StorageSystem.close(storage); - storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); for (int i = 0; i < total; i++) { String dataCheck = createData(i); @@ -373,16 +373,16 @@ class StorageTest { data2 = storage.getAndPut(createKey, new Data()); Assert.assertEquals("Object is not the same", data, data2); - StorageType.close(storage); - storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + StorageSystem.close(storage); + storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); data2 = storage.getAndPut(createKey, new Data()); Assert.assertEquals("Object is not the same", data, data2); - StorageType.close(storage); + StorageSystem.close(storage); } catch (Exception e) { e.printStackTrace(); Assert.fail("Error!"); @@ -398,10 +398,10 @@ class StorageTest { } try { - Storage storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + Storage storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); for (int i = 0; i < total; i++) { String addRecord = add(storage, i); @@ -409,12 +409,12 @@ class StorageTest { Assert.assertEquals("Object is not the same", addRecord, readRecord); } - StorageType.close(storage); + StorageSystem.close(storage); - storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); for (int i = 0; i < total; i++) { String dataCheck = createData(i); @@ -442,12 +442,12 @@ class StorageTest { Assert.assertEquals("Object is not the same", dataCheck, addRecord); - StorageType.close(storage); + StorageSystem.close(storage); - storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); // check 9 again readRecord = readRecord(storage, 9); @@ -469,10 +469,10 @@ class StorageTest { public void testUpdateRecords() throws IOException, ClassNotFoundException { try { - Storage storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + Storage storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); for (int i = 0; i < total; i++) { String addRecord = add(storage, i); @@ -480,48 +480,48 @@ class StorageTest { Assert.assertEquals("Object is not the same", addRecord, readRecord); } - StorageType.close(storage); + StorageSystem.close(storage); - storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); String updateRecord = updateRecord(storage, 3, createData(3) + "new"); String readRecord = readRecord(storage, 3); Assert.assertEquals("Object is not the same", updateRecord, readRecord); - StorageType.close(storage); - storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + StorageSystem.close(storage); + storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); readRecord = readRecord(storage, 3); Assert.assertEquals("Object is not the same", updateRecord, readRecord); updateRecord = updateRecord(storage, 3, createData(3)); - StorageType.close(storage); - storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + StorageSystem.close(storage); + storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); readRecord = readRecord(storage, 3); Assert.assertEquals("Object is not the same", updateRecord, readRecord); - StorageType.close(storage); - storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + StorageSystem.close(storage); + storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); updateRecord = updateRecord(storage, 0, createData(0) + "new"); readRecord = readRecord(storage, 0); Assert.assertEquals("Object is not the same", updateRecord, readRecord); - StorageType.close(storage); + StorageSystem.close(storage); } catch (Exception e) { e.printStackTrace(); Assert.fail("Error!"); @@ -533,10 +533,10 @@ class StorageTest { public void testSaveAllRecords() throws IOException, ClassNotFoundException { try { - Storage storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + Storage storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); for (int i = 0; i < total; i++) { Data data = new Data(); @@ -545,15 +545,15 @@ class StorageTest { storage.put(createKey, data); } - StorageType.close(storage); + StorageSystem.close(storage); Data data = new Data(); makeData(data); - storage = StorageType.Disk() - .file(TEST_DB) - .serializer(manager) - .make(); + storage = StorageSystem.Disk() + .file(TEST_DB) + .serializer(manager) + .make(); for (int i = 0; i < total; i++) { String createKey = createKey(i); @@ -561,7 +561,7 @@ class StorageTest { data2 = storage.getAndPut(createKey, new Data()); Assert.assertEquals("Object is not the same", data, data2); } - StorageType.close(storage); + StorageSystem.close(storage); } catch (Exception e) { e.printStackTrace(); Assert.fail("Error!");