From 6ef15220738d7394b7d6badf558add8707df6a37 Mon Sep 17 00:00:00 2001 From: dhoard Date: Sun, 12 Jul 2026 19:16:26 -0400 Subject: [PATCH] polish: Polished Javadocs Signed-off-by: dhoard --- src/main/java/com/tidesdb/CacheStats.java | 43 ++- src/main/java/com/tidesdb/ColumnFamily.java | 23 +- .../java/com/tidesdb/ColumnFamilyConfig.java | 309 +++++++++++++++++- .../com/tidesdb/CompressionAlgorithm.java | 33 +- src/main/java/com/tidesdb/Config.java | 118 ++++++- src/main/java/com/tidesdb/IsolationLevel.java | 37 ++- src/main/java/com/tidesdb/LogLevel.java | 41 ++- src/main/java/com/tidesdb/NativeLibrary.java | 44 ++- src/main/java/com/tidesdb/Stats.java | 43 ++- src/main/java/com/tidesdb/SyncMode.java | 31 +- src/main/java/com/tidesdb/TidesDB.java | 84 +++-- .../java/com/tidesdb/TidesDBException.java | 92 +++++- .../java/com/tidesdb/TidesDBIterator.java | 64 ++-- src/main/java/com/tidesdb/Transaction.java | 109 ++++-- 14 files changed, 925 insertions(+), 146 deletions(-) diff --git a/src/main/java/com/tidesdb/CacheStats.java b/src/main/java/com/tidesdb/CacheStats.java index cc846f4..de29061 100644 --- a/src/main/java/com/tidesdb/CacheStats.java +++ b/src/main/java/com/tidesdb/CacheStats.java @@ -19,7 +19,8 @@ package com.tidesdb; /** - * Statistics about the block cache. + * Statistics about the block cache in a {@link TidesDB} instance. Created by + * the native library and returned from {@link TidesDB#getCacheStats()}. */ public class CacheStats { @@ -31,6 +32,18 @@ public class CacheStats { private final double hitRate; private final long numPartitions; + /** + * Creates a new {@code CacheStats} instance. Typically called by the JNI + * bridge rather than application code. + * + * @param enabled whether the cache is enabled + * @param totalEntries the total number of cache entries + * @param totalBytes the total bytes used by the cache + * @param hits the number of cache hits + * @param misses the number of cache misses + * @param hitRate the cache hit rate (0.0 to 1.0) + * @param numPartitions the number of cache partitions + */ public CacheStats(boolean enabled, long totalEntries, long totalBytes, long hits, long misses, double hitRate, long numPartitions) { this.enabled = enabled; this.totalEntries = totalEntries; @@ -42,63 +55,63 @@ public CacheStats(boolean enabled, long totalEntries, long totalBytes, long hits } /** - * Returns whether the cache is enabled. + * Returns whether the block cache is enabled. * - * @return true if enabled + * @return {@code true} if the cache is enabled */ public boolean isEnabled() { return enabled; } /** - * Gets the total number of entries in the cache. + * Returns the total number of entries currently in the cache. * - * @return total entries + * @return the total entry count */ public long getTotalEntries() { return totalEntries; } /** - * Gets the total bytes used by the cache. + * Returns the total bytes used by the cache. * - * @return total bytes + * @return the total bytes */ public long getTotalBytes() { return totalBytes; } /** - * Gets the number of cache hits. + * Returns the cumulative number of cache hits. * - * @return cache hits + * @return the cache hit count */ public long getHits() { return hits; } /** - * Gets the number of cache misses. + * Returns the cumulative number of cache misses. * - * @return cache misses + * @return the cache miss count */ public long getMisses() { return misses; } /** - * Gets the cache hit rate. + * Returns the cache hit rate. * - * @return hit rate (0.0 to 1.0) + * @return the hit rate, typically in the range 0.0 to 1.0 */ public double getHitRate() { return hitRate; } /** - * Gets the number of cache partitions. + * Returns the number of cache partitions. * - * @return number of partitions + * @return the partition count */ public long getNumPartitions() { return numPartitions; diff --git a/src/main/java/com/tidesdb/ColumnFamily.java b/src/main/java/com/tidesdb/ColumnFamily.java index a1203e8..50aecb7 100644 --- a/src/main/java/com/tidesdb/ColumnFamily.java +++ b/src/main/java/com/tidesdb/ColumnFamily.java @@ -19,8 +19,15 @@ package com.tidesdb; /** - * Represents a column family in TidesDB. - * Column families are isolated key-value stores with independent configuration. + * Represents a column family in TidesDB. A column family is an isolated + * key-value store within a database, with its own independent configuration. + * + *

A {@code ColumnFamily} is a handle returned by {@link TidesDB#getColumnFamily(String)} + * and is not independently closeable. There is no Java-side guard against using + * a column family after its owning database has been closed; callers must manage + * the lifecycle externally. + * + *

This class is not guaranteed to be thread-safe. */ public class ColumnFamily { @@ -39,7 +46,7 @@ public class ColumnFamily { /** * Gets the name of this column family. * - * @return the column family name + * @return the column family name, never {@code null} */ public String getName() { return name; @@ -48,8 +55,8 @@ public String getName() { /** * Retrieves statistics about this column family. * - * @return column family statistics - * @throws TidesDBException if the stats cannot be retrieved + * @return column family statistics, never {@code null} + * @throws TidesDBException if the native stats retrieval fails */ public Stats getStats() throws TidesDBException { return nativeGetStats(nativeHandle); @@ -58,16 +65,16 @@ public Stats getStats() throws TidesDBException { /** * Manually triggers compaction for this column family. * - * @throws TidesDBException if compaction fails + * @throws TidesDBException if the native compaction fails */ public void compact() throws TidesDBException { nativeCompact(nativeHandle); } /** - * Manually triggers memtable flush for this column family. + * Manually triggers a memtable flush for this column family. * - * @throws TidesDBException if flush fails + * @throws TidesDBException if the native flush fails */ public void flushMemtable() throws TidesDBException { nativeFlushMemtable(nativeHandle); diff --git a/src/main/java/com/tidesdb/ColumnFamilyConfig.java b/src/main/java/com/tidesdb/ColumnFamilyConfig.java index 06d4a73..d737f35 100644 --- a/src/main/java/com/tidesdb/ColumnFamilyConfig.java +++ b/src/main/java/com/tidesdb/ColumnFamilyConfig.java @@ -19,7 +19,13 @@ package com.tidesdb; /** - * Configuration for a column family. + * Configuration for a column family. Use {@link #builder()} to construct a + * configuration with custom values, or {@link #defaultConfig()} to obtain a + * configuration with default settings. + * + *

Instances are immutable once built. Unlike {@link Config.Builder}, the + * {@link Builder#build()} method does not perform Java-side validation of the + * field values. */ public class ColumnFamilyConfig { @@ -68,9 +74,31 @@ private ColumnFamilyConfig(Builder builder) { } /** - * Creates a default column family configuration. + * Creates a default column family configuration with the following values: + *

* - * @return a new ColumnFamilyConfig with default values + * @return a new {@code ColumnFamilyConfig} with default values */ public static ColumnFamilyConfig defaultConfig() { return new Builder() @@ -98,40 +126,176 @@ public static ColumnFamilyConfig defaultConfig() { } /** - * Creates a new builder for ColumnFamilyConfig. + * Creates a new builder with default values. * - * @return a new Builder + * @return a new {@code Builder} */ public static Builder builder() { return new Builder(); } + /** + * Returns the write-buffer (memtable) size in bytes. + * + * @return the write-buffer size in bytes + */ public long getWriteBufferSize() { return writeBufferSize; } + + /** + * Returns the size ratio between adjacent LSM levels. + * + * @return the level size ratio + */ public long getLevelSizeRatio() { return levelSizeRatio; } + + /** + * Returns the minimum number of LSM levels. + * + * @return the minimum level count + */ public int getMinLevels() { return minLevels; } + + /** + * Returns the dividing level offset used for tiering decisions. + * + * @return the dividing level offset + */ public int getDividingLevelOffset() { return dividingLevelOffset; } + + /** + * Returns the key-log value threshold in bytes. Values at or below this + * size are stored inline in the key log. + * + * @return the key-log value threshold in bytes + */ public long getKlogValueThreshold() { return klogValueThreshold; } + + /** + * Returns the compression algorithm used for SSTables. + * + * @return the compression algorithm + */ public CompressionAlgorithm getCompressionAlgorithm() { return compressionAlgorithm; } + + /** + * Returns whether Bloom filters are enabled for this column family. + * + * @return {@code true} if Bloom filters are enabled + */ public boolean isEnableBloomFilter() { return enableBloomFilter; } + + /** + * Returns the Bloom filter false-positive rate. + * + * @return the false-positive rate + */ public double getBloomFPR() { return bloomFPR; } + + /** + * Returns whether block indexes are enabled for this column family. + * + * @return {@code true} if block indexes are enabled + */ public boolean isEnableBlockIndexes() { return enableBlockIndexes; } + + /** + * Returns the index sample ratio for block indexes. + * + * @return the index sample ratio + */ public int getIndexSampleRatio() { return indexSampleRatio; } + + /** + * Returns the block index prefix length. + * + * @return the block index prefix length + */ public int getBlockIndexPrefixLen() { return blockIndexPrefixLen; } + + /** + * Returns the sync mode for durability control. + * + * @return the sync mode + */ public SyncMode getSyncMode() { return syncMode; } + + /** + * Returns the sync interval in microseconds. Only meaningful when + * {@code syncMode} is {@link SyncMode#SYNC_INTERVAL}. + * + * @return the sync interval in microseconds + */ public long getSyncIntervalUs() { return syncIntervalUs; } + + /** + * Returns the custom comparator name. An empty string indicates the + * default lexicographic comparator. + * + * @return the comparator name, or an empty string for the default + */ public String getComparatorName() { return comparatorName; } + + /** + * Returns the maximum level for the skip-list memtable. + * + * @return the skip-list maximum level + */ public int getSkipListMaxLevel() { return skipListMaxLevel; } + + /** + * Returns the probability parameter for skip-list level promotion. + * + * @return the skip-list probability + */ public float getSkipListProbability() { return skipListProbability; } + + /** + * Returns the default isolation level for transactions on this column + * family. + * + * @return the default isolation level + */ public IsolationLevel getDefaultIsolationLevel() { return defaultIsolationLevel; } + + /** + * Returns the minimum disk space in bytes required before writes are + * rejected. + * + * @return the minimum disk space in bytes + */ public long getMinDiskSpace() { return minDiskSpace; } + + /** + * Returns the L1 file-count trigger for compaction. + * + * @return the L1 file count trigger + */ public int getL1FileCountTrigger() { return l1FileCountTrigger; } + + /** + * Returns the L0 queue stall threshold. When the L0 file count reaches + * this threshold, writes are stalled until compaction reduces the count. + * + * @return the L0 queue stall threshold + */ public int getL0QueueStallThreshold() { return l0QueueStallThreshold; } /** - * Builder for ColumnFamilyConfig. + * Builder for {@link ColumnFamilyConfig}. All fields have sensible + * defaults matching {@link #defaultConfig()}. Call {@link #build()} to + * create the immutable configuration. + * + *

Unlike {@link Config.Builder}, the {@link #build()} method does not + * perform Java-side validation of field values. */ public static class Builder { private long writeBufferSize = 64 * 1024 * 1024; + + /** + * Creates a new builder with default values. + */ + public Builder() { + } private long levelSizeRatio = 10; private int minLevels = 4; private int dividingLevelOffset = 2; @@ -152,106 +316,239 @@ public static class Builder { private int l1FileCountTrigger = 4; private int l0QueueStallThreshold = 8; + /** + * Sets the write-buffer (memtable) size in bytes. + * + * @param writeBufferSize the size in bytes + * @return this builder + */ public Builder writeBufferSize(long writeBufferSize) { this.writeBufferSize = writeBufferSize; return this; } + /** + * Sets the size ratio between adjacent LSM levels. + * + * @param levelSizeRatio the level size ratio + * @return this builder + */ public Builder levelSizeRatio(long levelSizeRatio) { this.levelSizeRatio = levelSizeRatio; return this; } + /** + * Sets the minimum number of LSM levels. + * + * @param minLevels the minimum level count + * @return this builder + */ public Builder minLevels(int minLevels) { this.minLevels = minLevels; return this; } + /** + * Sets the dividing level offset for tiering decisions. + * + * @param dividingLevelOffset the offset + * @return this builder + */ public Builder dividingLevelOffset(int dividingLevelOffset) { this.dividingLevelOffset = dividingLevelOffset; return this; } + /** + * Sets the key-log value threshold in bytes. + * + * @param klogValueThreshold the threshold in bytes + * @return this builder + */ public Builder klogValueThreshold(long klogValueThreshold) { this.klogValueThreshold = klogValueThreshold; return this; } + /** + * Sets the compression algorithm for SSTables. + * + * @param compressionAlgorithm the compression algorithm; must not be + * {@code null} + * @return this builder + */ public Builder compressionAlgorithm(CompressionAlgorithm compressionAlgorithm) { this.compressionAlgorithm = compressionAlgorithm; return this; } + /** + * Enables or disables Bloom filters. + * + * @param enableBloomFilter {@code true} to enable + * @return this builder + */ public Builder enableBloomFilter(boolean enableBloomFilter) { this.enableBloomFilter = enableBloomFilter; return this; } + /** + * Sets the Bloom filter false-positive rate. + * + * @param bloomFPR the false-positive rate + * @return this builder + */ public Builder bloomFPR(double bloomFPR) { this.bloomFPR = bloomFPR; return this; } + /** + * Enables or disables block indexes. + * + * @param enableBlockIndexes {@code true} to enable + * @return this builder + */ public Builder enableBlockIndexes(boolean enableBlockIndexes) { this.enableBlockIndexes = enableBlockIndexes; return this; } + /** + * Sets the index sample ratio for block indexes. + * + * @param indexSampleRatio the sample ratio + * @return this builder + */ public Builder indexSampleRatio(int indexSampleRatio) { this.indexSampleRatio = indexSampleRatio; return this; } + /** + * Sets the block index prefix length. + * + * @param blockIndexPrefixLen the prefix length + * @return this builder + */ public Builder blockIndexPrefixLen(int blockIndexPrefixLen) { this.blockIndexPrefixLen = blockIndexPrefixLen; return this; } + /** + * Sets the sync mode for durability control. + * + * @param syncMode the sync mode; must not be {@code null} + * @return this builder + */ public Builder syncMode(SyncMode syncMode) { this.syncMode = syncMode; return this; } + /** + * Sets the sync interval in microseconds. Only meaningful when + * {@code syncMode} is {@link SyncMode#SYNC_INTERVAL}. + * + * @param syncIntervalUs the interval in microseconds + * @return this builder + */ public Builder syncIntervalUs(long syncIntervalUs) { this.syncIntervalUs = syncIntervalUs; return this; } + /** + * Sets the custom comparator name. An empty string selects the + * default lexicographic comparator. + * + * @param comparatorName the comparator name + * @return this builder + */ public Builder comparatorName(String comparatorName) { this.comparatorName = comparatorName; return this; } + /** + * Sets the maximum level for the skip-list memtable. + * + * @param skipListMaxLevel the maximum level + * @return this builder + */ public Builder skipListMaxLevel(int skipListMaxLevel) { this.skipListMaxLevel = skipListMaxLevel; return this; } + /** + * Sets the probability parameter for skip-list level promotion. + * + * @param skipListProbability the promotion probability + * @return this builder + */ public Builder skipListProbability(float skipListProbability) { this.skipListProbability = skipListProbability; return this; } + /** + * Sets the default isolation level for transactions on this column + * family. + * + * @param defaultIsolationLevel the isolation level; must not be + * {@code null} + * @return this builder + */ public Builder defaultIsolationLevel(IsolationLevel defaultIsolationLevel) { this.defaultIsolationLevel = defaultIsolationLevel; return this; } + /** + * Sets the minimum disk space in bytes required before writes are + * rejected. + * + * @param minDiskSpace the minimum disk space in bytes + * @return this builder + */ public Builder minDiskSpace(long minDiskSpace) { this.minDiskSpace = minDiskSpace; return this; } + /** + * Sets the L1 file-count trigger for compaction. + * + * @param l1FileCountTrigger the file count trigger + * @return this builder + */ public Builder l1FileCountTrigger(int l1FileCountTrigger) { this.l1FileCountTrigger = l1FileCountTrigger; return this; } + /** + * Sets the L0 queue stall threshold. When the L0 file count reaches + * this threshold, writes are stalled until compaction reduces the count. + * + * @param l0QueueStallThreshold the stall threshold + * @return this builder + */ public Builder l0QueueStallThreshold(int l0QueueStallThreshold) { this.l0QueueStallThreshold = l0QueueStallThreshold; return this; } + /** + * Creates the immutable {@link ColumnFamilyConfig}. No Java-side + * validation of field values is performed. + * + * @return a new {@code ColumnFamilyConfig} + */ public ColumnFamilyConfig build() { return new ColumnFamilyConfig(this); } diff --git a/src/main/java/com/tidesdb/CompressionAlgorithm.java b/src/main/java/com/tidesdb/CompressionAlgorithm.java index 6552962..0b42116 100644 --- a/src/main/java/com/tidesdb/CompressionAlgorithm.java +++ b/src/main/java/com/tidesdb/CompressionAlgorithm.java @@ -19,12 +19,29 @@ package com.tidesdb; /** - * Compression algorithm for column families. + * Compression algorithm for column family SSTables. Each constant maps to an + * integer used by the JNI bridge. */ public enum CompressionAlgorithm { + + /** + * No compression. + */ NO_COMPRESSION(0), + + /** + * LZ4 compression with default settings. + */ LZ4_COMPRESSION(1), + + /** + * Zstandard compression. + */ ZSTD_COMPRESSION(2), + + /** + * LZ4 compression optimized for speed. + */ LZ4_FAST_COMPRESSION(3); private final int value; @@ -33,10 +50,24 @@ public enum CompressionAlgorithm { this.value = value; } + /** + * Returns the JNI numeric mapping for this compression algorithm. + * + * @return the integer value passed to the native library + */ public int getValue() { return value; } + /** + * Returns the {@link CompressionAlgorithm} constant matching the given + * JNI integer value. + * + * @param value the JNI integer value + * @return the matching constant + * @throws IllegalArgumentException if {@code value} does not map to any + * known constant + */ public static CompressionAlgorithm fromValue(int value) { for (CompressionAlgorithm algo : values()) { if (algo.value == value) { diff --git a/src/main/java/com/tidesdb/Config.java b/src/main/java/com/tidesdb/Config.java index 77843b8..120d66e 100644 --- a/src/main/java/com/tidesdb/Config.java +++ b/src/main/java/com/tidesdb/Config.java @@ -19,7 +19,12 @@ package com.tidesdb; /** - * Configuration for opening a TidesDB instance. + * Configuration for opening a {@link TidesDB} instance. Use {@link #builder(String)} + * to construct a configuration with custom values, or {@link #defaultConfig()} to + * obtain a configuration with default settings. + * + *

Instances are immutable once built. {@link Builder#build()} validates all fields + * and throws {@link IllegalArgumentException} for invalid values. */ public class Config { @@ -40,9 +45,16 @@ private Config(Builder builder) { } /** - * Creates a default configuration. + * Creates a default configuration with the following values: + *

* - * @return a new Config with default values + * @return a new {@code Config} with default values */ public static Config defaultConfig() { return new Builder() @@ -55,80 +67,160 @@ public static Config defaultConfig() { } /** - * Creates a new builder for Config. + * Creates a new builder with the given database path. * - * @param dbPath the database path - * @return a new Builder + * @param dbPath the database file-system path; must not be {@code null} + * @return a new {@code Builder} */ public static Builder builder(String dbPath) { return new Builder().dbPath(dbPath); } + /** + * Returns the database file-system path. + * + * @return the database path + */ public String getDbPath() { return dbPath; } - + + /** + * Returns the number of flush threads. + * + * @return the flush thread count + */ public int getNumFlushThreads() { return numFlushThreads; } - + + /** + * Returns the number of compaction threads. + * + * @return the compaction thread count + */ public int getNumCompactionThreads() { return numCompactionThreads; } - + + /** + * Returns the log level. + * + * @return the log level + */ public LogLevel getLogLevel() { return logLevel; } - + + /** + * Returns the block cache size in bytes. + * + * @return the block cache size in bytes + */ public long getBlockCacheSize() { return blockCacheSize; } - + + /** + * Returns the maximum number of open SSTables. + * + * @return the maximum open SSTable count + */ public long getMaxOpenSSTables() { return maxOpenSSTables; } /** - * Builder for Config. + * Builder for {@link Config}. All fields have sensible defaults. Call + * {@link #build()} to create the immutable configuration; {@code build()} + * validates all fields. */ public static class Builder { private String dbPath = ""; + + /** + * Creates a new builder with default values. + */ + public Builder() { + } private int numFlushThreads = 2; private int numCompactionThreads = 2; private LogLevel logLevel = LogLevel.INFO; private long blockCacheSize = 64 * 1024 * 1024; private long maxOpenSSTables = 256; - + + /** + * Sets the database file-system path. + * + * @param dbPath the path; must not be {@code null} + * @return this builder + */ public Builder dbPath(String dbPath) { this.dbPath = dbPath; return this; } + /** + * Sets the number of flush threads. + * + * @param numFlushThreads the thread count; must be positive + * @return this builder + */ public Builder numFlushThreads(int numFlushThreads) { this.numFlushThreads = numFlushThreads; return this; } + /** + * Sets the number of compaction threads. + * + * @param numCompactionThreads the thread count; must be positive + * @return this builder + */ public Builder numCompactionThreads(int numCompactionThreads) { this.numCompactionThreads = numCompactionThreads; return this; } + /** + * Sets the log level. + * + * @param logLevel the log level; must not be {@code null} + * @return this builder + */ public Builder logLevel(LogLevel logLevel) { this.logLevel = logLevel; return this; } + /** + * Sets the block cache size in bytes. + * + * @param blockCacheSize the size in bytes; must not be negative + * @return this builder + */ public Builder blockCacheSize(long blockCacheSize) { this.blockCacheSize = blockCacheSize; return this; } + /** + * Sets the maximum number of open SSTables. + * + * @param maxOpenSSTables the maximum count; must be positive + * @return this builder + */ public Builder maxOpenSSTables(long maxOpenSSTables) { this.maxOpenSSTables = maxOpenSSTables; return this; } + /** + * Validates all fields and creates the immutable {@link Config}. + * + * @return a new {@code Config} + * @throws IllegalArgumentException if any field is invalid + */ public Config build() { validate(); return new Config(this); diff --git a/src/main/java/com/tidesdb/IsolationLevel.java b/src/main/java/com/tidesdb/IsolationLevel.java index a5a7166..e1d376b 100644 --- a/src/main/java/com/tidesdb/IsolationLevel.java +++ b/src/main/java/com/tidesdb/IsolationLevel.java @@ -19,13 +19,34 @@ package com.tidesdb; /** - * Transaction isolation level. + * Transaction isolation level. Each constant maps to an integer used by the + * JNI bridge. */ public enum IsolationLevel { + + /** + * Reads may see uncommitted changes from other transactions. + */ READ_UNCOMMITTED(0), + + /** + * Reads see only committed data (default). + */ READ_COMMITTED(1), + + /** + * Reads within a transaction see a consistent snapshot from its start. + */ REPEATABLE_READ(2), + + /** + * Reads operate against a named snapshot. + */ SNAPSHOT(3), + + /** + * Full serializable isolation. + */ SERIALIZABLE(4); private final int value; @@ -34,10 +55,24 @@ public enum IsolationLevel { this.value = value; } + /** + * Returns the JNI numeric mapping for this isolation level. + * + * @return the integer value passed to the native library + */ public int getValue() { return value; } + /** + * Returns the {@link IsolationLevel} constant matching the given JNI + * integer value. + * + * @param value the JNI integer value + * @return the matching constant + * @throws IllegalArgumentException if {@code value} does not map to any + * known constant + */ public static IsolationLevel fromValue(int value) { for (IsolationLevel level : values()) { if (level.value == value) { diff --git a/src/main/java/com/tidesdb/LogLevel.java b/src/main/java/com/tidesdb/LogLevel.java index 90e7333..33e020e 100644 --- a/src/main/java/com/tidesdb/LogLevel.java +++ b/src/main/java/com/tidesdb/LogLevel.java @@ -19,14 +19,39 @@ package com.tidesdb; /** - * Logging level for TidesDB. + * Logging level for the native TidesDB library. Each constant maps to an + * integer used by the JNI bridge. */ public enum LogLevel { + + /** + * Verbose debug output. + */ DEBUG(0), + + /** + * Informational messages (default). + */ INFO(1), + + /** + * Warning messages. + */ WARN(2), + + /** + * Error messages. + */ ERROR(3), + + /** + * Fatal messages. + */ FATAL(4), + + /** + * Logging disabled. + */ NONE(5); private final int value; @@ -35,10 +60,24 @@ public enum LogLevel { this.value = value; } + /** + * Returns the JNI numeric mapping for this log level. + * + * @return the integer value passed to the native library + */ public int getValue() { return value; } + /** + * Returns the {@link LogLevel} constant matching the given JNI integer + * value. + * + * @param value the JNI integer value + * @return the matching constant + * @throws IllegalArgumentException if {@code value} does not map to any + * known constant + */ public static LogLevel fromValue(int value) { for (LogLevel level : values()) { if (level.value == value) { diff --git a/src/main/java/com/tidesdb/NativeLibrary.java b/src/main/java/com/tidesdb/NativeLibrary.java index 4cb6417..d82fa75 100644 --- a/src/main/java/com/tidesdb/NativeLibrary.java +++ b/src/main/java/com/tidesdb/NativeLibrary.java @@ -26,17 +26,47 @@ import java.nio.file.StandardCopyOption; /** - * Handles loading of the native TidesDB JNI library. + * Handles loading of the native TidesDB JNI library ({@code tidesdb_jni}). + * + *

The {@link #load()} method is idempotent and {@code synchronized}; it + * attempts to load the native library through the following ordered lookup + * paths: + *

    + *
  1. {@code System.loadLibrary("tidesdb_jni")} using {@code java.library.path}
  2. + *
  3. Explicit file lookup in each {@code java.library.path} directory
  4. + *
  5. Packaged resource extraction from the classpath ({@code /native///})
  6. + *
+ * + *

If all paths fail, {@link UnsatisfiedLinkError} is thrown with details + * about the attempted paths. + * + *

{@link #isLoaded()} reports whether the library has been loaded + * successfully; it does not synchronize or guarantee availability. */ public class NativeLibrary { + private NativeLibrary() { + // utility class + } + private static final String LIBRARY_NAME = "tidesdb_jni"; private static volatile boolean loaded = false; private static final Object lock = new Object(); /** - * Loads the native library. - * This method is idempotent and thread-safe. + * Loads the native TidesDB JNI library. This method is idempotent and + * synchronized; concurrent calls are safe and only the first call + * performs the actual loading. + * + *

The lookup order is: + *

    + *
  1. {@code System.loadLibrary("tidesdb_jni")} using {@code java.library.path}
  2. + *
  3. Explicit file lookup in each {@code java.library.path} directory
  4. + *
  5. Packaged resource extraction from the classpath
  6. + *
+ * + * @throws UnsatisfiedLinkError if the library cannot be loaded through + * any of the supported lookup paths */ public static void load() { if (loaded) { @@ -138,9 +168,13 @@ private static void loadFromResources() throws IOException { } /** - * Returns whether the native library has been loaded. + * Returns whether the native library has been loaded successfully. + * + *

This method reports the current loaded flag without synchronizing; + * it does not guarantee that subsequent {@link #load()} calls will + * succeed or that the library is usable from the calling thread. * - * @return true if loaded + * @return {@code true} if the library has been loaded */ public static boolean isLoaded() { return loaded; diff --git a/src/main/java/com/tidesdb/Stats.java b/src/main/java/com/tidesdb/Stats.java index 221ee99..360aa0c 100644 --- a/src/main/java/com/tidesdb/Stats.java +++ b/src/main/java/com/tidesdb/Stats.java @@ -19,7 +19,13 @@ package com.tidesdb; /** - * Statistics about a column family. + * Statistics about a column family, including level structure, memtable size, + * and the active configuration. Created by the native library and returned + * from {@link ColumnFamily#getStats()}. + * + *

The arrays returned by {@link #getLevelSizes()} and + * {@link #getLevelNumSSTables()} are the internal stored references, not + * defensive copies. Callers must not modify them. */ public class Stats { @@ -29,6 +35,16 @@ public class Stats { private final int[] levelNumSSTables; private final ColumnFamilyConfig config; + /** + * Creates a new {@code Stats} instance. Typically called by the JNI + * bridge rather than application code. + * + * @param numLevels the number of LSM levels + * @param memtableSize the current memtable size in bytes + * @param levelSizes the size in bytes for each level (stored by reference) + * @param levelNumSSTables the SSTable count for each level (stored by reference) + * @param config the column family configuration + */ public Stats(int numLevels, long memtableSize, long[] levelSizes, int[] levelNumSSTables, ColumnFamilyConfig config) { this.numLevels = numLevels; this.memtableSize = memtableSize; @@ -38,7 +54,7 @@ public Stats(int numLevels, long memtableSize, long[] levelSizes, int[] levelNum } /** - * Gets the number of levels. + * Returns the number of LSM levels. * * @return the number of levels */ @@ -47,36 +63,43 @@ public int getNumLevels() { } /** - * Gets the memtable size in bytes. + * Returns the current memtable size in bytes. * - * @return the memtable size + * @return the memtable size in bytes */ public long getMemtableSize() { return memtableSize; } /** - * Gets the sizes of each level in bytes. + * Returns the sizes of each LSM level in bytes. + * + *

The returned array is the stored internal reference, not a + * defensive copy. Callers must not modify it. * - * @return array of level sizes + * @return the level sizes in bytes (internal reference) */ public long[] getLevelSizes() { return levelSizes; } /** - * Gets the number of SSTables at each level. + * Returns the number of SSTables at each LSM level. + * + *

The returned array is the stored internal reference, not a + * defensive copy. Callers must not modify it. * - * @return array of SSTable counts per level + * @return the SSTable counts per level (internal reference) */ public int[] getLevelNumSSTables() { return levelNumSSTables; } /** - * Gets the column family configuration. + * Returns the column family configuration active when these statistics + * were captured. * - * @return the configuration + * @return the configuration, never {@code null} */ public ColumnFamilyConfig getConfig() { return config; diff --git a/src/main/java/com/tidesdb/SyncMode.java b/src/main/java/com/tidesdb/SyncMode.java index 0958b21..9e6894b 100644 --- a/src/main/java/com/tidesdb/SyncMode.java +++ b/src/main/java/com/tidesdb/SyncMode.java @@ -19,11 +19,26 @@ package com.tidesdb; /** - * Sync mode for durability. + * Sync mode for durability control. Each constant maps to an integer used by + * the JNI bridge. */ public enum SyncMode { + + /** + * No synchronous writes; fastest, but uncommitted data may be lost on + * crash. + */ SYNC_NONE(0), + + /** + * Synchronous writes on every operation; slowest, but most durable. + */ SYNC_FULL(1), + + /** + * Synchronous writes at a configured interval (see + * {@code syncIntervalUs} in {@link ColumnFamilyConfig}). + */ SYNC_INTERVAL(2); private final int value; @@ -32,10 +47,24 @@ public enum SyncMode { this.value = value; } + /** + * Returns the JNI numeric mapping for this sync mode. + * + * @return the integer value passed to the native library + */ public int getValue() { return value; } + /** + * Returns the {@link SyncMode} constant matching the given JNI integer + * value. + * + * @param value the JNI integer value + * @return the matching constant + * @throws IllegalArgumentException if {@code value} does not map to any + * known constant + */ public static SyncMode fromValue(int value) { for (SyncMode mode : values()) { if (mode.value == value) { diff --git a/src/main/java/com/tidesdb/TidesDB.java b/src/main/java/com/tidesdb/TidesDB.java index d63268e..4506587 100644 --- a/src/main/java/com/tidesdb/TidesDB.java +++ b/src/main/java/com/tidesdb/TidesDB.java @@ -21,8 +21,17 @@ import java.io.Closeable; /** - * TidesDB is the main database class providing access to TidesDB functionality. - * This class wraps the native TidesDB library through JNI. + * Main entry point for a TidesDB database. This class wraps the native TidesDB + * library through JNI and owns the underlying database handle. + * + *

{@code TidesDB} implements {@link java.io.Closeable} and should be used with + * try-with-resources. Callers must close any {@link TidesDBIterator} and + * {@link Transaction} instances before closing the database. Closing an already-closed + * instance is a no-op. + * + *

Operations on a closed instance throw {@link IllegalStateException}. + * + *

This class is not guaranteed to be thread-safe. */ public class TidesDB implements Closeable { @@ -40,9 +49,11 @@ private TidesDB(long nativeHandle) { /** * Opens a TidesDB instance with the given configuration. * - * @param config the database configuration + * @param config the database configuration; must not be {@code null} * @return a new TidesDB instance - * @throws TidesDBException if the database cannot be opened + * @throws IllegalArgumentException if {@code config} is {@code null} or its + * {@code dbPath} is {@code null} or empty + * @throws TidesDBException if the native database cannot be opened */ public static TidesDB open(Config config) throws TidesDBException { if (config == null) { @@ -65,7 +76,13 @@ public static TidesDB open(Config config) throws TidesDBException { } /** - * Closes the database instance and releases all resources. + * Closes the database and releases all native resources. + * + *

This method is idempotent; subsequent calls are no-ops. After closing, + * all other operations on this instance throw {@link IllegalStateException}. + * + *

Callers should close all {@link TidesDBIterator} and {@link Transaction} + * instances before calling this method. */ @Override public void close() { @@ -79,9 +96,12 @@ public void close() { /** * Creates a new column family with the given configuration. * - * @param name the column family name - * @param config the column family configuration - * @throws TidesDBException if the column family cannot be created + * @param name the column family name; must not be {@code null} or empty + * @param config the column family configuration; must not be {@code null} + * @throws IllegalArgumentException if {@code name} is {@code null} or empty, + * or {@code config} is {@code null} + * @throws IllegalStateException if this database is closed + * @throws TidesDBException if the native column family cannot be created */ public void createColumnFamily(String name, ColumnFamilyConfig config) throws TidesDBException { checkNotClosed(); @@ -119,8 +139,10 @@ public void createColumnFamily(String name, ColumnFamilyConfig config) throws Ti /** * Drops a column family and all associated data. * - * @param name the column family name - * @throws TidesDBException if the column family cannot be dropped + * @param name the column family name; must not be {@code null} or empty + * @throws IllegalArgumentException if {@code name} is {@code null} or empty + * @throws IllegalStateException if this database is closed + * @throws TidesDBException if the native column family cannot be dropped */ public void dropColumnFamily(String name) throws TidesDBException { checkNotClosed(); @@ -133,9 +155,12 @@ public void dropColumnFamily(String name) throws TidesDBException { /** * Retrieves a column family by name. * - * @param name the column family name - * @return the column family - * @throws TidesDBException if the column family is not found + * @param name the column family name; must not be {@code null} or empty + * @return the column family handle + * @throws IllegalArgumentException if {@code name} is {@code null} or empty + * @throws IllegalStateException if this database is closed + * @throws TidesDBException if the column family is not found or a native + * error occurs */ public ColumnFamily getColumnFamily(String name) throws TidesDBException { checkNotClosed(); @@ -149,8 +174,9 @@ public ColumnFamily getColumnFamily(String name) throws TidesDBException { /** * Lists all column families in the database. * - * @return array of column family names - * @throws TidesDBException if the list cannot be retrieved + * @return array of column family names, never {@code null} + * @throws IllegalStateException if this database is closed + * @throws TidesDBException if the native list operation fails */ public String[] listColumnFamilies() throws TidesDBException { checkNotClosed(); @@ -158,10 +184,13 @@ public String[] listColumnFamilies() throws TidesDBException { } /** - * Begins a new transaction with default isolation level. + * Begins a new transaction with the default isolation level. + * + *

Close the returned transaction before closing this database. * * @return a new transaction - * @throws TidesDBException if the transaction cannot be started + * @throws IllegalStateException if this database is closed + * @throws TidesDBException if the native transaction cannot be started */ public Transaction beginTransaction() throws TidesDBException { checkNotClosed(); @@ -172,9 +201,13 @@ public Transaction beginTransaction() throws TidesDBException { /** * Begins a new transaction with the specified isolation level. * - * @param isolationLevel the isolation level + *

Close the returned transaction before closing this database. + * + * @param isolationLevel the isolation level; must not be {@code null} * @return a new transaction - * @throws TidesDBException if the transaction cannot be started + * @throws IllegalArgumentException if {@code isolationLevel} is {@code null} + * @throws IllegalStateException if this database is closed + * @throws TidesDBException if the native transaction cannot be started */ public Transaction beginTransaction(IsolationLevel isolationLevel) throws TidesDBException { checkNotClosed(); @@ -188,8 +221,9 @@ public Transaction beginTransaction(IsolationLevel isolationLevel) throws TidesD /** * Retrieves statistics about the block cache. * - * @return cache statistics - * @throws TidesDBException if the stats cannot be retrieved + * @return cache statistics, never {@code null} + * @throws IllegalStateException if this database is closed + * @throws TidesDBException if the native stats retrieval fails */ public CacheStats getCacheStats() throws TidesDBException { checkNotClosed(); @@ -199,9 +233,11 @@ public CacheStats getCacheStats() throws TidesDBException { /** * Registers a custom comparator with the database. * - * @param name the comparator name - * @param context optional context string - * @throws TidesDBException if the comparator cannot be registered + * @param name the comparator name; must not be {@code null} or empty + * @param context optional context string, may be {@code null} + * @throws IllegalArgumentException if {@code name} is {@code null} or empty + * @throws IllegalStateException if this database is closed + * @throws TidesDBException if the native comparator registration fails */ public void registerComparator(String name, String context) throws TidesDBException { checkNotClosed(); diff --git a/src/main/java/com/tidesdb/TidesDBException.java b/src/main/java/com/tidesdb/TidesDBException.java index d9a8ac3..c3247a5 100644 --- a/src/main/java/com/tidesdb/TidesDBException.java +++ b/src/main/java/com/tidesdb/TidesDBException.java @@ -19,62 +19,142 @@ package com.tidesdb; /** - * Exception thrown by TidesDB operations. + * Checked exception thrown by TidesDB native operations. Each exception carries + * an integer error code corresponding to a TidesDB status. Use {@link #getErrorCode()} + * to retrieve the numeric code and {@link #getErrorMessage()} for a human-readable + * description. */ public class TidesDBException extends Exception { + /** + * The error code. + */ private final int errorCode; /** - * Error codes from TidesDB. + * Error codes returned by the native TidesDB library. */ public static final int ERR_SUCCESS = 0; + + /** + * Memory allocation failure. + */ public static final int ERR_MEMORY = 1; + + /** + * Invalid arguments passed to a native operation. + */ public static final int ERR_INVALID_ARGS = 2; + + /** + * Requested entry not found. + */ public static final int ERR_NOT_FOUND = 3; + + /** + * I/O error during a native operation. + */ public static final int ERR_IO = 4; + + /** + * Data corruption detected. + */ public static final int ERR_CORRUPTION = 5; + + /** + * Entry already exists. + */ public static final int ERR_EXISTS = 6; + + /** + * Transaction conflict. + */ public static final int ERR_CONFLICT = 7; + + /** + * Key or value exceeds size limits. + */ public static final int ERR_TOO_LARGE = 8; + + /** + * Memory limit exceeded. + */ public static final int ERR_MEMORY_LIMIT = 9; + + /** + * Invalid database handle. + */ public static final int ERR_INVALID_DB = 10; + + /** + * Unknown error. + */ public static final int ERR_UNKNOWN = 11; + + /** + * Database is locked by another process. + */ public static final int ERR_LOCKED = 12; + /** + * Creates an exception with a message and an unknown error code. + * + * @param message the detail message + */ public TidesDBException(String message) { super(message); this.errorCode = ERR_UNKNOWN; } + /** + * Creates an exception with a message and a specific error code. + * + * @param message the detail message + * @param errorCode the TidesDB error code + */ public TidesDBException(String message, int errorCode) { super(message); this.errorCode = errorCode; } + /** + * Creates an exception with a message and a cause, using an unknown + * error code. + * + * @param message the detail message + * @param cause the underlying cause + */ public TidesDBException(String message, Throwable cause) { super(message, cause); this.errorCode = ERR_UNKNOWN; } + /** + * Creates an exception with a message, error code, and cause. + * + * @param message the detail message + * @param errorCode the TidesDB error code + * @param cause the underlying cause + */ public TidesDBException(String message, int errorCode, Throwable cause) { super(message, cause); this.errorCode = errorCode; } /** - * Gets the error code. + * Returns the TidesDB error code. * - * @return the error code + * @return one of the {@code ERR_*} constants defined in this class */ public int getErrorCode() { return errorCode; } /** - * Returns a human-readable error message for the error code. + * Returns a human-readable description of the error code. The mapping is + * local to this class and does not invoke any native method. * - * @return error message + * @return the error description */ public String getErrorMessage() { switch (errorCode) { diff --git a/src/main/java/com/tidesdb/TidesDBIterator.java b/src/main/java/com/tidesdb/TidesDBIterator.java index 8e3ce78..63ec442 100644 --- a/src/main/java/com/tidesdb/TidesDBIterator.java +++ b/src/main/java/com/tidesdb/TidesDBIterator.java @@ -22,7 +22,15 @@ /** * Iterator for traversing key-value pairs in a column family. - * Provides efficient bidirectional traversal. + * Provides efficient bidirectional traversal over the underlying storage. + * + *

{@code TidesDBIterator} implements {@link java.io.Closeable} for use with + * try-with-resources. Close iterators before the owning {@link Transaction} is + * freed. After this iterator is freed, all operations except {@link #isValid()} + * and {@code close()} throw {@link IllegalStateException}. The {@link #isValid()} + * method returns {@code false} on a freed iterator. + * + *

This class is not guaranteed to be thread-safe. */ public class TidesDBIterator implements Closeable { @@ -40,7 +48,8 @@ public class TidesDBIterator implements Closeable { /** * Positions the iterator at the first key. * - * @throws TidesDBException if the seek fails + * @throws IllegalStateException if this iterator is freed + * @throws TidesDBException if the native seek fails */ public void seekToFirst() throws TidesDBException { checkNotFreed(); @@ -50,7 +59,8 @@ public void seekToFirst() throws TidesDBException { /** * Positions the iterator at the last key. * - * @throws TidesDBException if the seek fails + * @throws IllegalStateException if this iterator is freed + * @throws TidesDBException if the native seek fails */ public void seekToLast() throws TidesDBException { checkNotFreed(); @@ -58,10 +68,13 @@ public void seekToLast() throws TidesDBException { } /** - * Positions the iterator at the first key >= target key. + * Positions the iterator at the first key greater than or equal to the + * target key. * - * @param key the target key - * @throws TidesDBException if the seek fails + * @param key the target key; must not be {@code null} or empty + * @throws IllegalArgumentException if {@code key} is {@code null} or empty + * @throws IllegalStateException if this iterator is freed + * @throws TidesDBException if the native seek fails */ public void seek(byte[] key) throws TidesDBException { checkNotFreed(); @@ -72,10 +85,13 @@ public void seek(byte[] key) throws TidesDBException { } /** - * Positions the iterator at the last key <= target key. + * Positions the iterator at the last key less than or equal to the target + * key. * - * @param key the target key - * @throws TidesDBException if the seek fails + * @param key the target key; must not be {@code null} or empty + * @throws IllegalArgumentException if {@code key} is {@code null} or empty + * @throws IllegalStateException if this iterator is freed + * @throws TidesDBException if the native seek fails */ public void seekForPrev(byte[] key) throws TidesDBException { checkNotFreed(); @@ -86,9 +102,12 @@ public void seekForPrev(byte[] key) throws TidesDBException { } /** - * Returns true if the iterator is positioned at a valid entry. + * Returns whether the iterator is positioned at a valid entry. * - * @return true if valid + *

Returns {@code false} if this iterator has been freed, without + * throwing an exception. + * + * @return {@code true} if the iterator is at a valid entry */ public boolean isValid() { if (freed) { @@ -100,7 +119,8 @@ public boolean isValid() { /** * Moves the iterator to the next entry. * - * @throws TidesDBException if the move fails + * @throws IllegalStateException if this iterator is freed + * @throws TidesDBException if the native next operation fails */ public void next() throws TidesDBException { checkNotFreed(); @@ -110,7 +130,8 @@ public void next() throws TidesDBException { /** * Moves the iterator to the previous entry. * - * @throws TidesDBException if the move fails + * @throws IllegalStateException if this iterator is freed + * @throws TidesDBException if the native prev operation fails */ public void prev() throws TidesDBException { checkNotFreed(); @@ -118,10 +139,11 @@ public void prev() throws TidesDBException { } /** - * Retrieves the current key from the iterator. + * Retrieves the key at the current iterator position. * * @return the current key - * @throws TidesDBException if the key cannot be retrieved + * @throws IllegalStateException if this iterator is freed + * @throws TidesDBException if the native key retrieval fails */ public byte[] key() throws TidesDBException { checkNotFreed(); @@ -129,10 +151,11 @@ public byte[] key() throws TidesDBException { } /** - * Retrieves the current value from the iterator. + * Retrieves the value at the current iterator position. * * @return the current value - * @throws TidesDBException if the value cannot be retrieved + * @throws IllegalStateException if this iterator is freed + * @throws TidesDBException if the native value retrieval fails */ public byte[] value() throws TidesDBException { checkNotFreed(); @@ -140,7 +163,10 @@ public byte[] value() throws TidesDBException { } /** - * Frees the iterator resources. + * Frees the iterator and releases all native resources. + * + *

This method is idempotent; subsequent calls are no-ops. After freeing, + * all operations except {@link #isValid()} throw {@link IllegalStateException}. */ public void free() { if (!freed && nativeHandle != 0) { @@ -151,7 +177,7 @@ public void free() { } /** - * Closes the iterator (same as free). + * Closes this iterator. Equivalent to {@link #free()}. */ @Override public void close() { diff --git a/src/main/java/com/tidesdb/Transaction.java b/src/main/java/com/tidesdb/Transaction.java index ef6c1e3..4a03478 100644 --- a/src/main/java/com/tidesdb/Transaction.java +++ b/src/main/java/com/tidesdb/Transaction.java @@ -21,8 +21,15 @@ import java.io.Closeable; /** - * Represents a transaction in TidesDB. - * Transactions provide atomic operations on the database. + * Represents a transaction in TidesDB. Transactions provide atomic + * operations on the database and implement {@link java.io.Closeable} for + * use with try-with-resources. + * + *

Close transactions before closing the owning {@link TidesDB} instance. + * After this transaction is freed, all operations except {@code close()} throw + * {@link IllegalStateException}. + * + *

This class is not guaranteed to be thread-safe. */ public class Transaction implements Closeable { @@ -40,11 +47,15 @@ public class Transaction implements Closeable { /** * Adds a key-value pair to the transaction. * - * @param cf the column family - * @param key the key - * @param value the value - * @param ttl Unix timestamp (seconds since epoch) for expiration, or -1 for no expiration - * @throws TidesDBException if the put fails + * @param cf the column family; must not be {@code null} + * @param key the key; must not be {@code null} or empty + * @param value the value; must not be {@code null} + * @param ttl expiration as seconds since the Unix epoch, or {@code -1} for + * no expiration + * @throws IllegalArgumentException if {@code cf} is {@code null}, {@code key} + * is {@code null} or empty, or {@code value} is {@code null} + * @throws IllegalStateException if this transaction is freed + * @throws TidesDBException if the native put fails */ public void put(ColumnFamily cf, byte[] key, byte[] value, long ttl) throws TidesDBException { checkNotFreed(); @@ -63,10 +74,15 @@ public void put(ColumnFamily cf, byte[] key, byte[] value, long ttl) throws Tide /** * Adds a key-value pair to the transaction with no expiration. * - * @param cf the column family - * @param key the key - * @param value the value - * @throws TidesDBException if the put fails + *

Equivalent to {@code put(cf, key, value, -1)}. + * + * @param cf the column family; must not be {@code null} + * @param key the key; must not be {@code null} or empty + * @param value the value; must not be {@code null} + * @throws IllegalArgumentException if {@code cf} is {@code null}, {@code key} + * is {@code null} or empty, or {@code value} is {@code null} + * @throws IllegalStateException if this transaction is freed + * @throws TidesDBException if the native put fails */ public void put(ColumnFamily cf, byte[] key, byte[] value) throws TidesDBException { put(cf, key, value, -1); @@ -75,10 +91,13 @@ public void put(ColumnFamily cf, byte[] key, byte[] value) throws TidesDBExcepti /** * Retrieves a value from the transaction. * - * @param cf the column family - * @param key the key - * @return the value, or null if not found - * @throws TidesDBException if the get fails + * @param cf the column family; must not be {@code null} + * @param key the key; must not be {@code null} or empty + * @return the value, or {@code null} if not found + * @throws IllegalArgumentException if {@code cf} is {@code null}, or + * {@code key} is {@code null} or empty + * @throws IllegalStateException if this transaction is freed + * @throws TidesDBException if the native get fails */ public byte[] get(ColumnFamily cf, byte[] key) throws TidesDBException { checkNotFreed(); @@ -94,9 +113,12 @@ public byte[] get(ColumnFamily cf, byte[] key) throws TidesDBException { /** * Removes a key-value pair from the transaction. * - * @param cf the column family - * @param key the key - * @throws TidesDBException if the delete fails + * @param cf the column family; must not be {@code null} + * @param key the key; must not be {@code null} or empty + * @throws IllegalArgumentException if {@code cf} is {@code null}, or + * {@code key} is {@code null} or empty + * @throws IllegalStateException if this transaction is freed + * @throws TidesDBException if the native delete fails */ public void delete(ColumnFamily cf, byte[] key) throws TidesDBException { checkNotFreed(); @@ -110,9 +132,10 @@ public void delete(ColumnFamily cf, byte[] key) throws TidesDBException { } /** - * Commits the transaction. + * Commits the transaction, making all pending operations durable. * - * @throws TidesDBException if the commit fails + * @throws IllegalStateException if this transaction is freed + * @throws TidesDBException if the native commit fails */ public void commit() throws TidesDBException { checkNotFreed(); @@ -120,9 +143,10 @@ public void commit() throws TidesDBException { } /** - * Rolls back the transaction. + * Rolls back all operations in the transaction. * - * @throws TidesDBException if the rollback fails + * @throws IllegalStateException if this transaction is freed + * @throws TidesDBException if the native rollback fails */ public void rollback() throws TidesDBException { checkNotFreed(); @@ -130,10 +154,12 @@ public void rollback() throws TidesDBException { } /** - * Creates a savepoint within the transaction. + * Creates a named savepoint within the transaction. * - * @param name the savepoint name - * @throws TidesDBException if the savepoint cannot be created + * @param name the savepoint name; must not be {@code null} or empty + * @throws IllegalArgumentException if {@code name} is {@code null} or empty + * @throws IllegalStateException if this transaction is freed + * @throws TidesDBException if the native savepoint creation fails */ public void savepoint(String name) throws TidesDBException { checkNotFreed(); @@ -144,10 +170,12 @@ public void savepoint(String name) throws TidesDBException { } /** - * Rolls back the transaction to a savepoint. + * Rolls back the transaction to a named savepoint. * - * @param name the savepoint name - * @throws TidesDBException if the rollback fails + * @param name the savepoint name; must not be {@code null} or empty + * @throws IllegalArgumentException if {@code name} is {@code null} or empty + * @throws IllegalStateException if this transaction is freed + * @throws TidesDBException if the native rollback fails */ public void rollbackToSavepoint(String name) throws TidesDBException { checkNotFreed(); @@ -158,10 +186,12 @@ public void rollbackToSavepoint(String name) throws TidesDBException { } /** - * Releases a savepoint without rolling back. + * Releases a named savepoint without rolling back. * - * @param name the savepoint name - * @throws TidesDBException if the release fails + * @param name the savepoint name; must not be {@code null} or empty + * @throws IllegalArgumentException if {@code name} is {@code null} or empty + * @throws IllegalStateException if this transaction is freed + * @throws TidesDBException if the native release fails */ public void releaseSavepoint(String name) throws TidesDBException { checkNotFreed(); @@ -172,11 +202,15 @@ public void releaseSavepoint(String name) throws TidesDBException { } /** - * Creates a new iterator for a column family within this transaction. + * Creates a new iterator for the given column family within this transaction. * - * @param cf the column family + *

Close the returned iterator before freeing this transaction. + * + * @param cf the column family; must not be {@code null} * @return a new iterator - * @throws TidesDBException if the iterator cannot be created + * @throws IllegalArgumentException if {@code cf} is {@code null} + * @throws IllegalStateException if this transaction is freed + * @throws TidesDBException if the native iterator cannot be created */ public TidesDBIterator newIterator(ColumnFamily cf) throws TidesDBException { checkNotFreed(); @@ -188,7 +222,10 @@ public TidesDBIterator newIterator(ColumnFamily cf) throws TidesDBException { } /** - * Frees the transaction resources. + * Frees the transaction and releases all native resources. + * + *

This method is idempotent; subsequent calls are no-ops. After freeing, + * all other operations on this instance throw {@link IllegalStateException}. */ public void free() { if (!freed && nativeHandle != 0) { @@ -199,7 +236,7 @@ public void free() { } /** - * Closes the transaction (same as free). + * Closes this transaction. Equivalent to {@link #free()}. */ @Override public void close() {