From 1def19d219dc6051465a5a09c056d2c068d6dc2d Mon Sep 17 00:00:00 2001 From: Andrea Cavalli Date: Sat, 9 Mar 2019 18:53:30 +0100 Subject: [PATCH] Server 1.0.0 --- database.blocks.dat | 0 database.db | Bin 0 -> 4256 bytes database.references.dat | 0 database.structure.dat | 0 database.structure.txt | 21 + pom.xml | 18 +- .../cavallium/strangedb/server/ArrayNode.java | 52 ++ .../cavallium/strangedb/server/ClassNode.java | 89 ++++ .../strangedb/server/DatabaseNodesIO.java | 452 ++++++++++++++++++ .../strangedb/server/DatabaseSimple.java | 27 ++ .../it/cavallium/strangedb/server/Node.java | 7 + .../strangedb/server/NodeProperty.java | 25 + .../cavallium/strangedb/server/NodeType.java | 8 + .../strangedb/server/NumberNode.java | 35 ++ .../it/cavallium/strangedb/server/Server.java | 47 ++ .../cavallium/strangedb/server/TreePath.java | 159 ++++++ .../strangedb/server/TreePathWalker.java | 46 ++ .../cavallium/strangedb/server/ValueNode.java | 37 ++ .../strangedb/server/http/ExistsHandler.java | 37 ++ .../strangedb/server/http/GetHandler.java | 37 ++ .../strangedb/server/http/SetHandler.java | 43 ++ .../strangedb/server/GetSetExistsTest.java | 57 +++ .../server/strangedb/tests/Clean.java | 88 ---- .../strangedb/tests/EnhancedClassUpdate.java | 50 -- .../tests/MultipleEnhancedObjects.java | 85 ---- .../server/strangedb/tests/OldClass.java | 30 -- .../server/strangedb/tests/Performance.java | 343 ------------- .../server/strangedb/tests/V2Class.java | 44 -- .../strangedb/utils/ConsumerWithIO.java | 32 -- .../strangedb/utils/NSimplestClass.java | 23 - .../server/strangedb/utils/NTestUtils.java | 284 ----------- 31 files changed, 1194 insertions(+), 982 deletions(-) create mode 100644 database.blocks.dat create mode 100644 database.db create mode 100644 database.references.dat create mode 100644 database.structure.dat create mode 100644 database.structure.txt create mode 100644 src/main/java/it/cavallium/strangedb/server/ArrayNode.java create mode 100644 src/main/java/it/cavallium/strangedb/server/ClassNode.java create mode 100644 src/main/java/it/cavallium/strangedb/server/DatabaseNodesIO.java create mode 100644 src/main/java/it/cavallium/strangedb/server/DatabaseSimple.java create mode 100644 src/main/java/it/cavallium/strangedb/server/Node.java create mode 100644 src/main/java/it/cavallium/strangedb/server/NodeProperty.java create mode 100644 src/main/java/it/cavallium/strangedb/server/NodeType.java create mode 100644 src/main/java/it/cavallium/strangedb/server/NumberNode.java create mode 100644 src/main/java/it/cavallium/strangedb/server/TreePath.java create mode 100644 src/main/java/it/cavallium/strangedb/server/TreePathWalker.java create mode 100644 src/main/java/it/cavallium/strangedb/server/ValueNode.java create mode 100644 src/main/java/it/cavallium/strangedb/server/http/ExistsHandler.java create mode 100644 src/main/java/it/cavallium/strangedb/server/http/GetHandler.java create mode 100644 src/main/java/it/cavallium/strangedb/server/http/SetHandler.java create mode 100644 src/test/java/it/cavallium/strangedb/server/GetSetExistsTest.java delete mode 100644 src/test/java/it/cavallium/strangedb/server/strangedb/tests/Clean.java delete mode 100644 src/test/java/it/cavallium/strangedb/server/strangedb/tests/EnhancedClassUpdate.java delete mode 100644 src/test/java/it/cavallium/strangedb/server/strangedb/tests/MultipleEnhancedObjects.java delete mode 100644 src/test/java/it/cavallium/strangedb/server/strangedb/tests/OldClass.java delete mode 100644 src/test/java/it/cavallium/strangedb/server/strangedb/tests/Performance.java delete mode 100644 src/test/java/it/cavallium/strangedb/server/strangedb/tests/V2Class.java delete mode 100644 src/test/java/it/cavallium/strangedb/server/strangedb/utils/ConsumerWithIO.java delete mode 100644 src/test/java/it/cavallium/strangedb/server/strangedb/utils/NSimplestClass.java delete mode 100644 src/test/java/it/cavallium/strangedb/server/strangedb/utils/NTestUtils.java diff --git a/database.blocks.dat b/database.blocks.dat new file mode 100644 index 0000000..e69de29 diff --git a/database.db b/database.db new file mode 100644 index 0000000000000000000000000000000000000000..fb78a6399b0755206b22a14a218ed9465b1d54f6 GIT binary patch literal 4256 zcmds)+fD*85QaG{uuY_vhyk7Z`=$aned)FQQco7;_ho$q~G zgMFaew(J;#Q|fltRkpi?d1M_bLU(7}2Bexxij*bg79LCjJuO#H+tJe`YwEs(jk)6ogfu_Q%fLB9)V#q6j>kh>2p8|02KQS*olu-VfP$0~D0$$pTa#P(x)=J?4-Ns0gSL zw*l$`P%~vwdYZ_6N<~2FtUyiL02%z@^KlK;C7`aOtU5kpv87Z5bvmS=DmZ5Pz{Onw z?qmk(DXT-w8p_5@$CvygDniV3E`>qHfJz*c&e4R~anv;@J&ai~Wz<`VIJ0s5VHO&( zWgbhb$1SuBfA#t^A3jyEfP!|4<>uu>i~a ssRFPr0Q0CbV>$|SZRqqjQqY-X+jhr~w+(aTbn_N_?$|zb{wh`f50qC>NB{r; literal 0 HcmV?d00001 diff --git a/database.references.dat b/database.references.dat new file mode 100644 index 0000000..e69de29 diff --git a/database.structure.dat b/database.structure.dat new file mode 100644 index 0000000..e69de29 diff --git a/database.structure.txt b/database.structure.txt new file mode 100644 index 0000000..ef1a86f --- /dev/null +++ b/database.structure.txt @@ -0,0 +1,21 @@ +types: + - name: Long2IntMap + model: map: [LONG, INTEGER] +definitions: + - name: ChatLog + version: 0 + fields: + - name: chatId + type: LONG + - name: messageIds + type: Long2IntMap + preloaded: true + - name: messages + type: ARRAY + preloaded: true + - name: chatDetailsHistory + type: ChatSnapshotList + preloaded: true + - name: MessageList + fields: + - name: message diff --git a/pom.xml b/pom.xml index b91758b..0518152 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ strangedb-server 1.5.4 - strangedb + strangedb-server https://git.ignuranza.net/andreacavalli/strangedb @@ -49,8 +49,8 @@ it.cavallium - strangedb - 1.5.4 + strangedb-core + 1.5.5 @@ -64,6 +64,18 @@ RELEASE compile + + org.json + json + 20170516 + compile + + + com.google.guava + guava + 27.0-jre + compile + diff --git a/src/main/java/it/cavallium/strangedb/server/ArrayNode.java b/src/main/java/it/cavallium/strangedb/server/ArrayNode.java new file mode 100644 index 0000000..9179dc5 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/server/ArrayNode.java @@ -0,0 +1,52 @@ +package it.cavallium.strangedb.server; + +import java.util.Arrays; + +public class ArrayNode implements Node { + + private final long reference; + private long[] items; + + public ArrayNode(long reference, long[] items) { + this.reference = reference; + this.items = items; + } + + public long[] getItems() { + return items; + } + + public long getItem(int index) { + return items[index]; + } + + public int countItems() { + return items.length; + } + + public void setItem(int index, long value) { + if (index >= items.length) { + items = Arrays.copyOf(items, index + 1); + } + items[index] = value; + } + + public boolean hasItem(int index) { + return index >= 0 && index < items.length; + } + + @Override + public NodeType getType() { + return NodeType.ARRAY; + } + + @Override + public long getReference() { + return reference; + } + + @Override + public Node copy() { + return new ArrayNode(reference, items.clone()); + } +} diff --git a/src/main/java/it/cavallium/strangedb/server/ClassNode.java b/src/main/java/it/cavallium/strangedb/server/ClassNode.java new file mode 100644 index 0000000..04a6d99 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/server/ClassNode.java @@ -0,0 +1,89 @@ +package it.cavallium.strangedb.server; + +import java.util.Arrays; + +public class ClassNode implements Node { + + private final long reference; + private NodeProperty[] properties; + + public ClassNode(long reference, NodeProperty[] properties) { + this.reference = reference; + this.properties = properties; + } + + public NodeProperty[] getProperties() { + return properties; + } + + public long getProperty(byte[] propertyName) { + int propertyIndex = getPropertyIndex(propertyName); + if (propertyIndex == -1) { + throw new NullPointerException(); + } + return properties[propertyIndex].getReference(); + } + + public boolean hasProperty(byte[] name) { + for (int i = 0; i < properties.length; i++) { + NodeProperty property = properties[i]; + if (DatabaseNodesIO.nameEquals(property.getName(), name)) { + return true; + } + } + return false; + } + + public NodeProperty getProperty(int index) { + return properties[index]; + } + + public int countProperties() { + return properties.length; + } + + + public void setProperty(byte[] propertyName, long valueReference) { + setProperty(new NodeProperty(propertyName, valueReference)); + } + + public void setProperty(NodeProperty value) { + // Find if property exists + int propertyToEditIndex = getPropertyIndex(value.getName()); + + // Add new property + if (propertyToEditIndex < 0) { + properties = Arrays.copyOf(properties, properties.length + 1); + properties[properties.length - 1] = value; + } else { + properties[propertyToEditIndex] = value; + } + } + + private int getPropertyIndex(byte[] name) { + int propIndex = -1; + for (int i = 0; i < properties.length; i++) { + NodeProperty property = properties[i]; + if (DatabaseNodesIO.nameEquals(property.getName(), name)) { + propIndex = i; + break; + } + } + return propIndex; + } + + @Override + public NodeType getType() { + return NodeType.CLASS; + } + + @Override + public long getReference() { + return reference; + } + + @Override + public Node copy() { + return new ClassNode(reference, properties.clone()); + } +} diff --git a/src/main/java/it/cavallium/strangedb/server/DatabaseNodesIO.java b/src/main/java/it/cavallium/strangedb/server/DatabaseNodesIO.java new file mode 100644 index 0000000..ec357d3 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/server/DatabaseNodesIO.java @@ -0,0 +1,452 @@ +package it.cavallium.strangedb.server; + +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; +import it.cavallium.strangedb.database.IReferencesIO; +import it.cavallium.strangedb.database.references.DatabaseReferencesMetadata; +import org.json.*; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Map; + +import static it.cavallium.strangedb.server.TreePath.stringToNode; + +public class DatabaseNodesIO { + private final IReferencesIO referencesIO; + private static final int isArrayMask = 0b10000000000000000000000000000000; + private static final int isValueMask = 0b01000000000000000000000000000000; + private static final int isNumberMask = 0b11000000000000000000000000000000; + private static final int nodeCountMask = 0b01111111111111111111111111111111; + private static final int arrayCountMask = 0b01111111111111111111111111111111; + + public DatabaseNodesIO(IReferencesIO referencesIO, DatabaseReferencesMetadata referencesMetadata) throws IOException { + this.referencesIO = referencesIO; + if (referencesMetadata.getFirstFreeReference() == 0) { + long ref = this.referencesIO.allocateReference(); + if (ref != 0) throw new IOException("Root must be 0"); + ClassNode rootNode = new ClassNode(ref, new NodeProperty[0]); + this.setNode(rootNode); + } + } + + public String get(CharSequence path) throws IOException { + return get(TreePath.get(path)); + } + + public String get(TreePath path) throws IOException { + Node foundNode = getNode(path); + return toJson(foundNode); + } + + private String toJson(Node foundNode) throws IOException { + StringBuilder sb = new StringBuilder(); + toJson(sb, foundNode); + return sb.toString(); + } + + private void toJson(StringBuilder sb, long nodeReference) throws IOException { + toJson(sb, loadNode(nodeReference)); + } + + private void toJson(StringBuilder sb, Node foundNode) throws IOException { + switch (foundNode.getType()) { + case ARRAY: { + ArrayNode arrayNode = (ArrayNode) foundNode; + sb.append('['); + for (int i = 0; i < arrayNode.countItems(); i++) { + toJson(sb, arrayNode.getItem(i)); + if (i + 1 < arrayNode.countItems()) { + sb.append(','); + } + } + sb.append(']'); + break; + } + case CLASS: { + ClassNode classNode = (ClassNode) foundNode; + sb.append('{'); + for (int i = 0; i < classNode.countProperties(); i++) { + NodeProperty property = classNode.getProperty(i); + sb.append(property.getNameAsString()); + sb.append(':'); + toJson(sb, property.getReference()); + if (i + 1 < classNode.countProperties()) { + sb.append(','); + } + } + sb.append('}'); + break; + } + case VALUE: { + ValueNode valueNode = (ValueNode) foundNode; + sb.append(org.json.JSONObject.quote(loadValue(valueNode.getValueReference()))); + break; + } + case NUMBER: { + NumberNode valueNode = (NumberNode) foundNode; + sb.append(loadNumber(valueNode.getNumberReference())); + break; + } + } + } + + private void setValue(long reference, String value) throws IOException { + ByteBuffer valueBytes = StandardCharsets.UTF_8.encode(value); + referencesIO.writeToReference(reference, valueBytes.limit(), valueBytes); + } + + private String loadValue(long reference) throws IOException { + ByteBuffer buffer = referencesIO.readFromReference(reference); + return StandardCharsets.UTF_8.decode(buffer).toString(); + } + + private void setNumber(long reference, double value) throws IOException { + ByteBuffer buffer = ByteBuffer.allocate(Double.BYTES); + buffer.putDouble(value); + buffer.flip(); + referencesIO.writeToReference(reference, buffer.limit(), buffer); + } + + private double loadNumber(long reference) throws IOException { + ByteBuffer buffer = referencesIO.readFromReference(reference); + return buffer.getDouble(); + } + + public void set(CharSequence path, String value) throws IOException { + TreePath treePath = TreePath.get(path); + if (treePath.isRoot()) { + set(treePath, importNode(value, 0)); + } else { + set(treePath, importNode(value)); + } + } + + public void set(TreePath path, long valueReference) throws IOException { + Node node; + if (path.isRoot()) { + if (valueReference != 0) + throw new IOException("Root must be zero"); + } else { + node = getNode(path.getParent()); + switch (node.getType()) { + case ARRAY: { + if (!path.isArrayOffset()) { + throw new IOException("Required a property inside an array node"); + } + ArrayNode arrayNode = (ArrayNode) node; + int index = path.getArrayOffset(); + arrayNode.setItem(index, valueReference); + break; + } + case CLASS: { + if (!path.isNodeProperty()) + throw new IOException("Required array offset inside a non-array node"); + ClassNode classNode = (ClassNode) node; + byte[] propertyName = path.getNodeValue(); + classNode.setProperty(propertyName, valueReference); + break; + } + case NUMBER: + case VALUE: { + throw new IOException("WTF you shouldn't be here!"); + } + } + setNode(node); + } + } + + @Deprecated + private long importNode(String value) throws IOException { + return importNode(value, referencesIO.allocateReference()); + } + + private long importNode(String value, long reference) throws IOException { + switch (value.charAt(0)) { + case '[': + JSONArray array = new JSONArray(value); + return importJsonNode(array, reference); + case '{': + JSONObject obj = new JSONObject(value); + return importJsonNode(obj, reference); + case '"': + return importJsonNode(value.substring(1, value.length() - 1), reference); + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + return importJsonNode(Double.parseDouble(value), reference); + default: + throw new IOException("Unrecognized input"); + } + } + + @Deprecated + private long importJsonNode(Object o) throws IOException { + return importJsonNode(o, referencesIO.allocateReference()); + } + + private long importJsonNode(Object o, long reference) throws IOException { + if (o instanceof ArrayList) { + o = new JSONArray((ArrayList) o); + } + if (o instanceof JSONArray) { + JSONArray array = (JSONArray) o; + int length = array.length(); + long[] arrayReferences = new long[length]; + for (int i = 0; i < length; i++) { + arrayReferences[i] = importJsonNode(array.get(i)); + } + Node node = createNewArrayNode(arrayReferences, reference); + setNode(node); + return node.getReference(); + } else if (o instanceof JSONObject) { + JSONObject obj = (JSONObject) o; + Map jsonProperties = obj.toMap(); + NodeProperty[] properties = new NodeProperty[jsonProperties.size()]; + int i = 0; + for (Map.Entry entry : jsonProperties.entrySet()) { + NodeProperty nodeProperty = new NodeProperty(stringToNode(entry.getKey()), importJsonNode(entry.getValue())); + properties[i] = nodeProperty; + } + Node node = createNewNodeNode(properties, reference); + setNode(node); + return node.getReference(); + } else if (o instanceof String) { + Node node = createNewValueNode((String) o, reference); + setNode(node); + return node.getReference(); + } else if (o instanceof Double || o instanceof Float || o instanceof Integer || o instanceof Long) { + double number; + if (o instanceof Integer) { + number = (Integer) o; + } else if (o instanceof Long) { + number = (Long) o; + } else if (o instanceof Float) { + number = (Float) o; + } else if (o instanceof Double) { + number = (Double) o; + } else { + throw new RuntimeException(); + } + Node node = createNewNumberNode(number+0, reference); + setNode(node); + return node.getReference(); + } else { + throw new RuntimeException(); + } + } + + public boolean exists(CharSequence path) throws IOException { + return exists(TreePath.get(path)); + } + + public boolean exists(TreePath path) throws IOException { + TreePathWalker pathWalker = new TreePathWalker(path); + Node node = loadNode(0); + while (pathWalker.hasNext()) { + TreePath nodePath = pathWalker.next(); + if (nodePath.isArrayOffset()) { + if (node.getType() != NodeType.ARRAY) { + return false; + } + int offset = nodePath.getArrayOffset(); + if (!((ArrayNode)node).hasItem(offset)) { + return false; + } + long nodeReference = ((ArrayNode) node).getItem(offset); + node = loadNode(nodeReference); + } else if (nodePath.isNodeProperty()) { + if (node.getType() == NodeType.ARRAY) { + return false; + } + byte[] propertyName = nodePath.getNodeValue(); + if (!((ClassNode) node).hasProperty(propertyName)) { + return false; + } + long nodeReference = ((ClassNode) node).getProperty(propertyName); + node = loadNode(nodeReference); + } + } + return node != null; + } + + private Node getNode(TreePath path) throws IOException { + TreePathWalker pathWalker = new TreePathWalker(path); + pathWalker.walkToRoot(); + Node node = loadNode(0); + while (pathWalker.hasNext()) { + TreePath nodePath = pathWalker.next(); + if (nodePath.isArrayOffset()) { + if (node.getType() != NodeType.ARRAY) { + throw new IOException("Required array offset inside a non-array node"); + } + int offset = nodePath.getArrayOffset(); + long nodeReference = ((ArrayNode) node).getItem(offset); + node = loadNode(nodeReference); + } else if (nodePath.isNodeProperty()) { + if (node.getType() == NodeType.ARRAY) { + throw new IOException("Required a property inside an array node"); + } + byte[] propertyName = nodePath.getNodeValue(); + long nodeReference = ((ClassNode) node).getProperty(propertyName); + node = loadNode(nodeReference); + } + } + if (node == null) + throw new NullPointerException(); + return node; + } + + private Node createNewArrayNode() throws IOException { + long reference = referencesIO.allocateReference(); + return new ArrayNode(reference, new long[0]); + } + + private Node createNewArrayNode(long[] items) throws IOException { + return createNewArrayNode(items, referencesIO.allocateReference()); + } + + private Node createNewArrayNode(long[] items, long reference) throws IOException { + return new ArrayNode(reference, items); + } + + private Node createNewValueNode() throws IOException { + long reference = referencesIO.allocateReference(); + return new ValueNode(reference, referencesIO.allocateReference()); + } + + private Node createNewValueNode(String value) throws IOException { + return createNewValueNode(value, referencesIO.allocateReference()); + } + + private Node createNewValueNode(String value, long reference) throws IOException { + byte[] string = value.getBytes(StandardCharsets.UTF_8); + long dataReference = referencesIO.allocateReference(string.length, ByteBuffer.wrap(string)); + return new ValueNode(reference, dataReference); + } + + private Node createNewNumberNode(double value, long reference) throws IOException { + ByteBuffer buffer = ByteBuffer.allocate(Double.BYTES); + buffer.putDouble(value); + buffer.flip(); + long dataReference = referencesIO.allocateReference(buffer.limit(), buffer); + return new NumberNode(reference, dataReference); + } + + private Node createNewNodeNode() throws IOException { + return createNewNodeNode(referencesIO.allocateReference()); + } + + private Node createNewNodeNode(long reference) { + return createNewNodeNode(new NodeProperty[0], reference); + } + + private Node createNewNodeNode(NodeProperty[] properties) throws IOException { + return createNewNodeNode(properties, referencesIO.allocateReference()); + } + + private Node createNewNodeNode(NodeProperty[] properties, long reference) { + return new ClassNode(reference, properties); + } + + private void setNode(Node node) throws IOException { + ByteBuffer buffer; + switch (node.getType()) { + case ARRAY: + ArrayNode arrayNode = ((ArrayNode) node); + buffer = ByteBuffer.allocate(Integer.BYTES + arrayNode.countItems() * Long.BYTES); + buffer.putInt((arrayNode.countItems() & arrayCountMask) | isArrayMask); + for (long ref : arrayNode.getItems()) { + buffer.putLong(ref); + } + buffer.flip(); + break; + case CLASS: + ClassNode classNode = ((ClassNode) node); + ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput(); + dataOutput.writeInt(classNode.countProperties() & nodeCountMask); + for (NodeProperty ref : classNode.getProperties()) { + dataOutput.write(ref.getName().length); + dataOutput.write(ref.getName()); + dataOutput.writeLong(ref.getReference()); + } + buffer = ByteBuffer.wrap(dataOutput.toByteArray()); + break; + case VALUE: + buffer = ByteBuffer.allocate(Integer.BYTES + Long.BYTES); + buffer.putInt(isValueMask); + buffer.putLong(((ValueNode) node).getValueReference()); + buffer.flip(); + break; + case NUMBER: + buffer = ByteBuffer.allocate(Integer.BYTES + Long.BYTES); + buffer.putInt(isNumberMask); + buffer.putLong(((NumberNode) node).getNumberReference()); + buffer.flip(); + break; + default: + throw new RuntimeException(); + } + referencesIO.writeToReference(node.getReference(), buffer.limit(), buffer); + } + + private Node loadNode(long reference) throws IOException { + Node node; + ByteBuffer nodeData = referencesIO.readFromReference(reference); + int propertiesCount = nodeData.getInt(); + boolean isNumber = (propertiesCount & isNumberMask) == isNumberMask; + boolean isArray = !isNumber && (propertiesCount & isArrayMask) != 0; + if (isArray) { + int arrayElementsCount = propertiesCount & arrayCountMask; + long[] arrayElementsReferences = new long[arrayElementsCount]; + for (int i = 0; i < arrayElementsCount; i++) { + arrayElementsReferences[i] = nodeData.getLong(); + } + node = new ArrayNode(reference, arrayElementsReferences); + } else { + boolean isValue = !isNumber && (propertiesCount & isValueMask) != 0; + if (isValue) { + long valueReference = nodeData.getLong(); + node = new ValueNode(reference, valueReference); + } else if (isNumber) { + long numberReference = nodeData.getLong(); + node = new NumberNode(reference, numberReference); + } else { + NodeProperty[] nodeProperties = new NodeProperty[propertiesCount & nodeCountMask]; + for (int i = 0; i < propertiesCount; i++) { + byte nameLength = nodeData.get(); + byte[] name = new byte[nameLength]; + nodeData.get(name); + long nodeReference = nodeData.getLong(); + nodeProperties[i] = new NodeProperty(name, nodeReference); + } + node = new ClassNode(reference, nodeProperties); + } + } + return node; + } + + public static boolean nameEquals(byte[] name1, byte[] name2) { + if (name1 == null || name2 == null || name1.length == 0 || name2.length == 0) { + throw new IllegalArgumentException(); + } + if (name1.length != name2.length) { + return false; + } + for (int i = 0; i < name1.length; i++) { + if (name1[i] != name2[i]) + return false; + } + return true; + } +} diff --git a/src/main/java/it/cavallium/strangedb/server/DatabaseSimple.java b/src/main/java/it/cavallium/strangedb/server/DatabaseSimple.java new file mode 100644 index 0000000..9222ba5 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/server/DatabaseSimple.java @@ -0,0 +1,27 @@ +package it.cavallium.strangedb.server; + +import it.cavallium.strangedb.database.DatabaseCore; + +import java.io.IOException; +import java.nio.file.Path; + +public class DatabaseSimple extends DatabaseCore { + private final DatabaseNodesIO databaseNodesIO; + + public DatabaseSimple(Path dataFile, Path blocksMetaFile, Path referencesMetaFile) throws IOException { + super(dataFile, blocksMetaFile, referencesMetaFile); + this.databaseNodesIO = new DatabaseNodesIO(referencesIO, referencesMetadata); + } + + public String get(CharSequence path) throws IOException { + return databaseNodesIO.get(path); + } + + public void set(CharSequence path, String value) throws IOException { + databaseNodesIO.set(path, value); + } + + public boolean exists(CharSequence path) throws IOException { + return databaseNodesIO.exists(path); + } +} diff --git a/src/main/java/it/cavallium/strangedb/server/Node.java b/src/main/java/it/cavallium/strangedb/server/Node.java new file mode 100644 index 0000000..4ca04ff --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/server/Node.java @@ -0,0 +1,7 @@ +package it.cavallium.strangedb.server; + +public interface Node { + NodeType getType(); + long getReference(); + Node copy(); +} diff --git a/src/main/java/it/cavallium/strangedb/server/NodeProperty.java b/src/main/java/it/cavallium/strangedb/server/NodeProperty.java new file mode 100644 index 0000000..96ef64a --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/server/NodeProperty.java @@ -0,0 +1,25 @@ +package it.cavallium.strangedb.server; + +import java.nio.charset.StandardCharsets; + +public class NodeProperty { + private final byte[] name; + private final long reference; + + public NodeProperty(byte[] name, long reference) { + this.name = name; + this.reference = reference; + } + + public byte[] getName() { + return name; + } + + public long getReference() { + return reference; + } + + public String getNameAsString() { + return new String(name, StandardCharsets.US_ASCII); + } +} diff --git a/src/main/java/it/cavallium/strangedb/server/NodeType.java b/src/main/java/it/cavallium/strangedb/server/NodeType.java new file mode 100644 index 0000000..ca74e54 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/server/NodeType.java @@ -0,0 +1,8 @@ +package it.cavallium.strangedb.server; + +public enum NodeType { + VALUE, + CLASS, + ARRAY, + NUMBER; +} diff --git a/src/main/java/it/cavallium/strangedb/server/NumberNode.java b/src/main/java/it/cavallium/strangedb/server/NumberNode.java new file mode 100644 index 0000000..4248474 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/server/NumberNode.java @@ -0,0 +1,35 @@ +package it.cavallium.strangedb.server; + +public class NumberNode implements Node { + + private final long reference; + private long value; + + public NumberNode(long reference, long value) { + this.reference = reference; + this.value = value; + } + + public long getNumberReference() { + return value; + } + + public void setValue(long value) { + this.value = value; + } + + @Override + public NodeType getType() { + return NodeType.NUMBER; + } + + @Override + public long getReference() { + return reference; + } + + @Override + public Node copy() { + return new NumberNode(reference, value); + } +} diff --git a/src/main/java/it/cavallium/strangedb/server/Server.java b/src/main/java/it/cavallium/strangedb/server/Server.java index 85b8e26..e02ff14 100644 --- a/src/main/java/it/cavallium/strangedb/server/Server.java +++ b/src/main/java/it/cavallium/strangedb/server/Server.java @@ -1,4 +1,51 @@ package it.cavallium.strangedb.server; +import com.sun.net.httpserver.HttpServer; +import it.cavallium.strangedb.server.http.ExistsHandler; +import it.cavallium.strangedb.server.http.GetHandler; +import it.cavallium.strangedb.server.http.SetHandler; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.file.Path; +import java.nio.file.Paths; + public class Server { + private final DatabaseSimple database; + + public Server(DatabaseSimple database) throws IOException { + this.database = database; + HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0); + server.createContext("/get", new GetHandler(this)); + server.createContext("/set", new SetHandler(this)); + server.createContext("/exists", new ExistsHandler(this)); + server.setExecutor(null); + server.start(); + } + + /** + *

Start the server

+ * java -jar server.jar <database-directory> + * @param args + */ + public static void main(String[] args) throws IOException { + if (args.length != 1) { + System.err.println("Usage: java -jar server.jar "); + } + Path databasePath = Paths.get(args[0]); + DatabaseSimple database = new DatabaseSimple(databasePath.resolve("database.db"), databasePath.resolve("database.blocks.dat"), databasePath.resolve("database.references.dat")); + new Server(database); + } + + public boolean exists(CharSequence path) throws IOException { + return database.exists(path); + } + + public String get(CharSequence path) throws IOException { + return database.get(path); + } + + public void set(CharSequence path, String value) throws IOException { + database.set(path, value); + } } diff --git a/src/main/java/it/cavallium/strangedb/server/TreePath.java b/src/main/java/it/cavallium/strangedb/server/TreePath.java new file mode 100644 index 0000000..059c134 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/server/TreePath.java @@ -0,0 +1,159 @@ +package it.cavallium.strangedb.server; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; + +public class TreePath { + public final TreePath parent; + private final byte[] node; + private final int offset; + + private TreePath() { + parent = null; + node = null; + offset = 0; + } + + private TreePath(TreePath parent, byte[] node) { + this.parent = parent; + this.node = node; + this.offset = 0; + } + + private TreePath(TreePath parent, int offset) { + this.parent = parent; + this.node = null; + this.offset = offset; + } + + public TreePath resolveArrayElement(int offset) { + return new TreePath(this, offset); + } + + public TreePath resolveNode(byte[] child) { + return new TreePath(this, child); + } + + public boolean isNodeProperty() { + return (isRoot() || node != null); + } + + public boolean isArrayOffset() { + return !isNodeProperty(); + } + + public byte[] getNodeValue() { + if(node == null || isRoot()) + throw new NullPointerException(); + return node; + } + + public int getArrayOffset() { + if(node != null || isRoot()) + throw new NullPointerException(); + return offset; + } + + public boolean hasParent() { + return parent != null; + } + + public TreePath getParent() { + if (parent == null) + throw new NullPointerException(); + return parent; + } + + @Override + public String toString() { + return toStringBuilder().toString(); + } + + /** + * Convert to string the actual TreePath + * @return The TreePath as a string + */ + private StringBuilder toStringBuilder() { + StringBuilder builder; + if (parent == null) { + builder = new StringBuilder(); + } else { + builder = parent.toStringBuilder(); + } + if (isRoot()) { + return builder; + } + if (node != null) { + if (parent != null && !parent.isRoot()) + builder.append('.'); + builder.append(nodeToString(node)); + } else { + builder.append('[').append(offset).append(']'); + } + return builder; + } + + /** + * Convert node bytes to a StringBuilder + * @param node node letters + * @return node letters joined together + */ + public static StringBuilder nodeToString(byte[] node) { + StringBuilder string = new StringBuilder(); + for (byte letter : node) { + string.append((char) letter); + } + return string; + } + + public static byte[] stringToNode(String text) { + return text.getBytes(StandardCharsets.US_ASCII); + } + + /** + * Convert a char sequence to a TreePath + * @param str char sequence + * @return The tree path + */ + public static TreePath get(CharSequence str) { + byte[] currentName = new byte[32]; + byte currentNamePosition = 0; + TreePath currentTreePath = new TreePath(); + for (int i = 0; i < str.length(); i++) { + byte character = (byte) str.charAt(i); + if (character >= '0' && character <= '9' + || character >= 'A' && character <= 'Z' + || character >= 'a' && character <= 'z' + || character == '_') { + currentName[currentNamePosition] = character; + currentNamePosition++; + } else if((character == '.' || character == '[') && currentNamePosition > 0) { + currentTreePath = currentTreePath.resolveNode(Arrays.copyOf(currentName, currentNamePosition)); + currentNamePosition = 0; + } else if (character == ']') { + if (currentNamePosition == 0) throw new NullPointerException(); + int arrayOffset = toInt(Arrays.copyOf(currentName, currentNamePosition)); + currentTreePath = currentTreePath.resolveArrayElement(arrayOffset); + currentNamePosition = 0; + } + } + if (currentNamePosition != 0) { + currentTreePath = currentTreePath.resolveNode(Arrays.copyOf(currentName, currentNamePosition)); + } + return currentTreePath; + } + + private static int toInt(byte[] number) { + int result = 0; + int tenpower = 1; + for (int i = number.length - 1; i >= 0; i--) { + result += (number[i] - '0') * tenpower; + tenpower *= 10; + } + return result; + } + + public boolean isRoot() { + return parent == null; + } +} diff --git a/src/main/java/it/cavallium/strangedb/server/TreePathWalker.java b/src/main/java/it/cavallium/strangedb/server/TreePathWalker.java new file mode 100644 index 0000000..9022948 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/server/TreePathWalker.java @@ -0,0 +1,46 @@ +package it.cavallium.strangedb.server; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +public class TreePathWalker { + private TreePath parts[]; + private int currentPosition; + + public TreePathWalker(TreePath path) { + List parts = new LinkedList<>(); + parts.add(path); + while (path.hasParent()) { + path = path.getParent(); + parts.add(path); + } + Collections.reverse(parts); + this.parts = parts.toArray(new TreePath[0]); + currentPosition = this.parts.length - 1; + } + + public TreePath walkToRoot() { + return parts[currentPosition = 0]; + } + + public TreePath current() { + return parts[currentPosition]; + } + + public boolean hasNext() { + return currentPosition + 1 < parts.length; + } + + public boolean hasPrevious() { + return currentPosition - 1 >= 0; + } + + public TreePath next() { + return parts[++currentPosition]; + } + + public TreePath previous() { + return parts[--currentPosition]; + } +} diff --git a/src/main/java/it/cavallium/strangedb/server/ValueNode.java b/src/main/java/it/cavallium/strangedb/server/ValueNode.java new file mode 100644 index 0000000..4d8a771 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/server/ValueNode.java @@ -0,0 +1,37 @@ +package it.cavallium.strangedb.server; + +import java.util.Arrays; + +public class ValueNode implements Node { + + private final long reference; + private long value; + + public ValueNode(long reference, long value) { + this.reference = reference; + this.value = value; + } + + public long getValueReference() { + return value; + } + + public void setValue(long value) { + this.value = value; + } + + @Override + public NodeType getType() { + return NodeType.VALUE; + } + + @Override + public long getReference() { + return reference; + } + + @Override + public Node copy() { + return new ValueNode(reference, value); + } +} diff --git a/src/main/java/it/cavallium/strangedb/server/http/ExistsHandler.java b/src/main/java/it/cavallium/strangedb/server/http/ExistsHandler.java new file mode 100644 index 0000000..87c23b7 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/server/http/ExistsHandler.java @@ -0,0 +1,37 @@ +package it.cavallium.strangedb.server.http; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import it.cavallium.strangedb.server.Server; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +public class ExistsHandler implements HttpHandler { + + private final Server server; + + public ExistsHandler(Server server) { + this.server = server; + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + String requestPath = exchange.getRequestURI().toString().split("/exists/", 2)[1].replace('(', '[').replace(')', ']'); + int responseCode = 500; + String response; + try { + response = "" + server.exists(requestPath); + responseCode = 200; + } catch (Exception ex) { + ex.printStackTrace(); + response = "Error"; + } + byte[] responseBytes = response.getBytes(StandardCharsets.UTF_8); + exchange.sendResponseHeaders(responseCode, responseBytes.length); + OutputStream os = exchange.getResponseBody(); + os.write(responseBytes); + os.close(); + } +} diff --git a/src/main/java/it/cavallium/strangedb/server/http/GetHandler.java b/src/main/java/it/cavallium/strangedb/server/http/GetHandler.java new file mode 100644 index 0000000..9924bb8 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/server/http/GetHandler.java @@ -0,0 +1,37 @@ +package it.cavallium.strangedb.server.http; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import it.cavallium.strangedb.server.Server; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +public class GetHandler implements HttpHandler { + + private final Server server; + + public GetHandler(Server server) { + this.server = server; + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + String requestPath = exchange.getRequestURI().toString().split("/get/", 2)[1].replace('(', '[').replace(')', ']'); + int responseCode = 500; + String response; + try { + response = server.get(requestPath); + responseCode = 200; + } catch (Exception ex) { + ex.printStackTrace(); + response = "Error"; + } + byte[] responseBytes = response.getBytes(StandardCharsets.UTF_8); + exchange.sendResponseHeaders(responseCode, responseBytes.length); + OutputStream os = exchange.getResponseBody(); + os.write(responseBytes); + os.close(); + } +} diff --git a/src/main/java/it/cavallium/strangedb/server/http/SetHandler.java b/src/main/java/it/cavallium/strangedb/server/http/SetHandler.java new file mode 100644 index 0000000..bcf4dc0 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/server/http/SetHandler.java @@ -0,0 +1,43 @@ +package it.cavallium.strangedb.server.http; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import it.cavallium.strangedb.server.Server; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +public class SetHandler implements HttpHandler { + + private final Server server; + + public SetHandler(Server server) { + this.server = server; + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + String requestPath = exchange.getRequestURI().toString().split("/set/", 2)[1].replace('(', '[').replace(')', ']'); + String requestBody = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + int responseCode = 500; + String response; + try { + if (exchange.getRequestMethod().equalsIgnoreCase("POST")) { + server.set(requestPath, requestBody); + response = "ok"; + responseCode = 200; + } else { + response = "The request method is not a POST"; + } + } catch (Exception ex) { + ex.printStackTrace(); + response = "Error"; + } + byte[] responseBytes = response.getBytes(StandardCharsets.UTF_8); + exchange.sendResponseHeaders(responseCode, responseBytes.length); + OutputStream os = exchange.getResponseBody(); + os.write(responseBytes); + os.close(); + } +} diff --git a/src/test/java/it/cavallium/strangedb/server/GetSetExistsTest.java b/src/test/java/it/cavallium/strangedb/server/GetSetExistsTest.java new file mode 100644 index 0000000..e1349df --- /dev/null +++ b/src/test/java/it/cavallium/strangedb/server/GetSetExistsTest.java @@ -0,0 +1,57 @@ +package it.cavallium.strangedb.server; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static junit.framework.Assert.*; + +public class GetSetExistsTest { + + private Path path1; + private Path path2; + private Path path3; + private DatabaseSimple db; + + @Before + public void setUp() throws Exception { + path1 = Files.createTempFile("db-tests-", ".db"); + path2 = Files.createTempFile("db-tests-", ".db"); + path3 = Files.createTempFile("db-tests-", ".db"); + db = new DatabaseSimple(path1, path2, path3); + } + + @Test + public void shouldSetObject() throws IOException { + assertTrue(db.exists("")); + assertEquals(db.get(""), "{}"); + db.set("", "{}"); + assertTrue(db.exists("")); + assertEquals(db.get(""), "{}"); + db.set("brightness", "\"15\""); + } + + @Test + public void shouldGetObject() throws IOException { + assertFalse(db.exists("brightness")); + db.set("brightness", "\"15\""); + assertTrue(db.exists("brightness")); + assertEquals(db.get("brightness"), "\"15\""); + assertEquals(db.get(""), "{brightness:\"15\"}"); + db.set("brightness", "\"16\""); + assertEquals(db.get("brightness"), "\"16\""); + assertEquals(db.get(""), "{brightness:\"16\"}"); + } + + @After + public void tearDown() throws Exception { + db.close(); + Files.deleteIfExists(path1); + Files.deleteIfExists(path2); + Files.deleteIfExists(path3); + } +} diff --git a/src/test/java/it/cavallium/strangedb/server/strangedb/tests/Clean.java b/src/test/java/it/cavallium/strangedb/server/strangedb/tests/Clean.java deleted file mode 100644 index 9817b2c..0000000 --- a/src/test/java/it/cavallium/strangedb/server/strangedb/tests/Clean.java +++ /dev/null @@ -1,88 +0,0 @@ -package it.cavallium.strangedb.server.strangedb.tests; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import it.cavallium.strangedb.server.strangedb.EnhancedObject; -import it.cavallium.strangedb.server.strangedb.database.IDatabaseTools; -import it.cavallium.strangedb.server.strangedb.annotations.DbDataType; -import it.cavallium.strangedb.server.strangedb.annotations.DbField; -import it.cavallium.strangedb.server.strangedb.annotations.DbPropertyGetter; -import it.cavallium.strangedb.server.strangedb.annotations.DbPropertySetter; -import it.cavallium.strangedb.server.strangedb.utils.NTestUtils; - -import java.io.IOException; - -public class Clean { - private NTestUtils.WrappedDb db; - private RootTwoClasses root; - - @Before - public void setUp() throws Exception { - db = NTestUtils.wrapDb().create((db) -> { - root = db.get().loadRoot(RootTwoClasses.class, RootTwoClasses::new); - }); - root.class1 = new NTestUtils.RootClass(db.get()); - db.setRootClassValues(root.class1); - root.class2 = new NTestUtils.RootClass(db.get()); - db.setRootClassValues(root.class2); - root.setClass3(new NTestUtils.RootClass(db.get())); - db.setRootClassValues(root.getClass3()); - root.setClass4(new NTestUtils.RootClass(db.get())); - db.setRootClassValues(root.getClass4()); - } - - @Test - public void shouldMatchMultipleEnhancedObjects() throws IOException { - db.testRootClassValues(root.class1); - db.testRootClassValues(root.class2); - db.testRootClassValues(root.getClass3()); - db.testRootClassValues(root.getClass4()); - db.get().closeAndClean(); - db = NTestUtils.wrapDb().create((db) -> { - root = db.get().loadRoot(RootTwoClasses.class, RootTwoClasses::new); - }); - } - - @After - public void tearDown() throws Exception { - db.delete(); - } - - public static class RootTwoClasses extends EnhancedObject { - - @DbField(id = 0, type = DbDataType.ENHANCED_OBJECT) - public NTestUtils.RootClass class1; - - @DbField(id = 1, type = DbDataType.ENHANCED_OBJECT) - public NTestUtils.RootClass class2; - - public RootTwoClasses() { - super(); - } - - public RootTwoClasses(IDatabaseTools databaseTools) throws IOException { - super(databaseTools); - } - - @DbPropertyGetter(id = 0, type = DbDataType.ENHANCED_OBJECT) - public NTestUtils.RootClass getClass3() { - return getProperty(); - } - - @DbPropertySetter(id = 0, type = DbDataType.ENHANCED_OBJECT) - public void setClass3(NTestUtils.RootClass value) { - setProperty(value); - } - - @DbPropertyGetter(id = 1, type = DbDataType.ENHANCED_OBJECT) - public NTestUtils.RootClass getClass4() { - return getProperty(); - } - - @DbPropertySetter(id = 1, type = DbDataType.ENHANCED_OBJECT) - public void setClass4(NTestUtils.RootClass value) { - setProperty(value); - } - } -} diff --git a/src/test/java/it/cavallium/strangedb/server/strangedb/tests/EnhancedClassUpdate.java b/src/test/java/it/cavallium/strangedb/server/strangedb/tests/EnhancedClassUpdate.java deleted file mode 100644 index 40f8675..0000000 --- a/src/test/java/it/cavallium/strangedb/server/strangedb/tests/EnhancedClassUpdate.java +++ /dev/null @@ -1,50 +0,0 @@ -package it.cavallium.strangedb.server.strangedb.tests; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import it.cavallium.strangedb.server.strangedb.database.Database; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; - -import static org.junit.Assert.assertEquals; - -public class EnhancedClassUpdate { - - private Path path1; - private Path path2; - private Path path3; - private Database db; - - @Before - public void setUp() throws Exception { - path1 = Files.createTempFile("db-tests-", ".db"); - path2 = Files.createTempFile("db-tests-", ".db"); - path3 = Files.createTempFile("db-tests-", ".db"); - db = new Database(path1, path2, path3); - OldClass root = db.loadRoot(OldClass.class, OldClass::new); - root.field1 = "Abc"; - root.field2 = 12; - root.field4 = 13; - db.close(); - } - - @Test - public void shouldUpdateClass() throws IOException { - db = new Database(path1, path2, path3); - V2Class root = db.loadRoot(V2Class.class, V2Class::new); - assertEquals(root.field4, "Abc"); - assertEquals(root.field2, 12); - assertEquals(root.field1, 13L); - db.close(); - } - - @After - public void tearDown() throws Exception { - Files.deleteIfExists(path1); - Files.deleteIfExists(path2); - Files.deleteIfExists(path3); - } -} diff --git a/src/test/java/it/cavallium/strangedb/server/strangedb/tests/MultipleEnhancedObjects.java b/src/test/java/it/cavallium/strangedb/server/strangedb/tests/MultipleEnhancedObjects.java deleted file mode 100644 index 78b882b..0000000 --- a/src/test/java/it/cavallium/strangedb/server/strangedb/tests/MultipleEnhancedObjects.java +++ /dev/null @@ -1,85 +0,0 @@ -package it.cavallium.strangedb.server.strangedb.tests; - -import it.cavallium.strangedb.server.strangedb.EnhancedObject; -import it.cavallium.strangedb.server.strangedb.annotations.DbDataType; -import it.cavallium.strangedb.server.strangedb.annotations.DbField; -import it.cavallium.strangedb.server.strangedb.annotations.DbPropertyGetter; -import it.cavallium.strangedb.server.strangedb.annotations.DbPropertySetter; -import it.cavallium.strangedb.server.strangedb.database.IDatabaseTools; -import it.cavallium.strangedb.server.strangedb.utils.NTestUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.IOException; - -public class MultipleEnhancedObjects { - private NTestUtils.WrappedDb db; - private RootTwoClasses root; - - @Before - public void setUp() throws Exception { - db = NTestUtils.wrapDb().create((db) -> { - root = db.get().loadRoot(RootTwoClasses.class, RootTwoClasses::new); - }); - root.class1 = new NTestUtils.RootClass(db.get()); - db.setRootClassValues(root.class1); - root.class2 = new NTestUtils.RootClass(db.get()); - db.setRootClassValues(root.class2); - root.setClass3(new NTestUtils.RootClass(db.get())); - db.setRootClassValues(root.getClass3()); - root.setClass4(new NTestUtils.RootClass(db.get())); - db.setRootClassValues(root.getClass4()); - db.closeAndReopen(); - } - - @Test - public void shouldMatchMultipleEnhancedObjects() { - db.testRootClassValues(root.class1); - db.testRootClassValues(root.class2); - db.testRootClassValues(root.getClass3()); - db.testRootClassValues(root.getClass4()); - } - - @After - public void tearDown() throws Exception { - db.delete(); - } - - public static class RootTwoClasses extends EnhancedObject { - - @DbField(id = 0, type = DbDataType.ENHANCED_OBJECT) - public NTestUtils.RootClass class1; - - @DbField(id = 1, type = DbDataType.ENHANCED_OBJECT) - public NTestUtils.RootClass class2; - - public RootTwoClasses() { - super(); - } - - public RootTwoClasses(IDatabaseTools databaseTools) throws IOException { - super(databaseTools); - } - - @DbPropertyGetter(id = 0, type = DbDataType.ENHANCED_OBJECT) - public NTestUtils.RootClass getClass3() { - return getProperty(); - } - - @DbPropertySetter(id = 0, type = DbDataType.ENHANCED_OBJECT) - public void setClass3(NTestUtils.RootClass value) { - setProperty(value); - } - - @DbPropertyGetter(id = 1, type = DbDataType.ENHANCED_OBJECT) - public NTestUtils.RootClass getClass4() { - return getProperty(); - } - - @DbPropertySetter(id = 1, type = DbDataType.ENHANCED_OBJECT) - public void setClass4(NTestUtils.RootClass value) { - setProperty(value); - } - } -} diff --git a/src/test/java/it/cavallium/strangedb/server/strangedb/tests/OldClass.java b/src/test/java/it/cavallium/strangedb/server/strangedb/tests/OldClass.java deleted file mode 100644 index eb1e66b..0000000 --- a/src/test/java/it/cavallium/strangedb/server/strangedb/tests/OldClass.java +++ /dev/null @@ -1,30 +0,0 @@ -package it.cavallium.strangedb.server.strangedb.tests; - -import it.cavallium.strangedb.server.strangedb.annotations.DbPrimitiveField; -import it.cavallium.strangedb.server.strangedb.annotations.DbPrimitiveType; -import it.cavallium.strangedb.server.strangedb.EnhancedObject; -import it.cavallium.strangedb.server.strangedb.database.IDatabaseTools; -import it.cavallium.strangedb.server.strangedb.annotations.DbDataType; -import it.cavallium.strangedb.server.strangedb.annotations.DbField; - -import java.io.IOException; - -public class OldClass extends EnhancedObject { - - @DbField(id = 0, type = DbDataType.OBJECT) - public String field1; - - @DbPrimitiveField(id = 0, type = DbPrimitiveType.INTEGER) - public int field2; - - @DbPrimitiveField(id = 2, type = DbPrimitiveType.INTEGER) - public int field4; - - public OldClass() { - - } - - public OldClass(IDatabaseTools databaseTools) throws IOException { - super(databaseTools); - } -} diff --git a/src/test/java/it/cavallium/strangedb/server/strangedb/tests/Performance.java b/src/test/java/it/cavallium/strangedb/server/strangedb/tests/Performance.java deleted file mode 100644 index bd355d0..0000000 --- a/src/test/java/it/cavallium/strangedb/server/strangedb/tests/Performance.java +++ /dev/null @@ -1,343 +0,0 @@ -package it.cavallium.strangedb.server.strangedb.tests; - -import it.cavallium.strangedb.annotations.*; -import it.cavallium.strangedb.server.strangedb.annotations.*; -import it.cavallium.strangedb.server.strangedb.functionalinterfaces.RunnableWithIO; -import it.cavallium.strangedb.server.strangedb.lists.EnhancedObjectStrandeDbList; -import it.cavallium.strangedb.server.strangedb.lists.ObjectStrandeDbList; -import it.unimi.dsi.fastutil.longs.LongArrayList; -import it.cavallium.strangedb.server.strangedb.database.Database; -import it.cavallium.strangedb.server.strangedb.EnhancedObject; -import it.cavallium.strangedb.server.strangedb.database.IDatabaseTools; -import it.cavallium.strangedb.server.strangedb.VariableWrapper; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; - -public class Performance { - private static boolean FAST_TESTS; - - private static Path rootDirectory; - private static Path dbDataFile; - private static Path dbBlocksFile; - private static Path dbReferencesFile; - private static Database db; - - /** - * - * @param args args[0] = true for fast tests - * @throws IOException - * @throws InterruptedException - */ - public static void main(String[] args) throws IOException, InterruptedException { - FAST_TESTS = args.length > 0 && args[0].equalsIgnoreCase("true"); - if (args.length >= 2) { - rootDirectory = Paths.get(args[1]); - try { - Files.createDirectory(rootDirectory); - } catch (Exception ex) { - - } - } else { - rootDirectory = Files.createTempDirectory("performance-tests"); - } - generateDb(); - System.out.println("Performance test started."); - System.out.println("-------------------------------------------------------+-----------------------------------------------------------------"); - System.out.println("Test name Total Time | Time at 1 Time at 10 Time at 100 Time at 1K Time at 10K"); - System.out.println("-------------------------------------------------------+-----------------------------------------------------------------"); - testS("Database creation", 3000, Performance::deleteDb, Performance::generateDb, () -> {}); - testS("Database root creation", 3000, Performance::regenDb, () -> db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new), () -> {}); - final VariableWrapper preloadedListContainer = new VariableWrapper<>(null); - final VariableWrapper simpleEnhancedObjectContainer = new VariableWrapper<>(null); - testS("ObjectStrandeDbList creation", 3000, () -> { - regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); - }, () -> preloadedListContainer.var.list = new ObjectStrandeDbList<>(db), () -> {}); - testS("ObjectStrandeDbList: Filling with 1000 items", 100, () -> { - regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); - preloadedListContainer.var.list = new ObjectStrandeDbList<>(db); - }, () -> { - for (int i = 0; i < 1000; i++) { - preloadedListContainer.var.list.add(1000); - } - }, () -> {}); - testS("ObjectStrandeDbList: Filling with 1000 items", 100, () -> { - regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); - preloadedListContainer.var.listOfEnhancedObj = new EnhancedObjectStrandeDbList<>(db, SimpleEnhancedObject.class); - simpleEnhancedObjectContainer.var = new SimpleEnhancedObject(db); - simpleEnhancedObjectContainer.var.integerNumber = 10; - simpleEnhancedObjectContainer.var.longNumber = 10L; - simpleEnhancedObjectContainer.var.object = new ArrayList<>(); - simpleEnhancedObjectContainer.var.object.add("XHIghicuiHUCB UIVY"); - simpleEnhancedObjectContainer.var.object.add("ioZ>UIHZXGHXYGY"); - simpleEnhancedObjectContainer.var.object.add("XJIOUIhcgGuigscwvyv"); - }, () -> { - for (int i = 0; i < 1000; i++) { - preloadedListContainer.var.listOfEnhancedObj.add(simpleEnhancedObjectContainer.var); - } - }, () -> {}); - testS("ObjectStrandeDbList: Filling with 10000 items", 10, () -> { - regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); - preloadedListContainer.var.list = new ObjectStrandeDbList<>(db); - }, () -> { - for (int i = 0; i < 10000; i++) { - preloadedListContainer.var.list.add(1000); - } - }, () -> {}); - testS("ObjectStrandeDbList: Filling with 100000 items", 1, () -> { - regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); - preloadedListContainer.var.list = new ObjectStrandeDbList<>(db); - }, () -> { - for (int i = 0; i < 100000; i++) { - preloadedListContainer.var.list.add(1000); - } - }, () -> {}); - testS("ObjectStrandeDbList: Loading 1000 items", 100, () -> { - regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); - preloadedListContainer.var.list = new ObjectStrandeDbList<>(db); - for (int i = 0; i < 1000; i++) { - preloadedListContainer.var.list.add(1000); - } - }, () -> { - for (int i = 0; i < 1000; i++) { - preloadedListContainer.var.list.get(i); - } - }, () -> {}); - testS("ObjectStrandeDbList: Loading with 1000 items", 100, () -> { - regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); - preloadedListContainer.var.listOfEnhancedObj = new EnhancedObjectStrandeDbList<>(db, SimpleEnhancedObject.class); - simpleEnhancedObjectContainer.var = new SimpleEnhancedObject(db); - simpleEnhancedObjectContainer.var.integerNumber = 10; - simpleEnhancedObjectContainer.var.longNumber = 10L; - simpleEnhancedObjectContainer.var.object = new ArrayList<>(); - simpleEnhancedObjectContainer.var.object.add("XHIghicuiHUCB UIVY"); - simpleEnhancedObjectContainer.var.object.add("ioZ>UIHZXGHXYGY"); - simpleEnhancedObjectContainer.var.object.add("XJIOUIhcgGuigscwvyv"); - for (int i = 0; i < 1000; i++) { - preloadedListContainer.var.listOfEnhancedObj.add(simpleEnhancedObjectContainer.var); - } - }, () -> { - for (int i = 0; i < 1000; i++) { - preloadedListContainer.var.listOfEnhancedObj.get(i); - } - }, () -> {}); - testS("ObjectStrandeDbList: Loading 10000 items", 10, () -> { - regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); - preloadedListContainer.var.list = new ObjectStrandeDbList<>(db); - for (int i = 0; i < 10000; i++) { - preloadedListContainer.var.list.add(1000); - } - }, () -> { - for (int i = 0; i < 10000; i++) { - preloadedListContainer.var.list.get(i); - } - }, () -> {}); - testS("ObjectStrandeDbList: getLast() with 1000 items", 100, () -> { - regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); - preloadedListContainer.var.list = new ObjectStrandeDbList<>(db); - for (int i = 0; i < 1000; i++) { - preloadedListContainer.var.list.add(1000); - } - }, () -> { - preloadedListContainer.var.list.getLast(); - }, () -> {}); - testS("ObjectStrandeDbList: getLast() with 1000 items", 100, () -> { - regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); - preloadedListContainer.var.listOfEnhancedObj = new EnhancedObjectStrandeDbList<>(db, SimpleEnhancedObject.class); - simpleEnhancedObjectContainer.var = new SimpleEnhancedObject(db); - simpleEnhancedObjectContainer.var.integerNumber = 10; - simpleEnhancedObjectContainer.var.longNumber = 10L; - simpleEnhancedObjectContainer.var.object = new ArrayList<>(); - simpleEnhancedObjectContainer.var.object.add("XHIghicuiHUCB UIVY"); - simpleEnhancedObjectContainer.var.object.add("ioZ>UIHZXGHXYGY"); - simpleEnhancedObjectContainer.var.object.add("XJIOUIhcgGuigscwvyv"); - for (int i = 0; i < 1000; i++) { - preloadedListContainer.var.listOfEnhancedObj.add(simpleEnhancedObjectContainer.var); - } - }, () -> { - preloadedListContainer.var.listOfEnhancedObj.getLast(); - }, () -> {}); - testS("ObjectStrandeDbList: size() with 1000 items", 100, () -> { - regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); - preloadedListContainer.var.list = new ObjectStrandeDbList<>(db); - for (int i = 0; i < 1000; i++) { - preloadedListContainer.var.list.add(1000); - } - }, () -> { - preloadedListContainer.var.list.size(); - }, () -> {}); - System.out.println("-------------------------------------------------------+-----------------------------------------------------------------"); - System.out.println("Performance test finished."); - deleteDb(); - Files.deleteIfExists(rootDirectory); - } - - private static void NtestS(String description, int times, RunnableWithIO beforeAction, RunnableWithIO action, RunnableWithIO afterAction) throws IOException, InterruptedException { - } - - - private static void testS(String description, int times, RunnableWithIO beforeAction, RunnableWithIO action, RunnableWithIO afterAction) throws IOException, InterruptedException { - if (FAST_TESTS) { - if (times >= 5) { - times /= 5; - } else if (times >= 2) { - times /= 2; - } - } - description = description + " time is"; - int spacesCount = 40 - description.length(); - int cutAt = 0; - if (spacesCount < 0) { - spacesCount = 40 - (description.length() - 40); - cutAt = 40; - } - StringBuilder spaces = new StringBuilder(); - for (int i = 0; i < spacesCount; i++) { - spaces.append(' '); - } - double[] results = test(times, beforeAction, action, afterAction); - if (cutAt > 0) { - System.out.println(description.substring(0, cutAt) + " |"); - } - System.out.printf("%s:%s%s%s%n", description.substring(cutAt), spaces, format(results[0]) + " |", results.length > 1 ? (format(results[1]) + (results.length > 2 ? (format(results[2]) + (results.length > 3 ? (format(results[3]) + (results.length > 4 ? (format(results[4]) + (results.length > 5 ? format(results[5]) : "")) : "")) : "")) : "")) : ""); - } - - private static String format(double result) { - String spaces; - if (result < 10) { - spaces = " "; - } else if (result < 100) { - spaces = " "; - } else if (result < 1000) { - spaces = " "; - } else { - spaces = " "; - } - return spaces + String.format("%.2fms", result); - } - - private static double[] test(int times, RunnableWithIO beforeAction, RunnableWithIO action, RunnableWithIO afterAction) throws IOException, InterruptedException { - LongArrayList results = new LongArrayList(times); - Thread.sleep(100); - System.gc(); - Thread.sleep(100); - for (int i = 0; i < times; i++) { - beforeAction.run(); - long startTime = System.nanoTime(); - action.run(); - long elapsedTime = System.nanoTime() - startTime; - afterAction.run(); - results.add(elapsedTime); - } - double result1 = results.stream().limit(1).mapToLong(val -> val).average().orElse(0.0) / 1000000d; - double result10 = results.stream().limit(10).mapToLong(val -> val).average().orElse(0.0) / 1000000d; - double result100 = results.stream().limit(100).mapToLong(val -> val).average().orElse(0.0) / 1000000d; - double result1000 = results.stream().limit(1000).mapToLong(val -> val).average().orElse(0.0) / 1000000d; - double result10000 = results.stream().limit(10000).mapToLong(val -> val).average().orElse(0.0) / 1000000d; - double resultMax = results.stream().mapToLong(val -> val).average().orElse(0.0) / 1000000d; - if (times <= 1) { - return new double[]{resultMax}; - } else if (times <= 10) { - return new double[]{resultMax, result1}; - } else if (times <= 100) { - return new double[]{resultMax, result1, result10}; - } else if (times <= 1000) { - return new double[]{resultMax, result1, result10, result100}; - } else if (times <= 10000) { - return new double[]{resultMax, result1, result10, result100, result1000}; - } else { - return new double[]{resultMax, result1, result10, result100, result1000, result10000}; - } - } - - public static void generateDb() throws IOException { - dbDataFile = Files.createFile(rootDirectory.resolve("db_data.dat")); - dbBlocksFile = Files.createFile(rootDirectory.resolve("db_blocks.dat")); - dbReferencesFile = Files.createFile(rootDirectory.resolve("db_references.dat")); - db = new Database(dbDataFile, dbBlocksFile, dbReferencesFile); - } - - public static void deleteDb() throws IOException { - db.close(); - Files.deleteIfExists(dbDataFile); - Files.deleteIfExists(dbBlocksFile); - Files.deleteIfExists(dbReferencesFile); - } - - public static void regenDb() throws IOException { - deleteDb(); - generateDb(); - } - - public static class PreloadedListContainer extends EnhancedObject { - - @DbField(id = 0, type = DbDataType.ENHANCED_OBJECT) - public ObjectStrandeDbList list; - - @DbField(id = 1, type = DbDataType.ENHANCED_OBJECT) - public EnhancedObjectStrandeDbList listOfEnhancedObj; - - public PreloadedListContainer() { - - } - - public PreloadedListContainer(IDatabaseTools databaseTools) throws IOException { - super(databaseTools); - } - } - - public static class DynamicListContainer extends EnhancedObject { - - public DynamicListContainer() { - - } - - public DynamicListContainer(IDatabaseTools databaseTools) throws IOException { - super(databaseTools); - } - - - @DbPropertyGetter(id = 0, type = DbDataType.ENHANCED_OBJECT) - public ObjectStrandeDbList getList() { - return getProperty(); - } - - @DbPropertySetter(id = 1, type = DbDataType.ENHANCED_OBJECT) - public void setList(ObjectStrandeDbList list) { - setProperty(list); - } - } - - public static class SimpleEnhancedObject extends EnhancedObject { - public SimpleEnhancedObject() { - - } - - public SimpleEnhancedObject(IDatabaseTools databaseTools) throws IOException { - super(databaseTools); - } - - @DbField(id = 0, type = DbDataType.OBJECT) - public ArrayList object; - - @DbPrimitiveField(id = 0, type = DbPrimitiveType.INTEGER) - public int integerNumber; - - @DbPrimitiveField(id = 1, type = DbPrimitiveType.LONG) - public long longNumber; - } -} diff --git a/src/test/java/it/cavallium/strangedb/server/strangedb/tests/V2Class.java b/src/test/java/it/cavallium/strangedb/server/strangedb/tests/V2Class.java deleted file mode 100644 index 0209781..0000000 --- a/src/test/java/it/cavallium/strangedb/server/strangedb/tests/V2Class.java +++ /dev/null @@ -1,44 +0,0 @@ -package it.cavallium.strangedb.server.strangedb.tests; - -import it.cavallium.strangedb.server.strangedb.EnhancedObjectUpgrader; -import it.cavallium.strangedb.server.strangedb.annotations.DbDataType; -import it.cavallium.strangedb.server.strangedb.annotations.DbField; -import it.cavallium.strangedb.server.strangedb.annotations.DbPrimitiveField; -import it.cavallium.strangedb.server.strangedb.annotations.DbPrimitiveType; -import it.cavallium.strangedb.server.strangedb.EnhancedObject; -import it.cavallium.strangedb.server.strangedb.database.IDatabaseTools; -import it.cavallium.strangedb.server.strangedb.annotations.DbClass; - -import java.io.IOException; - -@DbClass(version = 1) -public class V2Class extends EnhancedObject { - @DbPrimitiveField(id = 0, type = DbPrimitiveType.LONG) - public long field1; - - @DbPrimitiveField(id = 1, type = DbPrimitiveType.INTEGER) - public int field2; - - @DbField(id = 0, type = DbDataType.OBJECT) - public String field4; - - public V2Class() { - - } - - public V2Class(IDatabaseTools databaseTools) throws IOException { - super(databaseTools); - } - - @Override - public void onUpgrade(int oldObjectVersion, EnhancedObjectUpgrader enhancedObjectUpgrader) throws IOException { - switch (oldObjectVersion) { - case 0: { - field1 = (long) enhancedObjectUpgrader.getPrimitiveInt(2); - field2 = enhancedObjectUpgrader.getPrimitiveInt(0); - field4 = (String) enhancedObjectUpgrader.getField(0, DbDataType.OBJECT); - break; - } - } - } -} diff --git a/src/test/java/it/cavallium/strangedb/server/strangedb/utils/ConsumerWithIO.java b/src/test/java/it/cavallium/strangedb/server/strangedb/utils/ConsumerWithIO.java deleted file mode 100644 index fa3b8cf..0000000 --- a/src/test/java/it/cavallium/strangedb/server/strangedb/utils/ConsumerWithIO.java +++ /dev/null @@ -1,32 +0,0 @@ -package it.cavallium.strangedb.server.strangedb.utils; - -import java.io.IOException; -import java.util.Objects; - -@FunctionalInterface -public interface ConsumerWithIO { - - /** - * Performs this operation on the given argument. - * - * @param t the input argument - */ - void accept(T t) throws IOException; - - /** - * Returns a composed {@code Consumer} that performs, in sequence, this - * operation followed by the {@code after} operation. If performing either - * operation throws an exception, it is relayed to the caller of the - * composed operation. If performing this operation throws an exception, - * the {@code after} operation will not be performed. - * - * @param after the operation to perform after this operation - * @return a composed {@code Consumer} that performs in sequence this - * operation followed by the {@code after} operation - * @throws NullPointerException if {@code after} is null - */ - default ConsumerWithIO andThen(ConsumerWithIO after) { - Objects.requireNonNull(after); - return (T t) -> { accept(t); after.accept(t); }; - } -} diff --git a/src/test/java/it/cavallium/strangedb/server/strangedb/utils/NSimplestClass.java b/src/test/java/it/cavallium/strangedb/server/strangedb/utils/NSimplestClass.java deleted file mode 100644 index 25a7465..0000000 --- a/src/test/java/it/cavallium/strangedb/server/strangedb/utils/NSimplestClass.java +++ /dev/null @@ -1,23 +0,0 @@ -package it.cavallium.strangedb.server.strangedb.utils; - -import it.cavallium.strangedb.server.strangedb.annotations.DbPrimitiveField; -import it.cavallium.strangedb.server.strangedb.annotations.DbPrimitiveType; -import it.cavallium.strangedb.server.strangedb.database.Database; -import it.cavallium.strangedb.server.strangedb.EnhancedObject; - -import java.io.IOException; - -public class NSimplestClass extends EnhancedObject { - - @DbPrimitiveField(id = 0, type = DbPrimitiveType.BOOLEAN) - public boolean field1; - - public NSimplestClass() { - - } - - public NSimplestClass(Database database) throws IOException { - super(database); - field1 = true; - } -} diff --git a/src/test/java/it/cavallium/strangedb/server/strangedb/utils/NTestUtils.java b/src/test/java/it/cavallium/strangedb/server/strangedb/utils/NTestUtils.java deleted file mode 100644 index 4c1dd5a..0000000 --- a/src/test/java/it/cavallium/strangedb/server/strangedb/utils/NTestUtils.java +++ /dev/null @@ -1,284 +0,0 @@ -package it.cavallium.strangedb.server.strangedb.utils; - -import it.cavallium.strangedb.annotations.*; -import it.cavallium.strangedb.server.strangedb.annotations.*; -import it.cavallium.strangedb.server.strangedb.functionalinterfaces.RunnableWithIO; -import it.unimi.dsi.fastutil.longs.LongArrayList; -import it.cavallium.strangedb.server.strangedb.database.Database; -import it.cavallium.strangedb.server.strangedb.EnhancedObject; -import it.cavallium.strangedb.server.strangedb.database.IDatabaseTools; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Comparator; - -import static org.junit.Assert.*; - -public class NTestUtils { - public static WrappedDb wrapDb() { - return new WrappedDb(); - } - - public static class WrappedDb { - - private Database db; - private Path tempDir; - private RunnableWithIO r; - - private WrappedDb() { - - } - - public WrappedDb create() throws IOException { - tempDir = Files.createTempDirectory("tests-"); - db = openDatabase(); - if (r != null) { - r.run(); - } - return this; - } - - public WrappedDb create(ConsumerWithIO r) throws IOException { - this.r = () -> r.accept(WrappedDb.this); - this.create(); - return this; - } - - private Database openDatabase() throws IOException { - return new Database(tempDir.resolve(Paths.get("data.db")), tempDir.resolve(Paths.get("blocks.dat")), tempDir.resolve(Paths.get("references.dat"))); - } - - public void delete() throws IOException { - db.close(); - deleteDir(tempDir); - } - - public Database get() { - return db; - } - - private void deleteDir(Path p) throws IOException { - Files.walk(p) - .sorted(Comparator.reverseOrder()) - .map(Path::toFile) - .forEach(File::delete); - } - - public void closeAndReopen() throws IOException { - db.close(); - db = openDatabase(); - r.run(); - } - - public void setRootClassValues(RootClass root) throws IOException { - setRootClassFields(root); - setRootClassProperties(root); - } - - public void setRootClassFields(RootClass root) throws IOException { - root.field1 = true; - root.field2 = 2; - root.field3 = 3; - root.field4 = 4; - root.field5 = 5; - root.field6 = 6; - root.field7 = "Test"; - root.field8 = new LongArrayList(); - root.field8.add(0); - root.field8.add(1); - root.field8.add(2); - root.field8.add(Long.MAX_VALUE/2); - root.field8.add(Long.MIN_VALUE/2); - root.field8.add(Long.MAX_VALUE); - root.field8.add(Long.MIN_VALUE); - root.field9 = new NSimplestClass(db); - root.field9.field1 = true; - - } - - public void setRootClassProperties(RootClass root) throws IOException { - root.set7("Test"); - LongArrayList lArrayList = new LongArrayList(); - lArrayList.add(0); - lArrayList.add(1); - lArrayList.add(2); - lArrayList.add(Long.MAX_VALUE/2); - lArrayList.add(Long.MIN_VALUE/2); - lArrayList.add(Long.MAX_VALUE); - lArrayList.add(Long.MIN_VALUE); - root.set8(lArrayList); - NSimplestClass simplestClass9 = new NSimplestClass(db); - simplestClass9.field1 = true; - root.set9(simplestClass9); - } - - public void testRootClassValues(RootClass root) { - testRootClassFields(root); - testRootClassProperties(root); - } - - public void testRootClassFields(RootClass root) { - shouldGetFieldBoolean(root); - shouldGetFieldByte(root); - shouldGetFieldShort(root); - shouldGetFieldCharacter(root); - shouldGetFieldInteger(root); - shouldGetFieldLong(root); - shouldGetFieldObject(root); - shouldGetFieldUID(root); - shouldGetFieldDBObject(root); - } - - public void testRootClassProperties(RootClass root) { - shouldGetPropertyObject(root); - shouldGetPropertyUID(root); - shouldGetPropertyDBObject(root); - } - - - private void shouldGetFieldBoolean(RootClass root) { - assertTrue(root.field1); - } - - private void shouldGetFieldByte(RootClass root) { - assertEquals(2, root.field2); - } - - private void shouldGetFieldShort(RootClass root) { - assertEquals(3, root.field3); - } - - private void shouldGetFieldCharacter(RootClass root) { - assertEquals(4, root.field4); - } - - private void shouldGetFieldInteger(RootClass root) { - assertEquals(5, root.field5); - } - - private void shouldGetFieldLong(RootClass root) { - assertEquals(6, root.field6); - } - - private void shouldGetFieldObject(RootClass root) { - shouldGetObject(root.field7); - } - - private void shouldGetPropertyObject(RootClass root) { - shouldGetObject(root.get7()); - } - - private void shouldGetFieldDBObject(RootClass root) { - assertTrue(root.field9.field1); - } - - private void shouldGetPropertyDBObject(RootClass root) { - assertTrue(root.get9().field1); - } - - private void shouldGetObject(String val) { - assertNotNull(val); - assertEquals("Test", val); - } - - private void shouldGetDBObject(NSimplestClass val) { - assertNotNull(val); - assertTrue(val.field1); - } - - private void shouldGetFieldUID(RootClass root) { - shouldGetUID(root.field8); - } - - private void shouldGetPropertyUID(RootClass root) { - shouldGetUID(root.get8()); - } - - private void shouldGetUID(LongArrayList val) { - assertNotNull(val); - assertEquals(7, val.size()); - assertEquals(0, val.getLong(0)); - assertEquals(val.getLong(5), Long.MAX_VALUE); - assertEquals(val.getLong(6), Long.MIN_VALUE); - } - - public void onLoad(RunnableWithIO r) { - this.r = r; - } - } - - public static class RootClass extends EnhancedObject { - - @DbPrimitiveField(id = 0, type = DbPrimitiveType.BOOLEAN) - public boolean field1; - - @DbPrimitiveField(id = 1, type = DbPrimitiveType.BYTE) - public byte field2; - - @DbPrimitiveField(id = 2, type = DbPrimitiveType.SHORT) - public short field3; - - @DbPrimitiveField(id = 3, type = DbPrimitiveType.CHAR) - public char field4; - - @DbPrimitiveField(id = 4, type = DbPrimitiveType.INTEGER) - public int field5; - - @DbPrimitiveField(id = 5, type = DbPrimitiveType.LONG) - public long field6; - - @DbField(id = 0, type = DbDataType.OBJECT) - public String field7; - - @DbField(id = 1, type = DbDataType.REFERENCES_LIST) - public LongArrayList field8; - - @DbField(id = 2, type = DbDataType.ENHANCED_OBJECT) - public NSimplestClass field9; - - public RootClass() { - - } - - public RootClass(IDatabaseTools databaseTools) throws IOException { - super(databaseTools); - } - - @DbPropertyGetter(id = 0, type = DbDataType.OBJECT) - public String get7() { - return getProperty(); - } - - @DbPropertyGetter(id = 1, type = DbDataType.REFERENCES_LIST) - public LongArrayList get8() { - return getProperty(); - } - - @DbPropertyGetter(id = 2, type = DbDataType.ENHANCED_OBJECT) - public NSimplestClass get9() { - return getProperty(); - } - - @DbPropertySetter(id = 0, type = DbDataType.OBJECT) - public void set7(String val) { - setProperty(val); - } - - @DbPropertySetter(id = 1, type = DbDataType.REFERENCES_LIST) - public void set8(LongArrayList val) { - setProperty(val); - } - - @DbPropertySetter(id = 2, type = DbDataType.ENHANCED_OBJECT) - public void set9(NSimplestClass val) { - setProperty(val); - } - - public boolean test() { - return true; - } - } -}