diff --git a/Dorkbox-Util/src/dorkbox/util/Message.java b/Dorkbox-Util/src/dorkbox/util/Message.java
index 5d13488..080c937 100644
--- a/Dorkbox-Util/src/dorkbox/util/Message.java
+++ b/Dorkbox-Util/src/dorkbox/util/Message.java
@@ -15,8 +15,6 @@
*/
package dorkbox.util;
-import java.io.Serializable;
-
-public interface Message extends Serializable {
+public interface Message {
}
diff --git a/Dorkbox-Util/src/dorkbox/util/SerializationManager.java b/Dorkbox-Util/src/dorkbox/util/SerializationManager.java
index 70ed68a..e44e757 100644
--- a/Dorkbox-Util/src/dorkbox/util/SerializationManager.java
+++ b/Dorkbox-Util/src/dorkbox/util/SerializationManager.java
@@ -21,6 +21,9 @@ import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import io.netty.buffer.ByteBuf;
+import org.slf4j.Logger;
+
+import java.io.IOException;
public
interface SerializationManager {
@@ -72,7 +75,7 @@ interface SerializationManager {
*
* There is a small speed penalty if there were no kryo's available to use.
*/
- void write(ByteBuf buffer, Object message);
+ void write(ByteBuf buffer, Object message) throws IOException;
/**
* Reads an object from the buffer.
@@ -81,17 +84,17 @@ interface SerializationManager {
*
* @param length should ALWAYS be the length of the expected object!
*/
- Object read(ByteBuf buffer, int length);
+ Object read(ByteBuf buffer, int length) throws IOException;
/**
* Writes the class and object using an available kryo instance
*/
- void writeFullClassAndObject(Output output, Object value);
+ void writeFullClassAndObject(final Logger logger, Output output, Object value) throws IOException;
/**
* Returns a class read from the input
*/
- Object readFullClassAndObject(Input input);
+ Object readFullClassAndObject(final Logger logger, final Input input) throws IOException;
/**
* Borrows a kryo from the threadsafe pool. You must release it back to the pool when done.
@@ -102,4 +105,15 @@ interface SerializationManager {
* Releases the kryo back to the threadsafe pool
*/
void release(Kryo kryo);
+
+ /**
+ * Called when initialization is complete. This is to prevent (and recognize) out-of-order class/serializer registration.
+ */
+ void finishInit();
+
+ /**
+ * @return true if our initialization is complete. Some registrations (in the property store, for example) always register for client
+ * and server, even if in the same JVM. This only attempts to register once.
+ */
+ boolean initialized();
}
diff --git a/Dorkbox-Util/src/dorkbox/util/database/DB_Server.java b/Dorkbox-Util/src/dorkbox/util/database/DB_Server.java
index 73466f4..3e83339 100644
--- a/Dorkbox-Util/src/dorkbox/util/database/DB_Server.java
+++ b/Dorkbox-Util/src/dorkbox/util/database/DB_Server.java
@@ -26,7 +26,7 @@ class DB_Server {
/**
* Address 0.0.0.0/32 may be used as a source address for this host on this network.
*/
- public static final ByteArrayWrapper IP_0_0_0_0 = ByteArrayWrapper.wrap(new byte[] {0, 0, 0, 0});
+ public static final ByteArrayWrapper IP_LOCALHOST = ByteArrayWrapper.wrap(new byte[] {127, 0, 0, 1});
// salt + IP address is used for equals!
private byte[] ipAddress;
diff --git a/Dorkbox-Util/src/dorkbox/util/exceptions/NetException.java b/Dorkbox-Util/src/dorkbox/util/exceptions/NetException.java
deleted file mode 100644
index 00b7d1c..0000000
--- a/Dorkbox-Util/src/dorkbox/util/exceptions/NetException.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2010 dorkbox, llc
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package dorkbox.util.exceptions;
-
-public
-class NetException extends RuntimeException {
-
- private static final long serialVersionUID = -3499720814336253695L;
-
- public
- NetException() {
- super();
- }
-
- public
- NetException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public
- NetException(String message) {
- super(message);
- }
-
- public
- NetException(Throwable cause) {
- super(cause);
- }
-}
diff --git a/Dorkbox-Util/src/dorkbox/util/serialization/UnmodifiableCollectionsSerializer.java b/Dorkbox-Util/src/dorkbox/util/serialization/UnmodifiableCollectionsSerializer.java
index 84b1580..12b1b1e 100644
--- a/Dorkbox-Util/src/dorkbox/util/serialization/UnmodifiableCollectionsSerializer.java
+++ b/Dorkbox-Util/src/dorkbox/util/serialization/UnmodifiableCollectionsSerializer.java
@@ -20,7 +20,6 @@ import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
-import dorkbox.util.exceptions.NetException;
import dorkbox.util.SerializationManager;
import java.lang.reflect.Field;
@@ -48,7 +47,7 @@ public class UnmodifiableCollectionsSerializer extends Serializer {
.getDeclaredField("m");
SOURCE_MAP_FIELD.setAccessible( true );
} catch ( final Exception e ) {
- throw new NetException("Could not access source collection" +
+ throw new RuntimeException("Could not access source collection" +
" field in java.util.Collections$UnmodifiableCollection.", e );
}
}
diff --git a/Dorkbox-Util/src/dorkbox/util/storage/DiskStorage.java b/Dorkbox-Util/src/dorkbox/util/storage/DiskStorage.java
index 1ca211e..b26f03c 100644
--- a/Dorkbox-Util/src/dorkbox/util/storage/DiskStorage.java
+++ b/Dorkbox-Util/src/dorkbox/util/storage/DiskStorage.java
@@ -159,7 +159,7 @@ class DiskStorage implements Storage {
}
/**
- * Uses the DEFAULT key ("") to return saved data.
+ * Uses the DEFAULT key ("") to return saved data. Also saves the data.
*
* This will check to see if there is an associated key for that data, if not - it will use data as the default
*
@@ -167,48 +167,48 @@ class DiskStorage implements Storage {
*/
@Override
public
- T load(T data) throws IOException {
- return load(this.defaultKey, data);
+ T getAndPut(T data) throws IOException {
+ return getAndPut(this.defaultKey, data);
}
/**
- * Returns the saved data for the specified key.
+ * 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 load(String key, T data) throws IOException {
+ T getAndPut(String key, T data) throws IOException {
ByteArrayWrapper wrap = ByteArrayWrapper.wrap(key);
- return load(wrap, data);
+ return getAndPut(wrap, data);
}
/**
- * Returns the saved data for the specified key.
+ * 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 load(byte[] key, T data) throws IOException {
- return load(ByteArrayWrapper.wrap(key), data);
+ T getAndPut(byte[] key, T data) throws IOException {
+ return getAndPut(ByteArrayWrapper.wrap(key), data);
}
/**
- * Returns the saved data for the specified key.
+ * 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
@SuppressWarnings("unchecked")
public
- T load(ByteArrayWrapper key, T data) throws IOException {
+ T getAndPut(ByteArrayWrapper key, T data) throws IOException {
Object source = get0(key);
if (source == null) {
// returned was null, so we should take value as the default
- put(key, data);
+ putAndSave(key, data);
return data;
}
else {
@@ -318,7 +318,7 @@ class DiskStorage implements Storage {
}
/**
- * Deletes an object from storage. To ALSO remove from the cache, use unRegister(key)
+ * Deletes an object from storage.
*
* @return true if the delete was successful. False if there were problems deleting the data.
*/
@@ -341,6 +341,28 @@ class DiskStorage implements Storage {
}
}
+ /**
+ * 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(ByteArrayWrapper key) {
+ 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) {
+ this.timer.delay(0L);
+ return this.storage.delete(key);
+ }
+ else {
+ return false;
+ }
+ }
+
/**
* Closes the database and file.
*/
@@ -352,10 +374,7 @@ class DiskStorage implements Storage {
// have to "close" it after we run the timer!
this.isOpen.set(false);
-
- if (timer != null) {
- this.storage.close();
- }
+ this.storage.close();
}
/**
@@ -446,8 +465,14 @@ class DiskStorage implements Storage {
try {
this.actionLock.lock();
- // push action to map
- this.actionMap.put(key, object);
+ if (object != null) {
+ // push action to map
+ this.actionMap.put(key, object);
+ } else {
+ this.actionMap.remove(key);
+ }
+
+
} finally {
this.actionLock.unlock();
}
@@ -477,7 +502,7 @@ class DiskStorage implements Storage {
*/
@Override
public final
- void commit() {
+ void save() {
if (!this.isOpen.get()) {
throw new RuntimeException("Unable to act on closed storage");
}
@@ -495,7 +520,7 @@ class DiskStorage implements Storage {
*/
@Override
public
- void commit(final String key, final Object object) {
+ void putAndSave(final String key, final Object object) {
if (!this.isOpen.get()) {
throw new RuntimeException("Unable to act on closed storage");
}
@@ -514,7 +539,7 @@ class DiskStorage implements Storage {
*/
@Override
public
- void commit(final byte[] key, final Object object) {
+ void putAndSave(final byte[] key, final Object object) {
if (!this.isOpen.get()) {
throw new RuntimeException("Unable to act on closed storage");
}
@@ -535,7 +560,7 @@ class DiskStorage implements Storage {
*/
@Override
public
- void commit(final ByteArrayWrapper key, final Object object) {
+ void putAndSave(final ByteArrayWrapper key, final Object object) {
if (!this.isOpen.get()) {
throw new RuntimeException("Unable to act on closed storage");
}
diff --git a/Dorkbox-Util/src/dorkbox/util/storage/MemoryStorage.java b/Dorkbox-Util/src/dorkbox/util/storage/MemoryStorage.java
index cdbe572..1d7459b 100644
--- a/Dorkbox-Util/src/dorkbox/util/storage/MemoryStorage.java
+++ b/Dorkbox-Util/src/dorkbox/util/storage/MemoryStorage.java
@@ -103,8 +103,8 @@ class MemoryStorage implements Storage {
*/
@Override
public
- T load(T data) throws IOException {
- return load(this.defaultKey, data);
+ T getAndPut(T data) throws IOException {
+ return getAndPut(this.defaultKey, data);
}
/**
@@ -114,10 +114,10 @@ class MemoryStorage implements Storage {
*/
@Override
public
- T load(String key, T data) throws IOException {
+ T getAndPut(String key, T data) throws IOException {
ByteArrayWrapper wrap = ByteArrayWrapper.wrap(key);
- return load(wrap, data);
+ return getAndPut(wrap, data);
}
/**
@@ -127,14 +127,14 @@ class MemoryStorage implements Storage {
*/
@Override
public
- T load(byte[] key, T data) throws IOException {
- return load(ByteArrayWrapper.wrap(key), data);
+ T getAndPut(byte[] key, T data) throws IOException {
+ return getAndPut(ByteArrayWrapper.wrap(key), data);
}
@SuppressWarnings("unchecked")
@Override
public
- T load(final ByteArrayWrapper key, final T data) throws IOException {
+ T getAndPut(final ByteArrayWrapper key, final T data) throws IOException {
final Object o = storage.get(key);
if (o == null) {
storage.put(key, data);
@@ -192,14 +192,25 @@ class MemoryStorage implements Storage {
}
/**
- * Deletes an object from storage. To ALSO remove from the cache, use unRegister(key)
+ * 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) {
- storage.remove(ByteArrayWrapper.wrap(key));
+ return delete(ByteArrayWrapper.wrap(key));
+ }
+
+ /**
+ * 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 ByteArrayWrapper key) {
+ storage.remove(key);
return true;
}
@@ -246,25 +257,25 @@ class MemoryStorage implements Storage {
@Override
public
- void commit() {
+ void save() {
// no-op
}
@Override
public
- void commit(final String key, final Object object) {
+ void putAndSave(final String key, final Object object) {
// no-op
}
@Override
public
- void commit(final byte[] key, final Object object) {
+ void putAndSave(final byte[] key, final Object object) {
// no-op
}
@Override
public
- void commit(final ByteArrayWrapper key, final Object object) {
+ void putAndSave(final ByteArrayWrapper key, final Object object) {
// no-op
}
}
diff --git a/Dorkbox-Util/src/dorkbox/util/storage/Metadata.java b/Dorkbox-Util/src/dorkbox/util/storage/Metadata.java
index 7bc2bd7..8be7996 100644
--- a/Dorkbox-Util/src/dorkbox/util/storage/Metadata.java
+++ b/Dorkbox-Util/src/dorkbox/util/storage/Metadata.java
@@ -260,10 +260,10 @@ class Metadata {
*/
static
- T readData(SerializationManager serializationManager, InflaterInputStream inputStream) {
+ T readData(SerializationManager serializationManager, InflaterInputStream inputStream) throws IOException {
Input input = new Input(inputStream, 1024); // read 1024 at a time
@SuppressWarnings("unchecked")
- T readObject = (T) serializationManager.readFullClassAndObject(input);
+ T readObject = (T) serializationManager.readFullClassAndObject(null, input);
return readObject;
}
@@ -277,7 +277,7 @@ class Metadata {
final DeflaterOutputStream outputStream) throws IOException {
// HAVE TO LOCK BEFORE THIS IS CALLED! (AND FREE AFTERWARDS!)
Output output = new Output(outputStream, 1024); // write 1024 at a time
- serializationManager.writeFullClassAndObject(output, data);
+ serializationManager.writeFullClassAndObject(null, output, data);
output.flush();
outputStream.flush(); // sync-flush is enabled, so the output stream will finish compressing data.
diff --git a/Dorkbox-Util/src/dorkbox/util/storage/Storage.java b/Dorkbox-Util/src/dorkbox/util/storage/Storage.java
index ea9967f..98138eb 100644
--- a/Dorkbox-Util/src/dorkbox/util/storage/Storage.java
+++ b/Dorkbox-Util/src/dorkbox/util/storage/Storage.java
@@ -23,6 +23,7 @@ import java.io.IOException;
/**
*
*/
+@SuppressWarnings("unused")
public
interface Storage {
/**
@@ -36,7 +37,7 @@ interface Storage {
boolean contains(String key);
/**
- * Reads a object using the default (blank) key, and casts it to the expected class
+ * Reads a object using the DEFAULT key ("") key, and casts it to the expected class
*/
T get();
@@ -62,21 +63,21 @@ interface Storage {
*
* @param data The data that will hold the copy of the data from disk
*/
- T load(T data) throws IOException;
+ T getAndPut(T data) throws IOException;
/**
* 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)
*/
- T load(String key, T data) throws IOException;
+ T getAndPut(String key, T data) throws IOException;
/**
* 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)
*/
- T load(byte[] key, T data) throws IOException;
+ T getAndPut(byte[] key, T data) throws IOException;
/**
* Returns the saved data for the specified key.
@@ -84,7 +85,7 @@ interface Storage {
* @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)
*/
@SuppressWarnings("unchecked")
- T load(ByteArrayWrapper key, T data) throws IOException;
+ T getAndPut(ByteArrayWrapper key, T data) throws IOException;
/**
* Saves the given data to storage with the associated key.
@@ -119,12 +120,19 @@ interface Storage {
void put(Object data);
/**
- * Deletes an object from storage. To ALSO remove from the cache, use unRegister(key)
+ * 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.
+ *
+ * @return true if the delete was successful. False if there were problems deleting the data.
+ */
+ boolean delete(ByteArrayWrapper key);
+
/**
* @return the file that backs this storage
*/
@@ -167,26 +175,26 @@ interface Storage {
*
* This will save the ALL of the pending save actions to the file
*/
- void commit();
+ void save();
/**
* Save the storage to disk, immediately.
*
* This will save the ALL of the pending save actions to the file
*/
- void commit(String key, Object object);
+ void putAndSave(String key, Object object);
/**
* Save the storage to disk, immediately.
*
* This will save the ALL of the pending save actions to the file
*/
- void commit(byte[] key, Object object);
+ void putAndSave(byte[] key, Object object);
/**
* Save the storage to disk, immediately.
*
* This will save the ALL of the pending save actions to the file
*/
- void commit(ByteArrayWrapper key, Object object);
+ void putAndSave(ByteArrayWrapper key, Object object);
}
diff --git a/Dorkbox-Util/src/dorkbox/util/storage/StorageBase.java b/Dorkbox-Util/src/dorkbox/util/storage/StorageBase.java
index 3eaee71..2a75ade 100644
--- a/Dorkbox-Util/src/dorkbox/util/storage/StorageBase.java
+++ b/Dorkbox-Util/src/dorkbox/util/storage/StorageBase.java
@@ -379,7 +379,7 @@ class StorageBase {
}
else {
// this is comparatively slow, since we serialize it first to get the size, then we put it in the file.
- ByteArrayOutputStream dataStream = getDataAsByteArray(this.serializationManager, object, deflater);
+ ByteArrayOutputStream dataStream = getDataAsByteArray(this.serializationManager, this.logger, object, deflater);
int size = dataStream.size();
if (size > metaData.dataCapacity) {
@@ -445,11 +445,11 @@ class StorageBase {
private static
- ByteArrayOutputStream getDataAsByteArray(SerializationManager kryo, Object data, Deflater deflater) throws IOException {
+ ByteArrayOutputStream getDataAsByteArray(SerializationManager serializationManager, Logger logger, Object data, Deflater deflater) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
OutputStream outputStream = new DeflaterOutputStream(byteArrayOutputStream, deflater);
Output output = new Output(outputStream, 1024); // write 1024 at a time
- kryo.writeFullClassAndObject(output, data);
+ serializationManager.writeFullClassAndObject(logger, output, data);
output.flush();
outputStream.flush();
diff --git a/Dorkbox-Util/src/dorkbox/util/storage/Store.java b/Dorkbox-Util/src/dorkbox/util/storage/Store.java
index aaec363..157a163 100644
--- a/Dorkbox-Util/src/dorkbox/util/storage/Store.java
+++ b/Dorkbox-Util/src/dorkbox/util/storage/Store.java
@@ -151,7 +151,7 @@ class Store {
boolean waiting = storage.hasWriteWaiting();
// we want this storage to be in a fresh state
if (waiting) {
- storage.commit();
+ storage.save();
}
((DiskStorage) storage).increaseReference();
}
diff --git a/Dorkbox-Util/test/dorkbox/util/StorageTest.java b/Dorkbox-Util/test/dorkbox/util/StorageTest.java
index efe600f..75fdecb 100644
--- a/Dorkbox-Util/test/dorkbox/util/StorageTest.java
+++ b/Dorkbox-Util/test/dorkbox/util/StorageTest.java
@@ -9,6 +9,7 @@ import dorkbox.util.storage.Store;
import io.netty.buffer.ByteBuf;
import org.junit.*;
import org.junit.runners.MethodSorters;
+import org.slf4j.Logger;
import java.io.File;
import java.io.IOException;
@@ -44,17 +45,17 @@ class StorageTest {
public
void write(final ByteBuf buffer, final Object message) {
final Output output = new Output();
- writeFullClassAndObject(output, message);
+ writeFullClassAndObject(null, output, message);
buffer.writeBytes(output.getBuffer());
}
@Override
public
- Object read(final ByteBuf buffer, final int length) {
+ Object read(final ByteBuf buffer, final int length) throws IOException {
final Input input = new Input();
buffer.readBytes(input.getBuffer());
- final Object o = readFullClassAndObject(input);
+ final Object o = readFullClassAndObject(null, input);
buffer.skipBytes(input.position());
return o;
@@ -62,13 +63,13 @@ class StorageTest {
@Override
public
- void writeFullClassAndObject(final Output output, final Object value) {
+ void writeFullClassAndObject(final Logger logger, final Output output, final Object value) {
kryo.writeClassAndObject(output, value);
}
@Override
public
- Object readFullClassAndObject(final Input input) {
+ Object readFullClassAndObject(final Logger logger, final Input input) throws IOException {
return kryo.readClassAndObject(input);
}
@@ -82,6 +83,17 @@ class StorageTest {
public
void release(final Kryo kryo) {
}
+
+ @Override
+ public
+ void finishInit() {
+ }
+
+ @Override
+ public
+ boolean initialized() {
+ return false;
+ }
};
static
@@ -335,7 +347,7 @@ class StorageTest {
storage.put(createKey, data);
Data data2 = new Data();
- storage.load(createKey, data2);
+ storage.getAndPut(createKey, data2);
Assert.assertEquals("Object is not the same", data, data2);
Store.close(storage);
@@ -345,7 +357,7 @@ class StorageTest {
.make();
data2 = new Data();
- storage.load(createKey, data2);
+ storage.getAndPut(createKey, data2);
Assert.assertEquals("Object is not the same", data, data2);
Store.close(storage);
@@ -522,7 +534,7 @@ class StorageTest {
String createKey = createKey(i);
Data data2 = new Data();
- storage.load(createKey, data2);
+ storage.getAndPut(createKey, data2);
Assert.assertEquals("Object is not the same", data, data2);
}
Store.close(storage);