From 85a745dc3aa95fb967fb7be6d65303598747636b Mon Sep 17 00:00:00 2001 From: nathan Date: Fri, 4 Aug 2017 16:26:32 +0200 Subject: [PATCH] Simplified storage API. Throws RuntimeException if trying to write to a read-only storage. --- src/dorkbox/util/storage/DiskStorage.java | 205 +++----------------- src/dorkbox/util/storage/MemoryStorage.java | 118 +---------- src/dorkbox/util/storage/Storage.java | 72 +------ test/dorkbox/util/StorageTest.java | 18 +- 4 files changed, 39 insertions(+), 374 deletions(-) diff --git a/src/dorkbox/util/storage/DiskStorage.java b/src/dorkbox/util/storage/DiskStorage.java index fbf5bbc..19ad6f6 100644 --- a/src/dorkbox/util/storage/DiskStorage.java +++ b/src/dorkbox/util/storage/DiskStorage.java @@ -36,6 +36,7 @@ import dorkbox.util.SerializationManager; */ @SuppressWarnings({"Convert2Diamond", "Convert2Lambda"}) class DiskStorage implements Storage { + // null if we are a read-only storage private final DelayTimer timer; private final StorageBase storage; @@ -60,16 +61,16 @@ class DiskStorage implements Storage { @Override public void run() { - ReentrantLock actionLock2 = DiskStorage.this.actionLock; + ReentrantLock actionLock = DiskStorage.this.actionLock; Map actions; try { - actionLock2.lock(); + actionLock.lock(); // do a fast swap on the actionMap. actions = DiskStorage.this.actionMap; DiskStorage.this.actionMap = new ConcurrentHashMap(); } finally { - actionLock2.unlock(); + actionLock.unlock(); } DiskStorage.this.storage.doActionThings(actions); @@ -108,32 +109,13 @@ class DiskStorage implements Storage { */ @Override public final - boolean contains(String key) { + boolean contains(StorageKey key) { if (!this.isOpen.get()) { throw new RuntimeException("Unable to act on closed storage"); } - final StorageKey wrap = new StorageKey(key); // check if our pending actions has it, or if our storage index has it - return this.actionMap.containsKey(wrap) || this.storage.contains(wrap); - } - - /** - * Reads a object using the specific key, and casts it to the expected class - */ - @Override - public final - T get(String key) { - return get0(new StorageKey(key)); - } - - /** - * Reads a object using the specific key, and casts it to the expected class - */ - @Override - public final - T get(byte[] key) { - return get0(new StorageKey(key)); + return this.actionMap.containsKey(key) || this.storage.contains(key); } /** @@ -146,31 +128,7 @@ class DiskStorage implements Storage { } /** - * Returns the saved data for the specified key. Also saves the data. - * - * @param data If there is no object in the DB with the specified key, this value will be the default (and will be saved to the db) - */ - @Override - public - T get(String key, T data) { - StorageKey wrap = new StorageKey(key); - - return get(wrap, data); - } - - /** - * Returns the saved data for the specified key. Also saves the data. - * - * @param data If there is no object in the DB with the specified key, this value will be the default (and will be saved to the db) - */ - @Override - public - T get(byte[] key, T data) { - return get(new StorageKey(key), data); - } - - /** - * Returns the saved data (or null) for the specified key. Also saves the data. + * Returns the saved data (or null) for the specified key. Also saves the data as default data. * * @param data If there is no object in the DB with the specified key, this value will be the default (and will be saved to the db) * @@ -184,7 +142,7 @@ class DiskStorage implements Storage { if (source == null) { // returned was null, so we should save the default value - putAndSave(key, data); + put(key, data); return data; } else { @@ -236,30 +194,6 @@ class DiskStorage implements Storage { return this.storage.get(key); } - /** - * Saves the given data to storage with the associated key. - *

- * Also will update existing data. If the new contents do not fit in the original space, then the update is handled by - * deleting the old data and adding the new. - */ - @Override - public final - void put(String key, Object object) { - put(new StorageKey(key), object); - } - - /** - * Saves the given data to storage with the associated key. - *

- * Also will update existing data. If the new contents do not fit in the original space, then the update is handled by - * deleting the old data and adding the new. - */ - @Override - public final - void put(byte[] key, Object object) { - put(new StorageKey(key), object); - } - /** * Saves the given data to storage with the associated key. *

@@ -274,34 +208,24 @@ class DiskStorage implements Storage { } if (timer != null) { - action(key, object); + try { + this.actionLock.lock(); + + if (object != null) { + // push action to map + this.actionMap.put(key, object); + } + else { + this.actionMap.remove(key); + } + } finally { + this.actionLock.unlock(); + } // timer action runs on TIMER thread, not this thread this.timer.delay(this.milliSeconds); - } - } - - /** - * Deletes an object from storage. - * - * @return true if the delete was successful. False if there were problems deleting the data. - */ - @Override - public final - boolean delete(String key) { - if (!this.isOpen.get()) { - throw new RuntimeException("Unable to act on closed storage"); - } - - StorageKey wrap = new StorageKey(key); - - // timer action runs on THIS thread, not timer thread - if (timer != null) { - this.timer.delay(0L); - return this.storage.delete(wrap); - } - else { - return false; + } else { + throw new RuntimeException("Unable to put on a read-only storage"); } } @@ -323,13 +247,14 @@ class DiskStorage implements Storage { return this.storage.delete(key); } else { - return false; + throw new RuntimeException("Unable to delete on a read-only storage"); } } /** * Closes and removes this storage from the storage system. This is the same as calling {@link StorageSystem#close(Storage)} */ + @Override public void close() { StorageSystem.close(this); @@ -433,24 +358,6 @@ class DiskStorage implements Storage { this.storage.setVersion(version); } - private - void action(StorageKey key, Object object) { - try { - this.actionLock.lock(); - - if (object != null) { - // push action to map - this.actionMap.put(key, object); - } else { - this.actionMap.remove(key); - } - - - } finally { - this.actionLock.unlock(); - } - } - void increaseReference() { this.references.incrementAndGet(); } @@ -483,66 +390,8 @@ class DiskStorage implements Storage { // timer action runs on THIS thread, not timer thread if (timer != null) { this.timer.delay(0L); - } - } - - /** - * Adds a key/value pair to the storage, then saves the storage to disk, immediately. - *

- * This will save ALL of the pending save actions to the file - */ - @Override - public - void putAndSave(final String key, final Object object) { - if (!this.isOpen.get()) { - throw new RuntimeException("Unable to act on closed storage"); - } - - // timer action runs on THIS thread, not timer thread - if (timer != null) { - action(new StorageKey(key), object); - this.timer.delay(0L); - } - } - - /** - * Adds a key/value pair to the storage, then save the storage to disk, immediately. - *

- * This will save ALL of the pending save actions to the file - */ - @Override - public - void putAndSave(final byte[] key, final Object object) { - if (!this.isOpen.get()) { - throw new RuntimeException("Unable to act on closed storage"); - } - - if (timer != null) { - action(new StorageKey(key), object); - - // timer action runs on THIS thread, not timer thread - this.timer.delay(0L); - } - - } - - /** - * Adds a key/value pair to the storage, then save the storage to disk, immediately. - *

- * This will save ALL of the pending save actions to the file - */ - @Override - public - void putAndSave(final StorageKey key, final Object object) { - if (!this.isOpen.get()) { - throw new RuntimeException("Unable to act on closed storage"); - } - - if (timer != null) { - action(key, object); - - // timer action runs on THIS thread, not timer thread - this.timer.delay(0L); + } else { + throw new RuntimeException("Unable to save on a read-only storage"); } } } diff --git a/src/dorkbox/util/storage/MemoryStorage.java b/src/dorkbox/util/storage/MemoryStorage.java index 6513bd3..3094f4b 100644 --- a/src/dorkbox/util/storage/MemoryStorage.java +++ b/src/dorkbox/util/storage/MemoryStorage.java @@ -45,26 +45,8 @@ class MemoryStorage implements Storage { */ @Override public - boolean contains(final String key) { - return storage.containsKey(new StorageKey(key)); - } - - /** - * Reads a object using the specific key, and casts it to the expected class - */ - @Override - public - T get(final String key) { - return get(new StorageKey(key)); - } - - /** - * Reads a object using the specific key, and casts it to the expected class - */ - @Override - public - T get(final byte[] key) { - return get(new StorageKey(key)); + boolean contains(final StorageKey key) { + return storage.containsKey(key); } /** @@ -77,30 +59,6 @@ class MemoryStorage implements Storage { return (T) storage.get(key); } - /** - * Returns the saved data for the specified key. - * - * @param data If there is no object in the DB with the specified key, this value will be the default (and will be saved to the db) - */ - @Override - public - T get(String key, T data) { - StorageKey wrap = new StorageKey(key); - - return get(wrap, data); - } - - /** - * Returns the saved data for the specified key. - * - * @param data If there is no object in the DB with the specified key, this value will be the default (and will be saved to the db) - */ - @Override - public - T get(byte[] key, T data) { - return get(new StorageKey(key), data); - } - @SuppressWarnings("unchecked") @Override public @@ -113,30 +71,6 @@ class MemoryStorage implements Storage { return (T) o; } - /** - * Saves the given data to storage with the associated key. - *

- * Also will update existing data. If the new contents do not fit in the original space, then the update is handled by - * deleting the old data and adding the new. - */ - @Override - public - void put(final String key, final Object data) { - put(new StorageKey(key), data); - } - - /** - * Saves the given data to storage with the associated key. - *

- * Also will update existing data. If the new contents do not fit in the original space, then the update is handled by - * deleting the old data and adding the new. - */ - @Override - public - void put(final byte[] key, final Object data) { - put(new StorageKey(key), data); - } - /** * Saves the given data to storage with the associated key. *

@@ -149,17 +83,6 @@ class MemoryStorage implements Storage { storage.put(key, object); } - /** - * Deletes an object from storage. - * - * @return true if the delete was successful. False if there were problems deleting the data. - */ - @Override - public - boolean delete(final String key) { - return delete(new StorageKey(key)); - } - /** * Deletes an object from storage. * @@ -247,43 +170,6 @@ class MemoryStorage implements Storage { // no-op } - /** - * Adds a key/value pair to the storage. - *

- * There is no file that backs this storage, so writes are immediate and saves do nothing - */ - @Override - public - void putAndSave(final String key, final Object object) { - put(key, object); - // no-save! - } - - /** - /** - * Adds a key/value pair to the storage. - *

- * There is no file that backs this storage, so writes are immediate and saves do nothing - */ - @Override - public - void putAndSave(final byte[] key, final Object object) { - put(key, object); - // no save because we are in memory! - } - - /** - * Adds a key/value pair to the storage. - *

- * There is no file that backs this storage, so writes are immediate and saves do nothing - */ - @Override - public - void putAndSave(final StorageKey key, final Object object) { - put(key, object); - // no save because we are in memory! - } - /** * In-memory storage systems do not have a backing file, so there is nothing to close */ diff --git a/src/dorkbox/util/storage/Storage.java b/src/dorkbox/util/storage/Storage.java index f6ab8b0..a9922cc 100644 --- a/src/dorkbox/util/storage/Storage.java +++ b/src/dorkbox/util/storage/Storage.java @@ -31,39 +31,13 @@ interface Storage { /** * Checks if there is a object corresponding to the given key. */ - boolean contains(String key); - - /** - * Reads a object using the specific key, and casts it to the expected class. - */ - T get(String key); - - /** - * Reads a object using the specific key, and casts it to the expected class - */ - T get(byte[] key); + boolean contains(StorageKey key); /** * Reads a object using the specific key, and casts it to the expected class */ T get(StorageKey key); - /** - * Returns the saved data for the specified key. - * - * @param key The key used to check if data already exists. - * @param data This is the default value, and if there is no value with the key in the DB this default value will be saved. - */ - T get(String key, T data); - - /** - * Returns the saved data for the specified key. - * - * @param key The key used to check if data already exists. - * @param data This is the default value, and if there is no value with the key in the DB this default value will be saved. - */ - T get(byte[] key, T data); - /** * Returns the saved data for the specified key. * @@ -72,22 +46,6 @@ interface Storage { */ T get(StorageKey key, T data); - /** - * Saves the given data to storage with the associated key. - *

- * Also will update existing data. If the new contents do not fit in the original space, then the update is handled by - * deleting the old data and adding the new. - */ - void put(String key, Object data); - - /** - * Saves the given data to storage with the associated key. - *

- * Also will update existing data. If the new contents do not fit in the original space, then the update is handled by - * deleting the old data and adding the new. - */ - void put(byte[] key, Object data); - /** * Saves the given data to storage with the associated key. *

@@ -96,13 +54,6 @@ interface Storage { */ void put(StorageKey key, Object data); - /** - * Deletes an object from storage. - * - * @return true if the delete was successful. False if there were problems deleting the data. - */ - boolean delete(String key); - /** * Deletes an object from storage. * @@ -154,27 +105,6 @@ interface Storage { */ void save(); - /** - * Adds a key/value pair to the storage, then saves the storage immediately. - *

- * This will save ALL of the pending save actions to the file - */ - void putAndSave(String key, Object object); - - /** - * Adds a key/value pair to the storage, then saves the storage immediately. - *

- * This will save ALL of the pending save actions to the file - */ - void putAndSave(byte[] key, Object object); - - /** - * Adds a key/value pair to the storage, then saves the storage immediately. - *

- * This will save ALL of the pending save actions to the file - */ - void putAndSave(StorageKey key, Object object); - /** * Closes this storage system */ diff --git a/test/dorkbox/util/StorageTest.java b/test/dorkbox/util/StorageTest.java index e174f31..cba2813 100644 --- a/test/dorkbox/util/StorageTest.java +++ b/test/dorkbox/util/StorageTest.java @@ -286,7 +286,7 @@ class StorageTest { // now test loading data Data data = new Data(); - String createKey = createKey(63); + StorageKey createKey = createKey(63); makeData(data); storage.put(createKey, data); @@ -453,7 +453,7 @@ class StorageTest { for (int i = 0; i < total; i++) { Data data = new Data(); makeData(data); - String createKey = createKey(i); + StorageKey createKey = createKey(i); storage.put(createKey, data); } @@ -466,7 +466,7 @@ class StorageTest { .file(TEST_DB) .build(); for (int i = 0; i < total; i++) { - String createKey = createKey(i); + StorageKey createKey = createKey(i); Data data2; data2 = storage.get(createKey, new Data()); @@ -489,7 +489,7 @@ class StorageTest { public static String add(Storage storage, int number) throws IOException { String record1Data = createData(number); - String record1Key = createKey(number); + StorageKey record1Key = createKey(number); log("adding record " + number + "..."); storage.put(record1Key, record1Data); @@ -498,7 +498,7 @@ class StorageTest { public static String readRecord(Storage storage, int number) throws ClassNotFoundException, IOException { - String record1Key = createKey(number); + StorageKey record1Key = createKey(number); log("reading record " + number + "..."); @@ -509,7 +509,7 @@ class StorageTest { public static void deleteRecord(Storage storage, int nNumber) throws ClassNotFoundException, IOException { - String record1Key = createKey(nNumber); + StorageKey record1Key = createKey(nNumber); log("deleting record " + nNumber + "..."); storage.delete(record1Key); @@ -517,7 +517,7 @@ class StorageTest { private static String updateRecord(Storage storage, int number, String newData) throws IOException { - String record1Key = createKey(number); + StorageKey record1Key = createKey(number); log("updating record " + number + "..."); storage.put(record1Key, newData); @@ -526,8 +526,8 @@ class StorageTest { } private static - String createKey(int number) { - return "foo" + number; + StorageKey createKey(int number) { + return new StorageKey("foo" + number); }