Added comments, renamed to StorageSystem

This commit is contained in:
nathan 2017-02-18 14:41:22 +01:00
parent f5ae7fb32d
commit b6272112e8
2 changed files with 196 additions and 138 deletions

View File

@ -22,12 +22,13 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.helpers.NOPLogger;
import dorkbox.util.FileUtil; import dorkbox.util.FileUtil;
import dorkbox.util.SerializationManager; import dorkbox.util.SerializationManager;
public public
class StorageType { class StorageSystem {
@SuppressWarnings("SpellCheckingInspection") @SuppressWarnings("SpellCheckingInspection")
private static final Map<File, Storage> storages = new HashMap<File, Storage>(1); private static final Map<File, Storage> storages = new HashMap<File, Storage>(1);
@ -36,7 +37,7 @@ class StorageType {
@Override @Override
public public
void run() { void run() {
StorageType.shutdown(); StorageSystem.shutdown();
} }
}); });
@ -46,21 +47,28 @@ class StorageType {
.addShutdownHook(shutdownHook); .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 public static
DiskMaker Disk() { DiskMaker Disk() {
return new DiskMaker(); return new DiskMaker();
} }
/**
* Creates an in-memory only storage system
*/
public static public static
MemoryMaker Memory() { MemoryMaker Memory() {
return new MemoryMaker(); return new MemoryMaker();
} }
/** /**
* Closes the storage. * Closes the specified storage system based on the file used
*/ */
public static public static
void close(File file) { void close(final File file) {
synchronized (storages) { synchronized (storages) {
Storage storage = storages.get(file); Storage storage = storages.get(file);
if (storage != null) { if (storage != null) {
@ -77,24 +85,27 @@ class StorageType {
} }
/** /**
* Closes the storage. * Closes the specified storage system
*/ */
public static public static
void close(Storage _storage) { void close(final Storage storage) {
synchronized (storages) { synchronized (storages) {
File file = _storage.getFile(); File file = storage.getFile();
close(file); close(file);
} }
} }
/**
* Saves and closes all open storage systems
*/
public static public static
void shutdown() { void shutdown() {
synchronized (storages) { synchronized (storages) {
Collection<Storage> values = storages.values(); Collection<Storage> values = storages.values();
for (Storage storage : values) { for (Storage storage : values) {
if (storage instanceof DiskStorage) { if (storage instanceof DiskStorage) {
//noinspection StatementWithEmptyBody
final DiskStorage diskStorage = (DiskStorage) storage; final DiskStorage diskStorage = (DiskStorage) storage;
//noinspection StatementWithEmptyBody
while (!diskStorage.decrementReference()) { while (!diskStorage.decrementReference()) {
} }
diskStorage.close(); diskStorage.close();
@ -104,6 +115,11 @@ class StorageType {
} }
} }
/**
* Closes (if in use) and deletes the specified storage file.
* <p>
* The file is checked to see if it is in use by the storage system first, and closes if so.
*/
public static public static
void delete(File file) { void delete(File file) {
synchronized (storages) { synchronized (storages) {
@ -116,13 +132,20 @@ class StorageType {
} }
} }
/**
* Closes (if in use) and deletes the specified storage.
*/
public static public static
void delete(Storage storage) { void delete(Storage storage) {
File file = storage.getFile(); File file = storage.getFile();
delete(file); 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 public static
class DiskMaker { class DiskMaker {
private File file; private File file;
@ -130,24 +153,64 @@ class StorageType {
private boolean readOnly = false; private boolean readOnly = false;
private Logger logger = null; private Logger logger = null;
/**
* Specify the file to write to on disk when saving objects
*/
public public
DiskMaker file(File file) { DiskMaker file(File file) {
this.file = FileUtil.normalize(file); this.file = FileUtil.normalize(file);
return this; return this;
} }
/**
* Specify the file to write to on disk when saving objects
*/
public public
DiskMaker file(String file) { DiskMaker file(String file) {
this.file = FileUtil.normalize(file); this.file = FileUtil.normalize(file);
return this; return this;
} }
/**
* Specify the serialization manager to use. This is what serializes the files (which are then saved to disk)
*/
public public
DiskMaker serializer(SerializationManager serializationManager) { DiskMaker serializer(SerializationManager serializationManager) {
this.serializationManager = serializationManager; this.serializationManager = serializationManager;
return this; 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 public
Storage make() { Storage make() {
if (this.file == null) { if (this.file == null) {
@ -188,23 +251,18 @@ class StorageType {
return storage; 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 public static
class MemoryMaker { class MemoryMaker {
/**
* Makes the storage system
*/
public public
MemoryStorage make() throws IOException { MemoryStorage make() throws IOException {
return new MemoryStorage(); return new MemoryStorage();

View File

@ -33,7 +33,7 @@ import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output; import com.esotericsoftware.kryo.io.Output;
import dorkbox.util.storage.Storage; import dorkbox.util.storage.Storage;
import dorkbox.util.storage.StorageType; import dorkbox.util.storage.StorageSystem;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
@FixMethodOrder(MethodSorters.NAME_ASCENDING) @FixMethodOrder(MethodSorters.NAME_ASCENDING)
@ -121,23 +121,23 @@ class StorageTest {
@Before @Before
public public
void deleteDB() { void deleteDB() {
StorageType.delete(TEST_DB); StorageSystem.delete(TEST_DB);
} }
@After @After
public public
void delete2DB() { void delete2DB() {
StorageType.delete(TEST_DB); StorageSystem.delete(TEST_DB);
} }
@Test @Test
public public
void testCreateDB() throws IOException { void testCreateDB() throws IOException {
Storage storage = StorageType.Disk() Storage storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
int numberOfRecords1 = storage.size(); int numberOfRecords1 = storage.size();
long size1 = storage.getFileSize(); long size1 = storage.getFileSize();
@ -145,12 +145,12 @@ class StorageTest {
Assert.assertEquals("count is not correct", numberOfRecords1, 0); Assert.assertEquals("count is not correct", numberOfRecords1, 0);
Assert.assertEquals("size is not correct", size1, initialSize); Assert.assertEquals("size is not correct", size1, initialSize);
StorageType.close(storage); StorageSystem.close(storage);
storage = StorageType.Disk() storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
int numberOfRecords2 = storage.size(); int numberOfRecords2 = storage.size();
long size2 = storage.getFileSize(); long size2 = storage.getFileSize();
@ -158,7 +158,7 @@ class StorageTest {
Assert.assertEquals("Record count is not the same", numberOfRecords1, numberOfRecords2); Assert.assertEquals("Record count is not the same", numberOfRecords1, numberOfRecords2);
Assert.assertEquals("size is not the same", size1, size2); Assert.assertEquals("size is not the same", size1, size2);
StorageType.close(storage); StorageSystem.close(storage);
} }
@ -166,20 +166,20 @@ class StorageTest {
public public
void testAddAsOne() throws IOException, ClassNotFoundException { void testAddAsOne() throws IOException, ClassNotFoundException {
try { try {
Storage storage = StorageType.Disk() Storage storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
add(storage, i); add(storage, i);
} }
StorageType.close(storage); StorageSystem.close(storage);
storage = StorageType.Disk() storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
String record1Data = createData(i); String record1Data = createData(i);
@ -188,7 +188,7 @@ class StorageTest {
Assert.assertEquals("Object is not the same", record1Data, readRecord); Assert.assertEquals("Object is not the same", record1Data, readRecord);
} }
StorageType.close(storage); StorageSystem.close(storage);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
Assert.fail("Error!"); Assert.fail("Error!");
@ -204,10 +204,10 @@ class StorageTest {
public public
void testAddNoKeyRecords() throws IOException, ClassNotFoundException { void testAddNoKeyRecords() throws IOException, ClassNotFoundException {
try { try {
Storage storage = StorageType.Disk() Storage storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
log("adding record " + i + "..."); log("adding record " + i + "...");
@ -219,12 +219,12 @@ class StorageTest {
Assert.assertEquals("Object is not the same", addRecord, readData); Assert.assertEquals("Object is not the same", addRecord, readData);
} }
StorageType.close(storage); StorageSystem.close(storage);
storage = StorageType.Disk() storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
String dataCheck = createData(total - 1); String dataCheck = createData(total - 1);
log("reading record " + (total - 1) + "..."); log("reading record " + (total - 1) + "...");
@ -240,7 +240,7 @@ class StorageTest {
Assert.assertEquals("size is not correct", size1, initialSize + sizePerRecord); Assert.assertEquals("size is not correct", size1, initialSize + sizePerRecord);
StorageType.close(storage); StorageSystem.close(storage);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
Assert.fail("Error!"); Assert.fail("Error!");
@ -251,10 +251,10 @@ class StorageTest {
public public
void testAddRecords_DelaySaveA() throws IOException, ClassNotFoundException { void testAddRecords_DelaySaveA() throws IOException, ClassNotFoundException {
try { try {
Storage storage = StorageType.Disk() Storage storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
add(storage, i); add(storage, i);
@ -272,12 +272,12 @@ class StorageTest {
Assert.assertEquals("Object is not the same", record1Data, readRecord); Assert.assertEquals("Object is not the same", record1Data, readRecord);
} }
StorageType.close(storage); StorageSystem.close(storage);
storage = StorageType.Disk() storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
String dataCheck = createData(i); String dataCheck = createData(i);
String readRecord = readRecord(storage, i); String readRecord = readRecord(storage, i);
@ -285,7 +285,7 @@ class StorageTest {
Assert.assertEquals("Object is not the same", dataCheck, readRecord); Assert.assertEquals("Object is not the same", dataCheck, readRecord);
} }
StorageType.close(storage); StorageSystem.close(storage);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
Assert.fail("Error!"); Assert.fail("Error!");
@ -296,10 +296,10 @@ class StorageTest {
public public
void testAddRecords_DelaySaveB() throws IOException, ClassNotFoundException { void testAddRecords_DelaySaveB() throws IOException, ClassNotFoundException {
try { try {
Storage storage = StorageType.Disk() Storage storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
add(storage, i); add(storage, i);
@ -312,12 +312,12 @@ class StorageTest {
Assert.assertEquals("Object is not the same", record1Data, readRecord); Assert.assertEquals("Object is not the same", record1Data, readRecord);
} }
StorageType.close(storage); StorageSystem.close(storage);
storage = StorageType.Disk() storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
String dataCheck = createData(i); String dataCheck = createData(i);
@ -326,7 +326,7 @@ class StorageTest {
Assert.assertEquals("Object is not the same", dataCheck, readRecord); Assert.assertEquals("Object is not the same", dataCheck, readRecord);
} }
StorageType.close(storage); StorageSystem.close(storage);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
Assert.fail("Error!"); Assert.fail("Error!");
@ -337,10 +337,10 @@ class StorageTest {
public public
void testLoadRecords() throws IOException, ClassNotFoundException { void testLoadRecords() throws IOException, ClassNotFoundException {
try { try {
Storage storage = StorageType.Disk() Storage storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
String addRecord = add(storage, i); String addRecord = add(storage, i);
@ -348,12 +348,12 @@ class StorageTest {
Assert.assertEquals("Object is not the same", addRecord, readRecord); Assert.assertEquals("Object is not the same", addRecord, readRecord);
} }
StorageType.close(storage); StorageSystem.close(storage);
storage = StorageType.Disk() storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
String dataCheck = createData(i); String dataCheck = createData(i);
@ -373,16 +373,16 @@ class StorageTest {
data2 = storage.getAndPut(createKey, new Data()); data2 = storage.getAndPut(createKey, new Data());
Assert.assertEquals("Object is not the same", data, data2); Assert.assertEquals("Object is not the same", data, data2);
StorageType.close(storage); StorageSystem.close(storage);
storage = StorageType.Disk() storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
data2 = storage.getAndPut(createKey, new Data()); data2 = storage.getAndPut(createKey, new Data());
Assert.assertEquals("Object is not the same", data, data2); Assert.assertEquals("Object is not the same", data, data2);
StorageType.close(storage); StorageSystem.close(storage);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
Assert.fail("Error!"); Assert.fail("Error!");
@ -398,10 +398,10 @@ class StorageTest {
} }
try { try {
Storage storage = StorageType.Disk() Storage storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
String addRecord = add(storage, i); String addRecord = add(storage, i);
@ -409,12 +409,12 @@ class StorageTest {
Assert.assertEquals("Object is not the same", addRecord, readRecord); Assert.assertEquals("Object is not the same", addRecord, readRecord);
} }
StorageType.close(storage); StorageSystem.close(storage);
storage = StorageType.Disk() storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
String dataCheck = createData(i); String dataCheck = createData(i);
@ -442,12 +442,12 @@ class StorageTest {
Assert.assertEquals("Object is not the same", dataCheck, addRecord); Assert.assertEquals("Object is not the same", dataCheck, addRecord);
StorageType.close(storage); StorageSystem.close(storage);
storage = StorageType.Disk() storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
// check 9 again // check 9 again
readRecord = readRecord(storage, 9); readRecord = readRecord(storage, 9);
@ -469,10 +469,10 @@ class StorageTest {
public public
void testUpdateRecords() throws IOException, ClassNotFoundException { void testUpdateRecords() throws IOException, ClassNotFoundException {
try { try {
Storage storage = StorageType.Disk() Storage storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
String addRecord = add(storage, i); String addRecord = add(storage, i);
@ -480,48 +480,48 @@ class StorageTest {
Assert.assertEquals("Object is not the same", addRecord, readRecord); Assert.assertEquals("Object is not the same", addRecord, readRecord);
} }
StorageType.close(storage); StorageSystem.close(storage);
storage = StorageType.Disk() storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
String updateRecord = updateRecord(storage, 3, createData(3) + "new"); String updateRecord = updateRecord(storage, 3, createData(3) + "new");
String readRecord = readRecord(storage, 3); String readRecord = readRecord(storage, 3);
Assert.assertEquals("Object is not the same", updateRecord, readRecord); Assert.assertEquals("Object is not the same", updateRecord, readRecord);
StorageType.close(storage); StorageSystem.close(storage);
storage = StorageType.Disk() storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
readRecord = readRecord(storage, 3); readRecord = readRecord(storage, 3);
Assert.assertEquals("Object is not the same", updateRecord, readRecord); Assert.assertEquals("Object is not the same", updateRecord, readRecord);
updateRecord = updateRecord(storage, 3, createData(3)); updateRecord = updateRecord(storage, 3, createData(3));
StorageType.close(storage); StorageSystem.close(storage);
storage = StorageType.Disk() storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
readRecord = readRecord(storage, 3); readRecord = readRecord(storage, 3);
Assert.assertEquals("Object is not the same", updateRecord, readRecord); Assert.assertEquals("Object is not the same", updateRecord, readRecord);
StorageType.close(storage); StorageSystem.close(storage);
storage = StorageType.Disk() storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
updateRecord = updateRecord(storage, 0, createData(0) + "new"); updateRecord = updateRecord(storage, 0, createData(0) + "new");
readRecord = readRecord(storage, 0); readRecord = readRecord(storage, 0);
Assert.assertEquals("Object is not the same", updateRecord, readRecord); Assert.assertEquals("Object is not the same", updateRecord, readRecord);
StorageType.close(storage); StorageSystem.close(storage);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
Assert.fail("Error!"); Assert.fail("Error!");
@ -533,10 +533,10 @@ class StorageTest {
public public
void testSaveAllRecords() throws IOException, ClassNotFoundException { void testSaveAllRecords() throws IOException, ClassNotFoundException {
try { try {
Storage storage = StorageType.Disk() Storage storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
Data data = new Data(); Data data = new Data();
@ -545,15 +545,15 @@ class StorageTest {
storage.put(createKey, data); storage.put(createKey, data);
} }
StorageType.close(storage); StorageSystem.close(storage);
Data data = new Data(); Data data = new Data();
makeData(data); makeData(data);
storage = StorageType.Disk() storage = StorageSystem.Disk()
.file(TEST_DB) .file(TEST_DB)
.serializer(manager) .serializer(manager)
.make(); .make();
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
String createKey = createKey(i); String createKey = createKey(i);
@ -561,7 +561,7 @@ class StorageTest {
data2 = storage.getAndPut(createKey, new Data()); data2 = storage.getAndPut(createKey, new Data());
Assert.assertEquals("Object is not the same", data, data2); Assert.assertEquals("Object is not the same", data, data2);
} }
StorageType.close(storage); StorageSystem.close(storage);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
Assert.fail("Error!"); Assert.fail("Error!");