Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions src/TidesDB/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,36 @@ public sealed class Config
/// </summary>
public ulong LogTruncationAt { get; init; } = 0;

/// <summary>
/// Enable unified memtable mode (default: false = per-CF memtables).
/// </summary>
public bool UnifiedMemtable { get; init; } = false;

/// <summary>
/// Unified memtable write buffer size in bytes (default: 0 = auto).
/// </summary>
public ulong UnifiedMemtableWriteBufferSize { get; init; } = 0;

/// <summary>
/// Skip list max level for unified memtable (default: 0 = 12).
/// </summary>
public int UnifiedMemtableSkipListMaxLevel { get; init; } = 0;

/// <summary>
/// Skip list probability for unified memtable (default: 0 = 0.25).
/// </summary>
public float UnifiedMemtableSkipListProbability { get; init; } = 0;

/// <summary>
/// Sync mode for unified WAL (default: None).
/// </summary>
public SyncMode UnifiedMemtableSyncMode { get; init; } = SyncMode.None;

/// <summary>
/// Sync interval for unified WAL in microseconds (default: 0).
/// </summary>
public ulong UnifiedMemtableSyncIntervalUs { get; init; } = 0;

/// <summary>
/// Creates a default configuration with the specified database path.
/// </summary>
Expand Down Expand Up @@ -185,6 +215,21 @@ public sealed class ColumnFamilyConfig
/// </summary>
public bool UseBtree { get; init; } = false;

/// <summary>
/// Target SSTable size in object store mode in bytes (default: 0 = auto/256MB).
/// </summary>
public ulong ObjectTargetFileSize { get; init; } = 0;

/// <summary>
/// Compact less aggressively in object store mode (default: false).
/// </summary>
public bool ObjectLazyCompaction { get; init; } = false;

/// <summary>
/// Download all inputs before merge in object store mode (default: true).
/// </summary>
public bool ObjectPrefetchCompaction { get; init; } = true;

/// <summary>
/// Creates a default column family configuration.
/// </summary>
Expand Down
3 changes: 2 additions & 1 deletion src/TidesDB/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,6 @@ public enum ErrorCode
MemoryLimit = -9,
InvalidDb = -10,
Unknown = -11,
Locked = -12
Locked = -12,
Readonly = -13
}
20 changes: 20 additions & 0 deletions src/TidesDB/Iterator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,26 @@ public byte[] Key()
return key;
}

/// <summary>
/// Gets both the current key and value in a single call.
/// More efficient than calling Key() and Value() separately.
/// </summary>
public (byte[] Key, byte[] Value) KeyValue()
{
ThrowIfDisposed();
var result = NativeMethods.tidesdb_iter_key_value(
_handle, out var keyPtr, out var keySize, out var valuePtr, out var valueSize);
TidesDBException.ThrowIfError(result, "failed to get key-value pair");

var key = new byte[(int)keySize];
Marshal.Copy(keyPtr, key, 0, (int)keySize);

var value = new byte[(int)valueSize];
Marshal.Copy(valuePtr, value, 0, (int)valueSize);

return (key, value);
}

/// <summary>
/// Gets the current value.
/// </summary>
Expand Down
7 changes: 7 additions & 0 deletions src/TidesDB/Native/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,20 @@ internal static partial class NativeMethods
[LibraryImport(LibraryName, EntryPoint = "tidesdb_iter_value")]
internal static partial int tidesdb_iter_value(nint iter, out nint value, out nuint valueSize);

[LibraryImport(LibraryName, EntryPoint = "tidesdb_iter_key_value")]
internal static partial int tidesdb_iter_key_value(nint iter, out nint key, out nuint keySize, out nint value, out nuint valueSize);

[LibraryImport(LibraryName, EntryPoint = "tidesdb_iter_free")]
internal static partial void tidesdb_iter_free(nint iter);

// Transaction reset
[LibraryImport(LibraryName, EntryPoint = "tidesdb_txn_reset")]
internal static partial int tidesdb_txn_reset(nint txn, int isolation);

// Column family delete by pointer
[LibraryImport(LibraryName, EntryPoint = "tidesdb_delete_column_family")]
internal static partial int tidesdb_delete_column_family(nint db, nint cf);

// Column family clone/rename operations
[LibraryImport(LibraryName, EntryPoint = "tidesdb_clone_column_family", StringMarshalling = StringMarshalling.Utf8)]
internal static partial int tidesdb_clone_column_family(nint db, string sourceName, string destName);
Expand Down
31 changes: 29 additions & 2 deletions src/TidesDB/Native/NativeStructs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,17 @@ internal struct NativeConfig
public int LogLevel;
public nuint BlockCacheSize;
public nuint MaxOpenSstables;
public nuint MaxMemoryUsage;
public int LogToFile;
public nuint LogTruncationAt;
public nuint MaxMemoryUsage;
public int UnifiedMemtable;
public nuint UnifiedMemtableWriteBufferSize;
public int UnifiedMemtableSkipListMaxLevel;
public float UnifiedMemtableSkipListProbability;
public int UnifiedMemtableSyncMode;
public ulong UnifiedMemtableSyncIntervalUs;
public nint ObjectStore;
public nint ObjectStoreConfig;
}

[StructLayout(LayoutKind.Sequential)]
Expand Down Expand Up @@ -62,6 +70,9 @@ internal unsafe struct NativeColumnFamilyConfig
public int UseBtree;
public nint CommitHookFn;
public nint CommitHookCtx;
public nuint ObjectTargetFileSize;
public int ObjectLazyCompaction;
public int ObjectPrefetchCompaction;
}

[StructLayout(LayoutKind.Sequential)]
Expand All @@ -82,12 +93,12 @@ internal struct NativeStats
public nuint MemtableSize;
public nint LevelSizes;
public nint LevelNumSstables;
public nint LevelKeyCounts;
public nint Config;
public ulong TotalKeys;
public ulong TotalDataSize;
public double AvgKeySize;
public double AvgValueSize;
public nint LevelKeyCounts;
public double ReadAmp;
public double HitRate;
public int UseBtree;
Expand Down Expand Up @@ -126,4 +137,20 @@ internal struct NativeDbStats
public long TxnMemoryBytes;
public nuint CompactionQueueSize;
public nuint FlushQueueSize;
public int UnifiedMemtableEnabled;
public long UnifiedMemtableBytes;
public int UnifiedImmutableCount;
public int UnifiedIsFlushing;
public uint UnifiedNextCfIndex;
public ulong UnifiedWalGeneration;
public int ObjectStoreEnabled;
public nint ObjectStoreConnector;
public nuint LocalCacheBytesUsed;
public nuint LocalCacheBytesMax;
public int LocalCacheNumFiles;
public ulong LastUploadedGeneration;
public nuint UploadQueueDepth;
public ulong TotalUploads;
public ulong TotalUploadFailures;
public int ReplicaMode;
}
80 changes: 80 additions & 0 deletions src/TidesDB/Stats.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,86 @@ public sealed class DbStats
/// Number of pending flush tasks in queue.
/// </summary>
public ulong FlushQueueSize { get; init; }

/// <summary>
/// Whether unified memtable mode is active.
/// </summary>
public bool UnifiedMemtableEnabled { get; init; }

/// <summary>
/// Bytes in unified active memtable.
/// </summary>
public long UnifiedMemtableBytes { get; init; }

/// <summary>
/// Number of unified immutable memtables.
/// </summary>
public int UnifiedImmutableCount { get; init; }

/// <summary>
/// Whether unified memtable is currently flushing/rotating.
/// </summary>
public bool UnifiedIsFlushing { get; init; }

/// <summary>
/// Next CF index to be assigned in unified mode.
/// </summary>
public uint UnifiedNextCfIndex { get; init; }

/// <summary>
/// Current unified WAL generation counter.
/// </summary>
public ulong UnifiedWalGeneration { get; init; }

/// <summary>
/// Whether object store mode is active.
/// </summary>
public bool ObjectStoreEnabled { get; init; }

/// <summary>
/// Connector name ("s3", "gcs", "fs", etc.), or null if not using object store.
/// </summary>
public string? ObjectStoreConnector { get; init; }

/// <summary>
/// Current local file cache usage in bytes.
/// </summary>
public ulong LocalCacheBytesUsed { get; init; }

/// <summary>
/// Configured maximum local cache size in bytes.
/// </summary>
public ulong LocalCacheBytesMax { get; init; }

/// <summary>
/// Number of files tracked in local cache.
/// </summary>
public int LocalCacheNumFiles { get; init; }

/// <summary>
/// Highest WAL generation confirmed uploaded.
/// </summary>
public ulong LastUploadedGeneration { get; init; }

/// <summary>
/// Number of pending upload jobs in the queue.
/// </summary>
public ulong UploadQueueDepth { get; init; }

/// <summary>
/// Lifetime count of objects uploaded to object store.
/// </summary>
public ulong TotalUploads { get; init; }

/// <summary>
/// Lifetime count of permanently failed uploads (after all retries).
/// </summary>
public ulong TotalUploadFailures { get; init; }

/// <summary>
/// Whether running in read-only replica mode.
/// </summary>
public bool ReplicaMode { get; init; }
}

/// <summary>
Expand Down
46 changes: 43 additions & 3 deletions src/TidesDB/TidesDB.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,17 @@ public static TidesDb Open(Config config)
LogLevel = (int)config.LogLevel,
BlockCacheSize = (nuint)config.BlockCacheSize,
MaxOpenSstables = (nuint)config.MaxOpenSstables,
MaxMemoryUsage = (nuint)config.MaxMemoryUsage,
LogToFile = config.LogToFile ? 1 : 0,
LogTruncationAt = (nuint)config.LogTruncationAt
LogTruncationAt = (nuint)config.LogTruncationAt,
MaxMemoryUsage = (nuint)config.MaxMemoryUsage,
UnifiedMemtable = config.UnifiedMemtable ? 1 : 0,
UnifiedMemtableWriteBufferSize = (nuint)config.UnifiedMemtableWriteBufferSize,
UnifiedMemtableSkipListMaxLevel = config.UnifiedMemtableSkipListMaxLevel,
UnifiedMemtableSkipListProbability = config.UnifiedMemtableSkipListProbability,
UnifiedMemtableSyncMode = (int)config.UnifiedMemtableSyncMode,
UnifiedMemtableSyncIntervalUs = config.UnifiedMemtableSyncIntervalUs,
ObjectStore = nint.Zero,
ObjectStoreConfig = nint.Zero
};

var result = NativeMethods.tidesdb_open(ref nativeConfig, out var dbHandle);
Expand Down Expand Up @@ -93,6 +101,18 @@ public void DropColumnFamily(string name)
TidesDBException.ThrowIfError(result, "failed to drop column family");
}

/// <summary>
/// Deletes a column family by pointer. Faster than DropColumnFamily when you already
/// hold a ColumnFamily handle, as it skips the name lookup.
/// </summary>
/// <param name="cf">The column family to delete.</param>
public void DeleteColumnFamily(ColumnFamily cf)
{
ThrowIfDisposed();
var result = NativeMethods.tidesdb_delete_column_family(_handle, cf.Handle);
TidesDBException.ThrowIfError(result, "failed to delete column family");
}

/// <summary>
/// Clones a column family, creating a complete copy with a new name.
/// </summary>
Expand Down Expand Up @@ -266,7 +286,24 @@ public DbStats GetDbStats()
GlobalSeq = nativeStats.GlobalSeq,
TxnMemoryBytes = nativeStats.TxnMemoryBytes,
CompactionQueueSize = (ulong)nativeStats.CompactionQueueSize,
FlushQueueSize = (ulong)nativeStats.FlushQueueSize
FlushQueueSize = (ulong)nativeStats.FlushQueueSize,
UnifiedMemtableEnabled = nativeStats.UnifiedMemtableEnabled != 0,
UnifiedMemtableBytes = nativeStats.UnifiedMemtableBytes,
UnifiedImmutableCount = nativeStats.UnifiedImmutableCount,
UnifiedIsFlushing = nativeStats.UnifiedIsFlushing != 0,
UnifiedNextCfIndex = nativeStats.UnifiedNextCfIndex,
UnifiedWalGeneration = nativeStats.UnifiedWalGeneration,
ObjectStoreEnabled = nativeStats.ObjectStoreEnabled != 0,
ObjectStoreConnector = nativeStats.ObjectStoreConnector != nint.Zero
? Marshal.PtrToStringAnsi(nativeStats.ObjectStoreConnector) : null,
LocalCacheBytesUsed = (ulong)nativeStats.LocalCacheBytesUsed,
LocalCacheBytesMax = (ulong)nativeStats.LocalCacheBytesMax,
LocalCacheNumFiles = nativeStats.LocalCacheNumFiles,
LastUploadedGeneration = nativeStats.LastUploadedGeneration,
UploadQueueDepth = (ulong)nativeStats.UploadQueueDepth,
TotalUploads = nativeStats.TotalUploads,
TotalUploadFailures = nativeStats.TotalUploadFailures,
ReplicaMode = nativeStats.ReplicaMode != 0
};
}

Expand Down Expand Up @@ -322,6 +359,9 @@ private static unsafe NativeColumnFamilyConfig CreateNativeColumnFamilyConfig(Co
UseBtree = config.UseBtree ? 1 : 0,
CommitHookFn = nint.Zero,
CommitHookCtx = nint.Zero,
ObjectTargetFileSize = (nuint)config.ObjectTargetFileSize,
ObjectLazyCompaction = config.ObjectLazyCompaction ? 1 : 0,
ObjectPrefetchCompaction = config.ObjectPrefetchCompaction ? 1 : 0,
ComparatorFnCached = nint.Zero,
ComparatorCtxCached = nint.Zero
};
Expand Down
2 changes: 1 addition & 1 deletion src/TidesDB/TidesDB.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<!-- Package metadata -->
<PackageId>TidesDB</PackageId>
<Version>0.4.5</Version>
<Version>0.4.6</Version>
<Authors>TidesDB</Authors>
<Company>TidesDB</Company>
<Description>Official C# bindings for TidesDB - A high-performance embedded key-value storage engine</Description>
Expand Down
1 change: 1 addition & 0 deletions src/TidesDB/TidesDBException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ private static string FormatMessage(ErrorCode errorCode, string? context)
ErrorCode.MemoryLimit => "memory limit exceeded",
ErrorCode.InvalidDb => "invalid database handle",
ErrorCode.Locked => "database is locked",
ErrorCode.Readonly => "database is read-only",
_ => "unknown error"
};

Expand Down
Loading
Loading