From c4a2fb1c257859128c55b5d8a93a881c54a29182 Mon Sep 17 00:00:00 2001 From: Alex Gaetano Padula Date: Sat, 7 Mar 2026 00:01:45 -0500 Subject: [PATCH] issue #25 extend java library to match c library db.h functionality availability --- pom.xml | 2 +- src/main/c/com_tidesdb_TidesDB.c | 4 +- src/main/java/com/tidesdb/Config.java | 13 ++++ src/main/java/com/tidesdb/TidesDB.java | 6 +- src/test/java/com/tidesdb/TidesDBTest.java | 72 ++++++++++++++++++++++ 5 files changed, 93 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 39307c1..7418f11 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.tidesdb tidesdb-java - 0.6.4 + 0.6.5 jar TidesDB Java diff --git a/src/main/c/com_tidesdb_TidesDB.c b/src/main/c/com_tidesdb_TidesDB.c index 70af321..87a3c89 100644 --- a/src/main/c/com_tidesdb_TidesDB.c +++ b/src/main/c/com_tidesdb_TidesDB.c @@ -78,7 +78,8 @@ JNIEXPORT jlong JNICALL Java_com_tidesdb_TidesDB_nativeOpen(JNIEnv *env, jclass jint numCompactionThreads, jint logLevel, jlong blockCacheSize, jlong maxOpenSSTables, jboolean logToFile, - jlong logTruncationAt) + jlong logTruncationAt, + jlong maxMemoryUsage) { const char *path = (*env)->GetStringUTFChars(env, dbPath, NULL); if (path == NULL) @@ -93,6 +94,7 @@ JNIEXPORT jlong JNICALL Java_com_tidesdb_TidesDB_nativeOpen(JNIEnv *env, jclass .log_level = (tidesdb_log_level_t)logLevel, .block_cache_size = (size_t)blockCacheSize, .max_open_sstables = (size_t)maxOpenSSTables, + .max_memory_usage = (size_t)maxMemoryUsage, .log_to_file = logToFile ? 1 : 0, .log_truncation_at = (size_t)logTruncationAt}; diff --git a/src/main/java/com/tidesdb/Config.java b/src/main/java/com/tidesdb/Config.java index c686f8d..7fd5c50 100644 --- a/src/main/java/com/tidesdb/Config.java +++ b/src/main/java/com/tidesdb/Config.java @@ -31,6 +31,7 @@ public class Config { private long maxOpenSSTables; private boolean logToFile; private long logTruncationAt; + private long maxMemoryUsage; private Config(Builder builder) { this.dbPath = builder.dbPath; @@ -41,6 +42,7 @@ private Config(Builder builder) { this.maxOpenSSTables = builder.maxOpenSSTables; this.logToFile = builder.logToFile; this.logTruncationAt = builder.logTruncationAt; + this.maxMemoryUsage = builder.maxMemoryUsage; } /** @@ -57,6 +59,7 @@ public static Config defaultConfig() { .maxOpenSSTables(256) .logToFile(false) .logTruncationAt(24 * 1024 * 1024) + .maxMemoryUsage(0) .build(); } @@ -102,6 +105,10 @@ public long getLogTruncationAt() { return logTruncationAt; } + public long getMaxMemoryUsage() { + return maxMemoryUsage; + } + /** * Builder for Config. */ @@ -114,6 +121,7 @@ public static class Builder { private long maxOpenSSTables = 256; private boolean logToFile = false; private long logTruncationAt = 24 * 1024 * 1024; + private long maxMemoryUsage = 0; public Builder dbPath(String dbPath) { this.dbPath = dbPath; @@ -155,6 +163,11 @@ public Builder logTruncationAt(long logTruncationAt) { return this; } + public Builder maxMemoryUsage(long maxMemoryUsage) { + this.maxMemoryUsage = maxMemoryUsage; + return this; + } + public Config build() { validate(); return new Config(this); diff --git a/src/main/java/com/tidesdb/TidesDB.java b/src/main/java/com/tidesdb/TidesDB.java index 5c0b7ed..c112a49 100644 --- a/src/main/java/com/tidesdb/TidesDB.java +++ b/src/main/java/com/tidesdb/TidesDB.java @@ -60,7 +60,8 @@ public static TidesDB open(Config config) throws TidesDBException { config.getBlockCacheSize(), config.getMaxOpenSSTables(), config.isLogToFile(), - config.getLogTruncationAt() + config.getLogTruncationAt(), + config.getMaxMemoryUsage() ); return new TidesDB(handle); @@ -294,7 +295,8 @@ long getNativeHandle() { private static native long nativeOpen(String dbPath, int numFlushThreads, int numCompactionThreads, int logLevel, long blockCacheSize, long maxOpenSSTables, - boolean logToFile, long logTruncationAt) throws TidesDBException; + boolean logToFile, long logTruncationAt, + long maxMemoryUsage) throws TidesDBException; private static native void nativeClose(long handle); diff --git a/src/test/java/com/tidesdb/TidesDBTest.java b/src/test/java/com/tidesdb/TidesDBTest.java index d7494ba..3715eec 100644 --- a/src/test/java/com/tidesdb/TidesDBTest.java +++ b/src/test/java/com/tidesdb/TidesDBTest.java @@ -1064,6 +1064,78 @@ void testCommitHookNullThrows() throws TidesDBException { } } + @Test + @Order(29) + void testMaxMemoryUsageConfig() throws TidesDBException { + Config config = Config.builder(tempDir.resolve("testdb27").toString()) + .numFlushThreads(2) + .numCompactionThreads(2) + .logLevel(LogLevel.INFO) + .blockCacheSize(64 * 1024 * 1024) + .maxOpenSSTables(256) + .maxMemoryUsage(0) + .build(); + + assertEquals(0, config.getMaxMemoryUsage()); + + try (TidesDB db = TidesDB.open(config)) { + ColumnFamilyConfig cfConfig = ColumnFamilyConfig.defaultConfig(); + db.createColumnFamily("test_cf", cfConfig); + + ColumnFamily cf = db.getColumnFamily("test_cf"); + + try (Transaction txn = db.beginTransaction()) { + txn.put(cf, "key1".getBytes(), "value1".getBytes()); + txn.commit(); + } + + try (Transaction txn = db.beginTransaction()) { + byte[] result = txn.get(cf, "key1".getBytes()); + assertNotNull(result); + assertArrayEquals("value1".getBytes(), result); + } + } + } + + @Test + @Order(30) + void testMultiColumnFamilyTransaction() throws TidesDBException { + Config config = Config.builder(tempDir.resolve("testdb28").toString()) + .numFlushThreads(2) + .numCompactionThreads(2) + .logLevel(LogLevel.INFO) + .blockCacheSize(64 * 1024 * 1024) + .maxOpenSSTables(256) + .build(); + + try (TidesDB db = TidesDB.open(config)) { + ColumnFamilyConfig cfConfig = ColumnFamilyConfig.defaultConfig(); + db.createColumnFamily("users", cfConfig); + db.createColumnFamily("orders", cfConfig); + + ColumnFamily usersCf = db.getColumnFamily("users"); + ColumnFamily ordersCf = db.getColumnFamily("orders"); + + // Atomic transaction across multiple column families + try (Transaction txn = db.beginTransaction()) { + txn.put(usersCf, "user:1000".getBytes(), "John Doe".getBytes()); + txn.put(ordersCf, "order:5000".getBytes(), "user:1000|product:A".getBytes()); + txn.commit(); + } + + // Verify data in both column families + try (Transaction txn = db.beginTransaction()) { + byte[] user = txn.get(usersCf, "user:1000".getBytes()); + assertNotNull(user); + assertArrayEquals("John Doe".getBytes(), user); + + byte[] order = txn.get(ordersCf, "order:5000".getBytes()); + assertNotNull(order); + assertArrayEquals("user:1000|product:A".getBytes(), order); + } + } + } + @Test @Order(21) void testTransactionResetNullIsolation() throws TidesDBException {