diff --git a/pom.xml b/pom.xml
index e3122bd..b20e8bd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,11 +39,6 @@
ipaddress
5.4.0
-
- com.typesafe
- config
- 1.4.3
-
org.jetbrains
annotations
diff --git a/src/main/java/it/cavallium/rockserver/core/Main.java b/src/main/java/it/cavallium/rockserver/core/Main.java
index dcf1985..2f6d187 100644
--- a/src/main/java/it/cavallium/rockserver/core/Main.java
+++ b/src/main/java/it/cavallium/rockserver/core/Main.java
@@ -18,7 +18,6 @@ import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;
-import org.rocksdb.RocksDB;
public class Main {
diff --git a/src/main/java/it/cavallium/rockserver/core/client/EmbeddedConnection.java b/src/main/java/it/cavallium/rockserver/core/client/EmbeddedConnection.java
index 6f974a8..0a1eb87 100644
--- a/src/main/java/it/cavallium/rockserver/core/client/EmbeddedConnection.java
+++ b/src/main/java/it/cavallium/rockserver/core/client/EmbeddedConnection.java
@@ -13,6 +13,7 @@ import java.net.URI;
import java.nio.file.Path;
import java.util.Optional;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class EmbeddedConnection extends BaseConnection {
@@ -47,7 +48,7 @@ public class EmbeddedConnection extends BaseConnection {
}
@Override
- public long createColumn(String name, ColumnSchema schema) {
+ public long createColumn(String name, @NotNull ColumnSchema schema) {
return db.createColumn(name, schema);
}
@@ -57,7 +58,7 @@ public class EmbeddedConnection extends BaseConnection {
}
@Override
- public long getColumnId(String name) {
+ public long getColumnId(@NotNull String name) {
return db.getColumnId(name);
}
@@ -65,8 +66,8 @@ public class EmbeddedConnection extends BaseConnection {
public T put(Arena arena,
long transactionId,
long columnId,
- MemorySegment[] keys,
- @Nullable MemorySegment value,
+ @NotNull MemorySegment @NotNull [] keys,
+ @NotNull MemorySegment value,
PutCallback super MemorySegment, T> callback) throws RocksDBException {
return db.put(arena, transactionId, columnId, keys, value, callback);
}
@@ -75,7 +76,7 @@ public class EmbeddedConnection extends BaseConnection {
public T get(Arena arena,
long transactionId,
long columnId,
- MemorySegment[] keys,
+ MemorySegment @NotNull [] keys,
GetCallback super MemorySegment, T> callback) throws RocksDBException {
return db.get(arena, transactionId, columnId, keys, callback);
}
@@ -84,7 +85,7 @@ public class EmbeddedConnection extends BaseConnection {
public long openIterator(Arena arena,
long transactionId,
long columnId,
- MemorySegment[] startKeysInclusive,
+ @NotNull MemorySegment @NotNull [] startKeysInclusive,
@Nullable MemorySegment[] endKeysExclusive,
boolean reverse,
long timeoutMs) throws RocksDBException {
@@ -97,7 +98,7 @@ public class EmbeddedConnection extends BaseConnection {
}
@Override
- public void seekTo(Arena arena, long iterationId, MemorySegment[] keys) throws RocksDBException {
+ public void seekTo(Arena arena, long iterationId, MemorySegment @NotNull [] keys) throws RocksDBException {
db.seekTo(arena, iterationId, keys);
}
@@ -106,7 +107,7 @@ public class EmbeddedConnection extends BaseConnection {
long iterationId,
long skipCount,
long takeCount,
- IteratorCallback super MemorySegment, T> callback) throws RocksDBException {
+ @NotNull IteratorCallback super MemorySegment, T> callback) throws RocksDBException {
return db.subsequent(arena, iterationId, skipCount, takeCount, callback);
}
}
diff --git a/src/main/java/it/cavallium/rockserver/core/client/RocksDBConnection.java b/src/main/java/it/cavallium/rockserver/core/client/RocksDBConnection.java
index 369aaee..768b0f5 100644
--- a/src/main/java/it/cavallium/rockserver/core/client/RocksDBConnection.java
+++ b/src/main/java/it/cavallium/rockserver/core/client/RocksDBConnection.java
@@ -3,7 +3,6 @@ package it.cavallium.rockserver.core.client;
import it.cavallium.rockserver.core.common.RocksDBAPI;
import java.io.Closeable;
import java.net.URI;
-import org.jetbrains.annotations.Nullable;
public interface RocksDBConnection extends Closeable, RocksDBAPI {
diff --git a/src/main/java/it/cavallium/rockserver/core/client/SocketConnection.java b/src/main/java/it/cavallium/rockserver/core/client/SocketConnection.java
index c1d757e..4021a2b 100644
--- a/src/main/java/it/cavallium/rockserver/core/client/SocketConnection.java
+++ b/src/main/java/it/cavallium/rockserver/core/client/SocketConnection.java
@@ -9,6 +9,7 @@ import java.io.IOException;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.net.SocketAddress;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class SocketConnection extends BaseConnection {
@@ -39,7 +40,7 @@ public abstract class SocketConnection extends BaseConnection {
}
@Override
- public long createColumn(String name, ColumnSchema schema) {
+ public long createColumn(String name, @NotNull ColumnSchema schema) {
throw new UnsupportedOperationException();
}
@@ -49,7 +50,7 @@ public abstract class SocketConnection extends BaseConnection {
}
@Override
- public long getColumnId(String name) {
+ public long getColumnId(@NotNull String name) {
throw new UnsupportedOperationException();
}
@@ -57,8 +58,8 @@ public abstract class SocketConnection extends BaseConnection {
public T put(Arena arena,
long transactionId,
long columnId,
- MemorySegment[] keys,
- @Nullable MemorySegment value,
+ MemorySegment @NotNull [] keys,
+ @NotNull MemorySegment value,
PutCallback super MemorySegment, T> callback) throws RocksDBException {
throw new UnsupportedOperationException();
}
@@ -67,7 +68,7 @@ public abstract class SocketConnection extends BaseConnection {
public T get(Arena arena,
long transactionId,
long columnId,
- MemorySegment[] keys,
+ MemorySegment @NotNull [] keys,
GetCallback super MemorySegment, T> callback) throws RocksDBException {
throw new UnsupportedOperationException();
}
@@ -76,7 +77,7 @@ public abstract class SocketConnection extends BaseConnection {
public long openIterator(Arena arena,
long transactionId,
long columnId,
- MemorySegment[] startKeysInclusive,
+ MemorySegment @NotNull [] startKeysInclusive,
@Nullable MemorySegment[] endKeysExclusive,
boolean reverse,
long timeoutMs) throws RocksDBException {
@@ -89,7 +90,7 @@ public abstract class SocketConnection extends BaseConnection {
}
@Override
- public void seekTo(Arena arena, long iterationId, MemorySegment[] keys) throws RocksDBException {
+ public void seekTo(Arena arena, long iterationId, MemorySegment @NotNull [] keys) throws RocksDBException {
throw new UnsupportedOperationException();
}
@@ -98,7 +99,7 @@ public abstract class SocketConnection extends BaseConnection {
long iterationId,
long skipCount,
long takeCount,
- IteratorCallback super MemorySegment, T> callback) throws RocksDBException {
+ @NotNull IteratorCallback super MemorySegment, T> callback) throws RocksDBException {
throw new UnsupportedOperationException();
}
}
diff --git a/src/main/java/it/cavallium/rockserver/core/client/SocketConnectionUnix.java b/src/main/java/it/cavallium/rockserver/core/client/SocketConnectionUnix.java
index 119777e..9f92c4f 100644
--- a/src/main/java/it/cavallium/rockserver/core/client/SocketConnectionUnix.java
+++ b/src/main/java/it/cavallium/rockserver/core/client/SocketConnectionUnix.java
@@ -1,7 +1,6 @@
package it.cavallium.rockserver.core.client;
import java.io.IOException;
-import java.net.SocketAddress;
import java.net.URI;
import java.net.UnixDomainSocketAddress;
import java.nio.file.Files;
diff --git a/src/main/java/it/cavallium/rockserver/core/common/Callback.java b/src/main/java/it/cavallium/rockserver/core/common/Callback.java
index eabd243..fe5e006 100644
--- a/src/main/java/it/cavallium/rockserver/core/common/Callback.java
+++ b/src/main/java/it/cavallium/rockserver/core/common/Callback.java
@@ -1,9 +1,6 @@
package it.cavallium.rockserver.core.common;
-import java.lang.foreign.MemorySegment;
import java.util.List;
-import java.util.Map.Entry;
-import java.util.concurrent.atomic.AtomicReference;
import org.jetbrains.annotations.Nullable;
public sealed interface Callback {
diff --git a/src/main/java/it/cavallium/rockserver/core/common/ColumnHashType.java b/src/main/java/it/cavallium/rockserver/core/common/ColumnHashType.java
index 9e9fc99..e4923ec 100644
--- a/src/main/java/it/cavallium/rockserver/core/common/ColumnHashType.java
+++ b/src/main/java/it/cavallium/rockserver/core/common/ColumnHashType.java
@@ -11,9 +11,7 @@ public enum ColumnHashType implements HashFunction {
var xxHash = XXHash32.getInstance().hash(Utils.toByteArray(inputData), 0, Math.toIntExact(inputData.byteSize()), 0);
hashResult.set(ColumnInstance.BIG_ENDIAN_BYTES, 0, (byte) xxHash);
}),
- ALLSAME8(Byte.BYTES, (inputData, hashResult) -> {
- hashResult.set(ColumnInstance.BIG_ENDIAN_BYTES, 0, (byte) 0);
- });
+ ALLSAME8(Byte.BYTES, (inputData, hashResult) -> hashResult.set(ColumnInstance.BIG_ENDIAN_BYTES, 0, (byte) 0));
private final int bytes;
private final HashFunction hashFunction;
diff --git a/src/main/java/it/cavallium/rockserver/core/common/ColumnSchema.java b/src/main/java/it/cavallium/rockserver/core/common/ColumnSchema.java
index 5080af0..56e7691 100644
--- a/src/main/java/it/cavallium/rockserver/core/common/ColumnSchema.java
+++ b/src/main/java/it/cavallium/rockserver/core/common/ColumnSchema.java
@@ -4,7 +4,6 @@ import it.cavallium.rockserver.core.common.RocksDBException.RocksDBErrorType;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.objects.ObjectList;
-import java.lang.foreign.MemorySegment;
public record ColumnSchema(IntList keys, ObjectList variableTailKeys, boolean hasValue) {
@@ -44,7 +43,7 @@ public record ColumnSchema(IntList keys, ObjectList variableTail
/**
* Keys with their length
- * @return an array with the length of each key, variable-length keys must have the length of their hash
+ * @return an int list with the length of each key, variable-length keys must have the length of their hash
*/
@Override
public IntList keys() {
diff --git a/src/main/java/it/cavallium/rockserver/core/common/HashFunction.java b/src/main/java/it/cavallium/rockserver/core/common/HashFunction.java
index e389ff0..f7dfe25 100644
--- a/src/main/java/it/cavallium/rockserver/core/common/HashFunction.java
+++ b/src/main/java/it/cavallium/rockserver/core/common/HashFunction.java
@@ -1,6 +1,5 @@
package it.cavallium.rockserver.core.common;
-import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
public interface HashFunction {
diff --git a/src/main/java/it/cavallium/rockserver/core/common/RocksDBAPI.java b/src/main/java/it/cavallium/rockserver/core/common/RocksDBAPI.java
index 2d3bcb6..3e613e4 100644
--- a/src/main/java/it/cavallium/rockserver/core/common/RocksDBAPI.java
+++ b/src/main/java/it/cavallium/rockserver/core/common/RocksDBAPI.java
@@ -5,6 +5,7 @@ import it.cavallium.rockserver.core.common.Callback.IteratorCallback;
import it.cavallium.rockserver.core.common.Callback.PutCallback;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface RocksDBAPI {
@@ -31,7 +32,7 @@ public interface RocksDBAPI {
* @param schema column key-value schema
* @return column id
*/
- long createColumn(String name, ColumnSchema schema) throws RocksDBException;
+ long createColumn(String name, @NotNull ColumnSchema schema) throws RocksDBException;
/**
* Delete a column
@@ -44,7 +45,7 @@ public interface RocksDBAPI {
* @param name column name
* @return column id
*/
- long getColumnId(String name) throws RocksDBException;
+ long getColumnId(@NotNull String name) throws RocksDBException;
/**
* Put an element into the specified position
@@ -58,8 +59,8 @@ public interface RocksDBAPI {
T put(Arena arena,
long transactionId,
long columnId,
- MemorySegment[] keys,
- @Nullable MemorySegment value,
+ @NotNull MemorySegment @NotNull[] keys,
+ @NotNull MemorySegment value,
PutCallback super MemorySegment, T> callback) throws RocksDBException;
/**
@@ -73,7 +74,7 @@ public interface RocksDBAPI {
T get(Arena arena,
long transactionId,
long columnId,
- MemorySegment[] keys,
+ @NotNull MemorySegment @NotNull[] keys,
GetCallback super MemorySegment, T> callback) throws RocksDBException;
/**
@@ -90,8 +91,8 @@ public interface RocksDBAPI {
long openIterator(Arena arena,
long transactionId,
long columnId,
- MemorySegment[] startKeysInclusive,
- @Nullable MemorySegment[] endKeysExclusive,
+ @NotNull MemorySegment @NotNull[] startKeysInclusive,
+ @NotNull MemorySegment @Nullable[] endKeysExclusive,
boolean reverse,
long timeoutMs) throws RocksDBException;
@@ -107,7 +108,7 @@ public interface RocksDBAPI {
* @param iterationId iteration id
* @param keys keys, inclusive. [] means "the beginning"
*/
- void seekTo(Arena arena, long iterationId, MemorySegment[] keys) throws RocksDBException;
+ void seekTo(Arena arena, long iterationId, @NotNull MemorySegment @NotNull[] keys) throws RocksDBException;
/**
* Get the subsequent element during an iteration
@@ -121,5 +122,5 @@ public interface RocksDBAPI {
long iterationId,
long skipCount,
long takeCount,
- IteratorCallback super MemorySegment, T> callback) throws RocksDBException;
+ @NotNull IteratorCallback super MemorySegment, T> callback) throws RocksDBException;
}
diff --git a/src/main/java/it/cavallium/rockserver/core/common/Utils.java b/src/main/java/it/cavallium/rockserver/core/common/Utils.java
index bd273c8..7d3dde1 100644
--- a/src/main/java/it/cavallium/rockserver/core/common/Utils.java
+++ b/src/main/java/it/cavallium/rockserver/core/common/Utils.java
@@ -5,7 +5,9 @@ import static java.lang.foreign.MemorySegment.NULL;
import static java.util.Objects.requireNonNullElse;
import java.io.IOException;
+import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
+import java.lang.foreign.ValueLayout;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -16,9 +18,17 @@ import java.util.function.Function;
import java.util.stream.Stream;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
public class Utils {
+ @SuppressWarnings("resource")
+ private static final MemorySegment DUMMY_EMPTY_VALUE = Arena
+ .global()
+ .allocate(ValueLayout.JAVA_BYTE, (byte) -1)
+ .asReadOnly();
+
+ public static MemorySegment dummyEmptyValue() {
+ return DUMMY_EMPTY_VALUE;
+ }
/**
* Returns the value of the {@code int} argument, throwing an exception if the value overflows an {@code char}.
@@ -61,6 +71,14 @@ public class Utils {
}
}
+ public static MemorySegment toMemorySegment(Arena arena, byte... array) {
+ if (array != null) {
+ return arena.allocateArray(ValueLayout.JAVA_BYTE, array);
+ } else {
+ return MemorySegment.NULL;
+ }
+ }
+
@NotNull
public static MemorySegment toMemorySegmentSimple(int... array) {
if (array != null) {
@@ -74,6 +92,19 @@ public class Utils {
}
}
+ @NotNull
+ public static MemorySegment toMemorySegmentSimple(Arena arena, int... array) {
+ if (array != null) {
+ var newArray = new byte[array.length];
+ for (int i = 0; i < array.length; i++) {
+ newArray[i] = (byte) array[i];
+ }
+ return arena.allocateArray(ValueLayout.JAVA_BYTE, newArray);
+ } else {
+ return MemorySegment.NULL;
+ }
+ }
+
public static byte[] toByteArray(MemorySegment memorySegment) {
return memorySegment.toArray(BIG_ENDIAN_BYTES);
}
diff --git a/src/main/java/it/cavallium/rockserver/core/config/DataSize.java b/src/main/java/it/cavallium/rockserver/core/config/DataSize.java
index 7fb8940..f5353a4 100644
--- a/src/main/java/it/cavallium/rockserver/core/config/DataSize.java
+++ b/src/main/java/it/cavallium/rockserver/core/config/DataSize.java
@@ -88,13 +88,27 @@ public final class DataSize extends Number implements Comparable {
return;
}
// Measurements are like B, MB, or MiB, not longer
+ final var scale = getScale(size, numberEndOffset);
+ this.size = (negative ? -1 : 1) * number * scale;
+ }
+
+ private static int getScale(String size, int numberEndOffset) {
if (size.length() - numberEndOffset > 3) {
throw new IllegalArgumentException("Wrong measurement unit");
}
var scaleChar = size.charAt(numberEndOffset);
boolean powerOf2 = numberEndOffset + 1 < size.length() && size.charAt(numberEndOffset + 1) == 'i';
+ final var scale = getScale(powerOf2, scaleChar);
+ // if scale is 1, the unit should be "B", nothing more
+ if (scale == 1 && numberEndOffset + 1 != size.length()) {
+ throw new IllegalArgumentException("Invalid unit");
+ }
+ return scale;
+ }
+
+ private static int getScale(boolean powerOf2, char scaleChar) {
int k = powerOf2 ? 1024 : 1000;
- var scale = switch (scaleChar) {
+ return switch (scaleChar) {
case 'B' -> 1;
case 'b' -> throw new IllegalArgumentException("Bits are not allowed");
case 'K', 'k' -> k;
@@ -107,11 +121,6 @@ public final class DataSize extends Number implements Comparable {
case 'Y', 'y' -> k * k * k * k * k * k * k * k;
default -> throw new IllegalStateException("Unexpected value: " + scaleChar);
};
- // if scale is 1, the unit should be "B", nothing more
- if (scale == 1 && numberEndOffset + 1 != size.length()) {
- throw new IllegalArgumentException("Invalid unit");
- }
- this.size = (negative ? -1 : 1) * number * scale;
}
public static Long get(DataSize value) {
diff --git a/src/main/java/it/cavallium/rockserver/core/impl/Bucket.java b/src/main/java/it/cavallium/rockserver/core/impl/Bucket.java
index 3e64e33..b590ec7 100644
--- a/src/main/java/it/cavallium/rockserver/core/impl/Bucket.java
+++ b/src/main/java/it/cavallium/rockserver/core/impl/Bucket.java
@@ -7,7 +7,6 @@ import static java.lang.Math.toIntExact;
import it.cavallium.rockserver.core.common.Utils;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
-import java.lang.foreign.ValueLayout;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;
diff --git a/src/main/java/it/cavallium/rockserver/core/impl/ColumnInstance.java b/src/main/java/it/cavallium/rockserver/core/impl/ColumnInstance.java
index 187d2f3..e0b48b3 100644
--- a/src/main/java/it/cavallium/rockserver/core/impl/ColumnInstance.java
+++ b/src/main/java/it/cavallium/rockserver/core/impl/ColumnInstance.java
@@ -1,7 +1,6 @@
package it.cavallium.rockserver.core.impl;
import static it.cavallium.rockserver.core.common.Utils.toCharExact;
-import static java.lang.Math.toIntExact;
import it.cavallium.rockserver.core.common.ColumnSchema;
import it.cavallium.rockserver.core.common.RocksDBException;
@@ -141,7 +140,7 @@ public record ColumnInstance(ColumnFamilyHandle cfh, ColumnSchema schema, int fi
}
public void checkNullableValue(MemorySegment value) {
- if (schema.hasValue() == (value == null)) {
+ if (schema.hasValue() == (value == null || value == MemorySegment.NULL)) {
if (schema.hasValue()) {
throw RocksDBException.of(RocksDBErrorType.UNEXPECTED_NULL_VALUE,
"Schema expects a value, but a null value has been passed");
diff --git a/src/main/java/it/cavallium/rockserver/core/impl/DataSizeDecoder.java b/src/main/java/it/cavallium/rockserver/core/impl/DataSizeDecoder.java
index f4480ef..de3969f 100644
--- a/src/main/java/it/cavallium/rockserver/core/impl/DataSizeDecoder.java
+++ b/src/main/java/it/cavallium/rockserver/core/impl/DataSizeDecoder.java
@@ -4,7 +4,6 @@ import it.cavallium.rockserver.core.config.DataSize;
import java.util.List;
import org.github.gestalt.config.decoder.Decoder;
import org.github.gestalt.config.decoder.DecoderContext;
-import org.github.gestalt.config.decoder.DecoderService;
import org.github.gestalt.config.decoder.Priority;
import org.github.gestalt.config.entity.ValidationError;
import org.github.gestalt.config.node.ConfigNode;
diff --git a/src/main/java/it/cavallium/rockserver/core/impl/DbCompressionDecoder.java b/src/main/java/it/cavallium/rockserver/core/impl/DbCompressionDecoder.java
index a33a611..c603439 100644
--- a/src/main/java/it/cavallium/rockserver/core/impl/DbCompressionDecoder.java
+++ b/src/main/java/it/cavallium/rockserver/core/impl/DbCompressionDecoder.java
@@ -1,11 +1,9 @@
package it.cavallium.rockserver.core.impl;
-import it.cavallium.rockserver.core.config.DataSize;
import it.cavallium.rockserver.core.config.DatabaseCompression;
import java.util.List;
import org.github.gestalt.config.decoder.Decoder;
import org.github.gestalt.config.decoder.DecoderContext;
-import org.github.gestalt.config.decoder.DecoderService;
import org.github.gestalt.config.decoder.Priority;
import org.github.gestalt.config.entity.ValidationError;
import org.github.gestalt.config.node.ConfigNode;
diff --git a/src/main/java/it/cavallium/rockserver/core/impl/EmbeddedDB.java b/src/main/java/it/cavallium/rockserver/core/impl/EmbeddedDB.java
index cfa7b5c..7ca031e 100644
--- a/src/main/java/it/cavallium/rockserver/core/impl/EmbeddedDB.java
+++ b/src/main/java/it/cavallium/rockserver/core/impl/EmbeddedDB.java
@@ -2,8 +2,6 @@ package it.cavallium.rockserver.core.impl;
import static it.cavallium.rockserver.core.common.Utils.toMemorySegment;
import static it.cavallium.rockserver.core.impl.ColumnInstance.BIG_ENDIAN_BYTES;
-import static java.lang.foreign.MemorySegment.NULL;
-import static java.util.Objects.requireNonNullElse;
import static org.rocksdb.KeyMayExist.KeyMayExistEnum.kExistsWithValue;
import static org.rocksdb.KeyMayExist.KeyMayExistEnum.kExistsWithoutValue;
@@ -36,10 +34,10 @@ import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeoutException;
-import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.cliffc.high_scale_lib.NonBlockingHashMapLong;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.rocksdb.ColumnFamilyDescriptor;
import org.rocksdb.ColumnFamilyHandle;
@@ -57,9 +55,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
private static final boolean USE_FAST_GET = true;
private final Logger logger;
private final @Nullable Path path;
- private final @Nullable Path embeddedConfigPath;
- private final DatabaseConfig config;
- private TransactionalDB db;
+ private final TransactionalDB db;
private final NonBlockingHashMapLong columns;
private final ConcurrentMap columnNamesIndex;
private final NonBlockingHashMapLong> txs;
@@ -69,17 +65,16 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
public EmbeddedDB(@Nullable Path path, String name, @Nullable Path embeddedConfigPath) {
this.path = path;
- this.embeddedConfigPath = embeddedConfigPath;
this.logger = Logger.getLogger("db." + name);
this.columns = new NonBlockingHashMapLong<>();
this.txs = new NonBlockingHashMapLong<>();
this.its = new NonBlockingHashMapLong<>();
this.columnNamesIndex = new ConcurrentHashMap<>();
this.ops = new SafeShutdown();
- this.config = ConfigParser.parse(this.embeddedConfigPath);
+ DatabaseConfig config = ConfigParser.parse(embeddedConfigPath);
this.db = RocksDBLoader.load(path, config, logger);
if (Boolean.parseBoolean(System.getProperty("rockserver.core.print-config", "true"))) {
- logger.log(Level.INFO, "Database configuration: {0}", ConfigPrinter.stringify(this.config));
+ logger.log(Level.INFO, "Database configuration: {0}", ConfigPrinter.stringify(config));
}
}
@@ -87,7 +82,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
* The column must be registered once!!!
* Do not try to register a column that may already be registered
*/
- private long registerColumn(ColumnInstance column) {
+ private long registerColumn(@NotNull ColumnInstance column) {
try {
var columnName = new String(column.cfh().getName(), StandardCharsets.UTF_8);
long id = FastRandomUtils.allocateNewValue(this.columns, column, 1, Long.MAX_VALUE);
@@ -182,7 +177,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
}
}
- private boolean closeTransaction(REntry tx, boolean commit) {
+ private boolean closeTransaction(@NotNull REntry tx, boolean commit) {
ops.beginOp();
try {
// Transaction found
@@ -211,7 +206,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
}
}
- private boolean commitTxOptimistically(REntry tx) throws RocksDBException {
+ private boolean commitTxOptimistically(@NotNull REntry tx) throws RocksDBException {
try {
tx.val().commit();
return true;
@@ -225,7 +220,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
}
@Override
- public long createColumn(String name, ColumnSchema schema) throws it.cavallium.rockserver.core.common.RocksDBException {
+ public long createColumn(String name, @NotNull ColumnSchema schema) throws it.cavallium.rockserver.core.common.RocksDBException {
ops.beginOp();
try {
synchronized (columnEditLock) {
@@ -272,7 +267,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
}
@Override
- public long getColumnId(String name) {
+ public long getColumnId(@NotNull String name) {
var columnId = getColumnIdOrNull(name);
if (columnId == null) {
throw it.cavallium.rockserver.core.common.RocksDBException.of(RocksDBErrorType.COLUMN_NOT_FOUND,
@@ -282,7 +277,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
}
}
- private Long getColumnIdOrNull(String name) {
+ private Long getColumnIdOrNull(@NotNull String name) {
var columnId = (long) columnNamesIndex.getOrDefault(name, -1L);
ColumnInstance col;
if (columnId == -1L || (col = columns.get(columnId)) == null || !col.cfh().isOwningHandle()) {
@@ -296,8 +291,8 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
public T put(Arena arena,
long transactionId,
long columnId,
- MemorySegment[] keys,
- @Nullable MemorySegment value,
+ @NotNull MemorySegment @NotNull [] keys,
+ @NotNull MemorySegment value,
PutCallback super MemorySegment, T> callback) throws it.cavallium.rockserver.core.common.RocksDBException {
ops.beginOp();
try {
@@ -320,10 +315,10 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
}
private U put(Arena arena,
- REntry tx,
+ @Nullable REntry tx,
ColumnInstance col,
- MemorySegment[] keys,
- @Nullable MemorySegment value,
+ @NotNull MemorySegment @NotNull[] keys,
+ @NotNull MemorySegment value,
PutCallback super MemorySegment, U> callback) throws it.cavallium.rockserver.core.common.RocksDBException {
// Check for null value
col.checkNullableValue(value);
@@ -335,7 +330,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
var bucketElementKeys = col.getBucketElementKeys(keys);
try (var readOptions = new ReadOptions()) {
var previousRawBucketByteArray = tx.val().getForUpdate(readOptions, col.cfh(), calculatedKey.toArray(BIG_ENDIAN_BYTES), true);
- MemorySegment previousRawBucket = toMemorySegment(previousRawBucketByteArray);
+ MemorySegment previousRawBucket = toMemorySegment(arena, previousRawBucketByteArray);
var bucket = new Bucket(col, previousRawBucket);
previousValue = bucket.addElement(bucketElementKeys, value);
tx.val().put(col.cfh(), Utils.toByteArray(calculatedKey), Utils.toByteArray(bucket.toSegment(arena)));
@@ -364,7 +359,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
} else {
previousValueByteArray = db.get().get(col.cfh(), readOptions, calculatedKey.toArray(BIG_ENDIAN_BYTES));
}
- previousValue = toMemorySegment(previousValueByteArray);
+ previousValue = toMemorySegment(arena, previousValueByteArray);
} catch (RocksDBException e) {
throw it.cavallium.rockserver.core.common.RocksDBException.of(RocksDBErrorType.PUT_2, e);
}
@@ -372,10 +367,12 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
previousValue = null;
}
if (tx != null) {
- tx.val().put(col.cfh(), Utils.toByteArray(calculatedKey), Utils.toByteArray(requireNonNullElse(value, NULL)));
+ tx.val().put(col.cfh(), Utils.toByteArray(calculatedKey), Utils.toByteArray(value));
} else {
try (var w = new WriteOptions()) {
- db.get().put(col.cfh(), w, calculatedKey.asByteBuffer(), requireNonNullElse(value, NULL).asByteBuffer());
+ var keyBB = calculatedKey.asByteBuffer();
+ ByteBuffer valueBB = (col.schema().hasValue() ? value : Utils.dummyEmptyValue()).asByteBuffer();
+ db.get().put(col.cfh(), w, keyBB, valueBB);
}
}
}
@@ -396,7 +393,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
public T get(Arena arena,
long transactionId,
long columnId,
- MemorySegment[] keys,
+ MemorySegment @NotNull [] keys,
GetCallback super MemorySegment, T> callback) throws it.cavallium.rockserver.core.common.RocksDBException {
ops.beginOp();
try {
@@ -465,7 +462,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
public long openIterator(Arena arena,
long transactionId,
long columnId,
- MemorySegment[] startKeysInclusive,
+ MemorySegment @NotNull [] startKeysInclusive,
@Nullable MemorySegment[] endKeysExclusive,
boolean reverse,
long timeoutMs) throws it.cavallium.rockserver.core.common.RocksDBException {
@@ -501,7 +498,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
}
@Override
- public void seekTo(Arena arena, long iterationId, MemorySegment[] keys)
+ public void seekTo(Arena arena, long iterationId, @NotNull MemorySegment @NotNull [] keys)
throws it.cavallium.rockserver.core.common.RocksDBException {
ops.beginOp();
try {
@@ -516,7 +513,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
long iterationId,
long skipCount,
long takeCount,
- IteratorCallback super MemorySegment, T> callback) throws it.cavallium.rockserver.core.common.RocksDBException {
+ @NotNull IteratorCallback super MemorySegment, T> callback) throws it.cavallium.rockserver.core.common.RocksDBException {
ops.beginOp();
try {
throw new UnsupportedOperationException();
@@ -532,14 +529,14 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
MemorySegment calculatedKey) throws RocksDBException {
if (tx != null) {
var previousRawBucketByteArray = tx.val().get(col.cfh(), readOptions, calculatedKey.toArray(BIG_ENDIAN_BYTES));
- return toMemorySegment(previousRawBucketByteArray);
+ return toMemorySegment(arena, previousRawBucketByteArray);
} else {
var db = this.db.get();
if (USE_FAST_GET) {
return dbGetDirect(arena, col.cfh(), readOptions, calculatedKey);
} else {
var previousRawBucketByteArray = db.get(col.cfh(), readOptions, calculatedKey.toArray(BIG_ENDIAN_BYTES));
- return toMemorySegment(previousRawBucketByteArray);
+ return toMemorySegment(arena, previousRawBucketByteArray);
}
}
}
@@ -557,12 +554,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
case kNotExist -> null;
case kExistsWithValue, kExistsWithoutValue -> {
// At the beginning, size reflects the expected size, then it becomes the real data size
- int size;
- if (keyMayExist.exists == kExistsWithValue) {
- size = keyMayExist.valueLength;
- } else {
- size = -1;
- }
+ int size = keyMayExist.exists == kExistsWithValue ? keyMayExist.valueLength : -1;
if (keyMayExist.exists == kExistsWithoutValue || size > resultBuffer.limit()) {
if (size > resultBuffer.capacity()) {
resultBuffer = arena.allocate(size).asByteBuffer();
@@ -600,7 +592,7 @@ public class EmbeddedDB implements RocksDBAPI, Closeable {
}
}
- public Path getPath() {
+ public @Nullable Path getPath() {
return path;
}
diff --git a/src/main/java/it/cavallium/rockserver/core/impl/XXHash32.java b/src/main/java/it/cavallium/rockserver/core/impl/XXHash32.java
index 5e0c008..363f45b 100644
--- a/src/main/java/it/cavallium/rockserver/core/impl/XXHash32.java
+++ b/src/main/java/it/cavallium/rockserver/core/impl/XXHash32.java
@@ -14,7 +14,6 @@ package it.cavallium.rockserver.core.impl;
* limitations under the License.
*/
-import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
/**
diff --git a/src/main/java/it/cavallium/rockserver/core/impl/rocksdb/REntry.java b/src/main/java/it/cavallium/rockserver/core/impl/rocksdb/REntry.java
index e3d1190..eb62771 100644
--- a/src/main/java/it/cavallium/rockserver/core/impl/rocksdb/REntry.java
+++ b/src/main/java/it/cavallium/rockserver/core/impl/rocksdb/REntry.java
@@ -2,7 +2,6 @@ package it.cavallium.rockserver.core.impl.rocksdb;
import java.io.Closeable;
import org.rocksdb.AbstractNativeReference;
-import org.rocksdb.Status.Code;
public record REntry(T val, RocksDBObjects objs) implements Closeable {
diff --git a/src/main/java/it/cavallium/rockserver/core/impl/rocksdb/RocksDBLoader.java b/src/main/java/it/cavallium/rockserver/core/impl/rocksdb/RocksDBLoader.java
index 5524e5a..daa68fb 100644
--- a/src/main/java/it/cavallium/rockserver/core/impl/rocksdb/RocksDBLoader.java
+++ b/src/main/java/it/cavallium/rockserver/core/impl/rocksdb/RocksDBLoader.java
@@ -6,7 +6,6 @@ import org.github.gestalt.config.exceptions.GestaltException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.rocksdb.*;
-import org.rocksdb.util.Environment;
import org.rocksdb.util.SizeUnit;
import java.io.IOException;
@@ -141,7 +140,6 @@ public class RocksDBLoader {
.orElse(0L);
if (isDisableAutoCompactions()) {
- options.setMaxBackgroundCompactions(0);
options.setMaxBackgroundJobs(0);
} else {
var backgroundJobs = Integer.parseInt(System.getProperty("it.cavallium.dbengine.jobs.background.num", "-1"));
@@ -371,7 +369,7 @@ public class RocksDBLoader {
columnFamilyOptions.setBottommostCompressionOptions(lastLevelOptions.compressionOptions);
List compressionPerLevel = new ArrayList<>();
- for (ColumnLevelConfig columnLevelConfig : List.of(columnOptions.levels())) {
+ for (ColumnLevelConfig columnLevelConfig : columnOptions.levels()) {
CompressionType compression = columnLevelConfig.compression();
compressionPerLevel.add(compression);
}
@@ -532,9 +530,7 @@ public class RocksDBLoader {
logger.log(Level.FINE, "Failed to obtain stats", ex);
}
return TransactionalDB.create(definitiveDbPath.toString(), db);
- } catch (IOException ex) {
- throw it.cavallium.rockserver.core.common.RocksDBException.of(it.cavallium.rockserver.core.common.RocksDBException.RocksDBErrorType.ROCKSDB_LOAD_ERROR, "Failed to load rocksdb", ex);
- } catch (RocksDBException ex) {
+ } catch (IOException | RocksDBException ex) {
throw it.cavallium.rockserver.core.common.RocksDBException.of(it.cavallium.rockserver.core.common.RocksDBException.RocksDBErrorType.ROCKSDB_LOAD_ERROR, "Failed to load rocksdb", ex);
} catch (GestaltException e) {
throw it.cavallium.rockserver.core.common.RocksDBException.of(it.cavallium.rockserver.core.common.RocksDBException.RocksDBErrorType.CONFIG_ERROR, "Failed to load rocksdb", e);
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index ee9bf6b..457dc21 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -3,7 +3,6 @@ module rockserver.core {
requires net.sourceforge.argparse4j;
requires inet.ipaddr;
requires java.logging;
- requires typesafe.config;
requires org.jetbrains.annotations;
requires high.scale.lib;
requires org.github.gestalt.core;
diff --git a/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBFixedAndVarKeysWithValueTest.java b/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBFixedAndVarKeysWithValueTest.java
new file mode 100644
index 0000000..f58add9
--- /dev/null
+++ b/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBFixedAndVarKeysWithValueTest.java
@@ -0,0 +1,5 @@
+package it.cavallium.rockserver.core.impl.test;
+
+public class EmbeddedDBFixedAndVarKeysWithValueTest extends EmbeddedDBTest {
+
+}
diff --git a/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBFixedAndVarKeysWithoutValueTest.java b/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBFixedAndVarKeysWithoutValueTest.java
new file mode 100644
index 0000000..088ee8b
--- /dev/null
+++ b/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBFixedAndVarKeysWithoutValueTest.java
@@ -0,0 +1,31 @@
+package it.cavallium.rockserver.core.impl.test;
+
+import java.lang.foreign.MemorySegment;
+
+public class EmbeddedDBFixedAndVarKeysWithoutValueTest extends EmbeddedDBTest {
+
+ @Override
+ protected MemorySegment getValue1() {
+ return MemorySegment.NULL;
+ }
+
+ @Override
+ protected MemorySegment getValue2() {
+ return MemorySegment.NULL;
+ }
+
+ @Override
+ protected MemorySegment getValueI(int i) {
+ return MemorySegment.NULL;
+ }
+
+ @Override
+ protected boolean getHasValues() {
+ return false;
+ }
+
+ @Override
+ protected MemorySegment getBigValue() {
+ return MemorySegment.NULL;
+ }
+}
diff --git a/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBFixedWithValueTest.java b/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBFixedWithValueTest.java
new file mode 100644
index 0000000..e6ab89b
--- /dev/null
+++ b/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBFixedWithValueTest.java
@@ -0,0 +1,61 @@
+package it.cavallium.rockserver.core.impl.test;
+
+import static it.cavallium.rockserver.core.common.Utils.toMemorySegmentSimple;
+
+import it.cavallium.rockserver.core.common.ColumnHashType;
+import it.unimi.dsi.fastutil.objects.ObjectList;
+import java.lang.foreign.MemorySegment;
+
+public class EmbeddedDBFixedWithValueTest extends EmbeddedDBTest {
+
+ @Override
+ protected MemorySegment[] getKeyI(int i) {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 4, 7),
+ toMemorySegmentSimple(arena, i)
+ };
+ }
+
+ @Override
+ protected MemorySegment[] getNotFoundKeyI(int i) {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 5, 6),
+ toMemorySegmentSimple(arena, i)
+ };
+ }
+
+ @Override
+ protected MemorySegment[] getKey1() {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 4, 6),
+ toMemorySegmentSimple(arena, 3)
+ };
+ }
+
+ @Override
+ protected MemorySegment[] getKey2() {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 4, 6),
+ toMemorySegmentSimple(arena, 4)
+ };
+ }
+
+ @Override
+ protected MemorySegment[] getCollidingKey1() {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 4, 6),
+ toMemorySegmentSimple(arena, 5)
+ };
+ }
+
+ @Override
+ protected ObjectList getSchemaVarKeys() {
+ return ObjectList.of();
+ }
+
+}
diff --git a/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBFixedWithoutValueTest.java b/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBFixedWithoutValueTest.java
new file mode 100644
index 0000000..f36c195
--- /dev/null
+++ b/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBFixedWithoutValueTest.java
@@ -0,0 +1,85 @@
+package it.cavallium.rockserver.core.impl.test;
+
+import static it.cavallium.rockserver.core.common.Utils.toMemorySegmentSimple;
+
+import it.cavallium.rockserver.core.common.ColumnHashType;
+import it.unimi.dsi.fastutil.objects.ObjectList;
+import java.lang.foreign.MemorySegment;
+
+public class EmbeddedDBFixedWithoutValueTest extends EmbeddedDBTest {
+
+ @Override
+ protected boolean getHasValues() {
+ return false;
+ }
+
+ @Override
+ protected MemorySegment[] getKeyI(int i) {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 4, 7),
+ toMemorySegmentSimple(arena, i)
+ };
+ }
+
+ @Override
+ protected MemorySegment[] getNotFoundKeyI(int i) {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 5, 6),
+ toMemorySegmentSimple(arena, i)
+ };
+ }
+
+ @Override
+ protected MemorySegment[] getKey1() {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 4, 6),
+ toMemorySegmentSimple(arena, 3)
+ };
+ }
+
+ @Override
+ protected MemorySegment[] getKey2() {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 4, 6),
+ toMemorySegmentSimple(arena, 4)
+ };
+ }
+
+ @Override
+ protected MemorySegment[] getCollidingKey1() {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 4, 6),
+ toMemorySegmentSimple(arena, 5)
+ };
+ }
+
+ @Override
+ protected ObjectList getSchemaVarKeys() {
+ return ObjectList.of();
+ }
+
+ @Override
+ protected MemorySegment getValue1() {
+ return MemorySegment.NULL;
+ }
+
+ @Override
+ protected MemorySegment getValue2() {
+ return MemorySegment.NULL;
+ }
+
+ @Override
+ protected MemorySegment getValueI(int i) {
+ return MemorySegment.NULL;
+ }
+
+ @Override
+ protected MemorySegment getBigValue() {
+ return MemorySegment.NULL;
+ }
+}
diff --git a/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBTest.java b/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBTest.java
index b7ff879..9fd1f49 100644
--- a/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBTest.java
+++ b/src/test/java/it/cavallium/rockserver/core/impl/test/EmbeddedDBTest.java
@@ -6,6 +6,7 @@ import it.cavallium.rockserver.core.client.EmbeddedConnection;
import it.cavallium.rockserver.core.common.Callback;
import it.cavallium.rockserver.core.common.ColumnHashType;
import it.cavallium.rockserver.core.common.ColumnSchema;
+import it.cavallium.rockserver.core.common.Delta;
import it.cavallium.rockserver.core.common.Utils;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.objects.ObjectList;
@@ -15,18 +16,19 @@ import org.junit.jupiter.api.Assertions;
import java.io.IOException;
import java.lang.foreign.MemorySegment;
+import org.junit.jupiter.api.Test;
-class EmbeddedDBTest {
+abstract class EmbeddedDBTest {
- private EmbeddedConnection db;
- private long colId = 0L;
- private Arena arena;
- private MemorySegment bigValue;
- private MemorySegment[] key1;
- private MemorySegment[] collidingKey1;
- private MemorySegment[] key2;
- private MemorySegment value1;
- private MemorySegment value2;
+ protected EmbeddedConnection db;
+ protected long colId = 0L;
+ protected Arena arena;
+ protected MemorySegment bigValue;
+ protected MemorySegment[] key1;
+ protected MemorySegment[] collidingKey1;
+ protected MemorySegment[] key2;
+ protected MemorySegment value1;
+ protected MemorySegment value2;
@org.junit.jupiter.api.BeforeEach
void setUp() throws IOException {
@@ -37,41 +39,65 @@ class EmbeddedDBTest {
db = new EmbeddedConnection(null, "test", null);
createStandardColumn();
+ bigValue = getBigValue();
+ key1 = getKey1();
+ collidingKey1 = getCollidingKey1();
+ key2 = getKey2();
+ value1 = getValue1();
+ value2 = getValue2();
+ }
+
+ protected MemorySegment getBigValue() {
var bigValueArray = new byte[10_000];
ThreadLocalRandom.current().nextBytes(bigValueArray);
- bigValue = MemorySegment.ofArray(bigValueArray);
- key1 = new MemorySegment[] {
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(4, 6),
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(1, 2, 3),
- toMemorySegmentSimple(6, 7, 8)
- };
- collidingKey1 = new MemorySegment[] {
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(4, 6),
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(1, 2, 3),
- toMemorySegmentSimple(6, 7, -48)
- };
- key2 = new MemorySegment[] {
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(4, 6),
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(1, 2, 3),
- toMemorySegmentSimple(6, 7, 7)
- };
+ return Utils.toMemorySegment(arena, bigValueArray);
+ }
- value1 = MemorySegment.ofArray(new byte[] {0, 0, 3});
- value2 = MemorySegment.ofArray(new byte[] {0, 0, 5});
+ protected MemorySegment[] getKey2() {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 4, 6),
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 1, 2, 3),
+ toMemorySegmentSimple(arena, 6, 7, 7)
+ };
+ }
+
+ protected MemorySegment[] getCollidingKey1() {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 4, 6),
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 1, 2, 3),
+ toMemorySegmentSimple(arena, 6, 7, -48)
+ };
+ }
+
+ protected MemorySegment[] getKey1() {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 4, 6),
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 1, 2, 3),
+ toMemorySegmentSimple(arena, 6, 7, 8)
+ };
+ }
+
+ protected boolean getHasValues() {
+ return true;
+ }
+
+ protected MemorySegment getValue1() {
+ return Utils.toMemorySegmentSimple(arena, 0, 0, 3);
+ }
+
+ protected MemorySegment getValue2() {
+ return Utils.toMemorySegmentSimple(arena, 0, 0, 5);
}
private void createStandardColumn() {
- createColumn(ColumnSchema.of(IntList.of(1, 2, 1),
- ObjectList.of(ColumnHashType.XXHASH32, ColumnHashType.XXHASH32),
- true
- ));
+ createColumn(getSchema());
}
private void createColumn(ColumnSchema schema) {
@@ -86,18 +112,36 @@ class EmbeddedDBTest {
Assertions.assertNull(db.put(arena, 0, colId, collidingKey1, value2, Callback.none()));
Assertions.assertNull(db.put(arena, 0, colId, key2, bigValue, Callback.none()));
for (int i = 0; i < Byte.MAX_VALUE; i++) {
- var keyI = new MemorySegment[] {
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(4, 6),
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(1, 2, 3),
- toMemorySegmentSimple(8, 2, 5, 1, 7, i)
- };
- var valueI = toMemorySegmentSimple(i, i, i, i, i);
+ var keyI = getKeyI(i);
+ var valueI = getValueI(i);
Assertions.assertNull(db.put(arena, 0, colId, keyI, valueI, Callback.none()));
}
}
+ protected MemorySegment[] getKeyI(int i) {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 4, 6),
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 1, 2, 3),
+ toMemorySegmentSimple(arena, 8, 2, 5, 1, 7, i)
+ };
+ }
+
+ protected MemorySegment[] getNotFoundKeyI(int i) {
+ return new MemorySegment[] {
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 4, 6),
+ toMemorySegmentSimple(arena, 3),
+ toMemorySegmentSimple(arena, 1, 2, 3),
+ toMemorySegmentSimple(arena, 8, 2, 5, 1, 0, i)
+ };
+ }
+
+ protected MemorySegment getValueI(int i) {
+ return toMemorySegmentSimple(arena, i, i, i, i, i);
+ }
+
@org.junit.jupiter.api.AfterEach
void tearDown() throws IOException {
db.deleteColumn(colId);
@@ -105,19 +149,32 @@ class EmbeddedDBTest {
arena.close();
}
- @org.junit.jupiter.api.Test
- void putSameBucketSameKey() {
- var key = new MemorySegment[] {
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(4, 6),
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(1, 2, 3),
- toMemorySegmentSimple(0, 0, 3, 6, 7, 8)
- };
- var value1 = MemorySegment.ofArray(new byte[] {0, 0, 3});
- var value2 = MemorySegment.ofArray(new byte[] {0, 0, 5});
+ @SuppressWarnings("DataFlowIssue")
+ @Test
+ void putTestErrors() {
+ var key = getKey1();
- var delta = db.put(arena, 0, colId, key, value1, Callback.delta());
+ if (!getHasValues()) {
+ Assertions.assertThrows(Exception.class, () -> db.put(arena, 0, colId, key, toMemorySegmentSimple(arena, 123), Callback.delta()));
+ }
+
+ Assertions.assertThrows(Exception.class, () -> db.put(arena, 0, colId, key, null, Callback.delta()));
+ Assertions.assertThrows(Exception.class, () -> db.put(arena, 0, colId, null, value1, Callback.delta()));
+ Assertions.assertThrows(Exception.class, () -> db.put(arena, 0, colId, null, null, Callback.delta()));
+ Assertions.assertThrows(Exception.class, () -> db.put(arena, 0, colId, key, value1, null));
+ Assertions.assertThrows(Exception.class, () -> db.put(arena, 1, colId, key, value1, Callback.delta()));
+ Assertions.assertThrows(Exception.class, () -> db.put(arena, 0, 21203, key, value1, Callback.delta()));
+ }
+
+ @Test
+ void putSameBucketSameKey() {
+ var key = getKey1();
+ var value1 = getValue1();
+ var value2 = getValue2();
+
+ Delta delta;
+
+ delta = db.put(arena, 0, colId, key, value1, Callback.delta());
Assertions.assertNull(delta.previous());
Assertions.assertTrue(Utils.valueEquals(delta.current(), value1));
@@ -126,32 +183,22 @@ class EmbeddedDBTest {
Assertions.assertTrue(Utils.valueEquals(delta.current(), value2));
}
- @org.junit.jupiter.api.Test
+ @Test
void putSameBucketDifferentKey() {
- createColumn(ColumnSchema.of(IntList.of(1, 2, 1), ObjectList.of(ColumnHashType.XXHASH32, ColumnHashType.ALLSAME8), true));
+ if (getSchemaVarKeys().isEmpty()) {
+ return;
+ }
+ createColumn(ColumnSchema.of(getSchemaFixedKeys(), ObjectList.of(ColumnHashType.XXHASH32, ColumnHashType.ALLSAME8), getHasValues()));
- var lastKey1 = toMemorySegmentSimple(6, 7, 8);
- var lastKey2 = toMemorySegmentSimple(6, 7, -48);
+ var key1 = getKey1();
+ var key2 = getCollidingKey1();
- var key1 = new MemorySegment[] {
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(4, 6),
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(1, 2, 3),
- lastKey1
- };
- var key2 = new MemorySegment[] {
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(4, 6),
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(1, 2, 3),
- lastKey2
- };
+ var value1 = getValue1();
+ var value2 = getValue2();
- var value1 = MemorySegment.ofArray(new byte[] {0, 0, 3});
- var value2 = MemorySegment.ofArray(new byte[] {0, 0, 5});
+ Delta delta;
- var delta = db.put(arena, 0, colId, key1, value1, Callback.delta());
+ delta = db.put(arena, 0, colId, key1, value1, Callback.delta());
Assertions.assertNull(delta.previous());
Assertions.assertTrue(Utils.valueEquals(delta.current(), value1));
@@ -164,41 +211,29 @@ class EmbeddedDBTest {
Assertions.assertTrue(Utils.valueEquals(delta.current(), value1));
}
+ protected ColumnSchema getSchema() {
+ return ColumnSchema.of(getSchemaFixedKeys(), getSchemaVarKeys(), getHasValues());
+ }
+
+ protected IntList getSchemaFixedKeys() {
+ return IntList.of(1, 2, 1);
+ }
+
+ protected ObjectList getSchemaVarKeys() {
+ return ObjectList.of(ColumnHashType.XXHASH32, ColumnHashType.XXHASH8);
+ }
+
/**
* Some keys have same bucket, some not
*/
- @org.junit.jupiter.api.Test
+ @Test
void putMixedBucketMixedKey() {
- createColumn(ColumnSchema.of(IntList.of(1, 2, 1), ObjectList.of(ColumnHashType.XXHASH32, ColumnHashType.XXHASH8), true));
+ var key1 = getKey1();
+ var collidingKey1 = getCollidingKey1();
+ var key2 = getKey2();
- var lastKey1 = toMemorySegmentSimple(6, 7, 8);
- var collidingLastKey1 = toMemorySegmentSimple(6, 7, -48);
- var lastKey2 = toMemorySegmentSimple(6, 7, 7);
-
- var key1 = new MemorySegment[] {
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(4, 6),
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(1, 2, 3),
- lastKey1
- };
- var collidingKey1 = new MemorySegment[] {
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(4, 6),
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(1, 2, 3),
- collidingLastKey1
- };
- var key2 = new MemorySegment[] {
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(4, 6),
- toMemorySegmentSimple(3),
- toMemorySegmentSimple(1, 2, 3),
- lastKey2
- };
-
- var value1 = MemorySegment.ofArray(new byte[] {0, 0, 3});
- var value2 = MemorySegment.ofArray(new byte[] {0, 0, 5});
+ var value1 = getValue1();
+ var value2 = getValue2();
var delta = db.put(arena, 0, colId, key1, value1, Callback.delta());
Assertions.assertNull(delta.previous());
@@ -221,11 +256,25 @@ class EmbeddedDBTest {
Assertions.assertTrue(Utils.valueEquals(delta.current(), value2));
}
- @org.junit.jupiter.api.Test
+ @Test
void get() {
+ Assertions.assertNull(db.get(arena, 0, colId, key1, Callback.current()));
+ Assertions.assertNull(db.get(arena, 0, colId, collidingKey1, Callback.current()));
+ Assertions.assertNull(db.get(arena, 0, colId, key2, Callback.current()));
fillSomeKeys();
Assertions.assertTrue(Utils.valueEquals(value1, db.get(arena, 0, colId, key1, Callback.current())));
+ Assertions.assertNull(db.get(arena, 0, colId, getNotFoundKeyI(0), Callback.current()));
Assertions.assertTrue(Utils.valueEquals(value2, db.get(arena, 0, colId, collidingKey1, Callback.current())));
Assertions.assertTrue(Utils.valueEquals(bigValue, db.get(arena, 0, colId, key2, Callback.current())));
}
+
+ @SuppressWarnings("DataFlowIssue")
+ @Test
+ void getTestError() {
+ fillSomeKeys();
+ Assertions.assertThrows(Exception.class, () -> Utils.valueEquals(value1, db.get(arena, 0, colId, null, Callback.current())));
+ Assertions.assertThrows(Exception.class, () -> Utils.valueEquals(value1, db.get(arena, 0, 18239, key1, Callback.current())));
+ Assertions.assertThrows(Exception.class, () -> Utils.valueEquals(value1, db.get(arena, 1, colId, key1, Callback.current())));
+ Assertions.assertThrows(Exception.class, () -> Utils.valueEquals(value1, db.get(arena, 0, colId, key1, null)));
+ }
}
\ No newline at end of file
diff --git a/src/test/java/it/cavallium/rockserver/core/test/XXHash32Test.java b/src/test/java/it/cavallium/rockserver/core/test/XXHash32Test.java
index fdb5e8e..4cdae91 100644
--- a/src/test/java/it/cavallium/rockserver/core/test/XXHash32Test.java
+++ b/src/test/java/it/cavallium/rockserver/core/test/XXHash32Test.java
@@ -3,9 +3,7 @@ package it.cavallium.rockserver.core.test;
import it.cavallium.rockserver.core.impl.ColumnInstance;
import it.cavallium.rockserver.core.impl.XXHash32;
import java.lang.foreign.Arena;
-import java.lang.foreign.ValueLayout;
import java.lang.foreign.ValueLayout.OfByte;
-import java.nio.ByteOrder;
import java.util.concurrent.ThreadLocalRandom;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;