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="));
}
}