From 2aa875c0bf6af58e96ea457e441f01bc3cf5dc3e Mon Sep 17 00:00:00 2001 From: Alex Gaetano Padula Date: Sun, 21 Jun 2026 22:47:47 -0400 Subject: [PATCH] extend stats and error codes --- pom.xml | 2 +- src/main/c/com_tidesdb_TidesDB.c | 8 +++++-- src/main/java/com/tidesdb/DbStats.java | 28 ++++++++++++++++++++++ src/test/java/com/tidesdb/TidesDBTest.java | 6 +++++ 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index bfffdbd..1ca85b2 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.tidesdb tidesdb-java - 0.8.2 + 0.8.3 jar TidesDB Java diff --git a/src/main/c/com_tidesdb_TidesDB.c b/src/main/c/com_tidesdb_TidesDB.c index e0f5f72..7418337 100644 --- a/src/main/c/com_tidesdb_TidesDB.c +++ b/src/main/c/com_tidesdb_TidesDB.c @@ -1423,10 +1423,12 @@ JNIEXPORT jobject JNICALL Java_com_tidesdb_TidesDB_nativeGetDbStats(JNIEnv *env, /* Constructor signature: int, long, long, long, int, int, long, int, int, long, int, long, long, long, long, boolean, long, int, boolean, int, long, - boolean, String, long, long, int, long, long, long, long, boolean */ + boolean, String, long, long, int, long, long, long, long, boolean, + long (primaryEpoch), long (seenEpoch), + long, long, long, long, long, long, long, long */ jmethodID constructor = (*env)->GetMethodID( env, dbStatsClass, "", - "(IJJJIIJIIJIJJJJZJIZIJZLjava/lang/String;JJIJJJJZJJJJJJJJ)V"); + "(IJJJIIJIIJIJJJJZJIZIJZLjava/lang/String;JJIJJJJZJJJJJJJJJJ)V"); jstring connectorStr = NULL; if (db_stats.object_store_connector != NULL) @@ -1466,6 +1468,8 @@ JNIEXPORT jobject JNICALL Java_com_tidesdb_TidesDB_nativeGetDbStats(JNIEnv *env, (jlong)db_stats.total_uploads, (jlong)db_stats.total_upload_failures, db_stats.replica_mode != 0, + (jlong)db_stats.primary_epoch, + (jlong)db_stats.seen_epoch, (jlong)db_stats.uwal_bytes_written, (jlong)db_stats.wal_bytes_written, (jlong)db_stats.flush_bytes_written, diff --git a/src/main/java/com/tidesdb/DbStats.java b/src/main/java/com/tidesdb/DbStats.java index 83d8718..98a280d 100644 --- a/src/main/java/com/tidesdb/DbStats.java +++ b/src/main/java/com/tidesdb/DbStats.java @@ -54,6 +54,8 @@ public class DbStats { private final long totalUploads; private final long totalUploadFailures; private final boolean replicaMode; + private final long primaryEpoch; + private final long seenEpoch; private final long uwalBytesWritten; private final long walBytesWritten; private final long flushBytesWritten; @@ -75,6 +77,7 @@ public DbStats(int numColumnFamilies, long totalMemory, long availableMemory, long localCacheBytesUsed, long localCacheBytesMax, int localCacheNumFiles, long lastUploadedGeneration, long uploadQueueDepth, long totalUploads, long totalUploadFailures, boolean replicaMode, + long primaryEpoch, long seenEpoch, long uwalBytesWritten, long walBytesWritten, long flushBytesWritten, long compactionBytesWritten, long compactionBytesRead, long userBytesWritten, long flushCount, long compactionCount) { @@ -109,6 +112,8 @@ public DbStats(int numColumnFamilies, long totalMemory, long availableMemory, this.totalUploads = totalUploads; this.totalUploadFailures = totalUploadFailures; this.replicaMode = replicaMode; + this.primaryEpoch = primaryEpoch; + this.seenEpoch = seenEpoch; this.uwalBytesWritten = uwalBytesWritten; this.walBytesWritten = walBytesWritten; this.flushBytesWritten = flushBytesWritten; @@ -243,6 +248,27 @@ public boolean isReplicaMode() { return replicaMode; } + /** + * Gets the lease epoch this primary currently holds (object-store single-writer fencing). + * Returns 0 when this node is not a primary or holds no lease. A promotion that takes + * effect bumps this value. + * + * @return the current primary lease epoch, or 0 if not a primary + */ + public long getPrimaryEpoch() { + return primaryEpoch; + } + + /** + * Gets the highest lease epoch this node has observed (object-store single-writer fencing). + * A fenced primary sees {@link #isReplicaMode()} flip back to true once a newer epoch is seen. + * + * @return the highest observed lease epoch + */ + public long getSeenEpoch() { + return seenEpoch; + } + /** * Gets the framed bytes appended to the shared unified WAL (lifetime since open). * Returns 0 when unified memtable mode is off. @@ -355,6 +381,8 @@ public String toString() { ", totalUploads=" + totalUploads + ", totalUploadFailures=" + totalUploadFailures + ", replicaMode=" + replicaMode + + ", primaryEpoch=" + primaryEpoch + + ", seenEpoch=" + seenEpoch + ", uwalBytesWritten=" + uwalBytesWritten + ", walBytesWritten=" + walBytesWritten + ", flushBytesWritten=" + flushBytesWritten + diff --git a/src/test/java/com/tidesdb/TidesDBTest.java b/src/test/java/com/tidesdb/TidesDBTest.java index 5456c0b..fdb7d61 100644 --- a/src/test/java/com/tidesdb/TidesDBTest.java +++ b/src/test/java/com/tidesdb/TidesDBTest.java @@ -1480,11 +1480,17 @@ void testDbStatsUnifiedFields() throws TidesDBException { assertTrue(dbStats.getTotalUploads() >= 0); assertTrue(dbStats.getTotalUploadFailures() >= 0); + // Single-writer fencing epochs default to 0 outside object-store primary mode + assertEquals(0, dbStats.getPrimaryEpoch()); + assertTrue(dbStats.getSeenEpoch() >= 0); + // Verify toString includes new fields String str = dbStats.toString(); assertTrue(str.contains("unifiedMemtableEnabled=")); assertTrue(str.contains("objectStoreEnabled=")); assertTrue(str.contains("replicaMode=")); + assertTrue(str.contains("primaryEpoch=")); + assertTrue(str.contains("seenEpoch=")); } }