Skip to content
Open
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
105 changes: 70 additions & 35 deletions csharp/src/Native.Marshaled.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ This is kept separate so that the lowest level imports can be kept as close as p
*/
using System;
using System.Collections.Generic;
#if NET6_0_OR_GREATER
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
#endif
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
Expand Down Expand Up @@ -225,27 +229,34 @@ public unsafe byte[] rocksdb_get(
ColumnFamilyHandle cf = null)
{
UIntPtr skLength = (UIntPtr)key.Length;
IntPtr resultPtr;
UIntPtr valueLength;
IntPtr handle;
fixed (byte* ptr = &MemoryMarshal.GetReference(key))
{
resultPtr = cf is null
? rocksdb_get(db, read_options, ptr, skLength, out valueLength, out errptr)
: rocksdb_get_cf(db, read_options, cf.Handle, ptr, skLength, out valueLength, out errptr);
handle = cf is null
? rocksdb_get_pinned(db, read_options, ptr, skLength, out errptr)
: rocksdb_get_pinned_cf(db, read_options, cf.Handle, ptr, skLength, out errptr);
}

if (errptr != IntPtr.Zero)
{
ThrowRocksDbException(errptr);
}

if (handle == IntPtr.Zero)
{
return null;
}

if (resultPtr == IntPtr.Zero)
IntPtr valuePtr = rocksdb_pinnableslice_value(handle, out UIntPtr valueLength);
if (valuePtr == IntPtr.Zero)
{
return null;
}

var result = new byte[(ulong)valueLength];
Marshal.Copy(resultPtr, result, 0, (int)valueLength);
rocksdb_free(resultPtr);
int length = (int)valueLength;
byte[] result = new byte[length];
Marshal.Copy(valuePtr, result, 0, length);
rocksdb_pinnableslice_destroy(handle);
return result;
}

Expand All @@ -257,26 +268,30 @@ public unsafe bool rocksdb_has_key(
ColumnFamilyHandle cf = null)
{
UIntPtr skLength = (UIntPtr)key.Length;
IntPtr resultPtr;
UIntPtr valueLength;
IntPtr handle;
fixed (byte* ptr = &MemoryMarshal.GetReference(key))
{
resultPtr = cf is null
? rocksdb_get(db, read_options, ptr, skLength, out valueLength, out errptr)
: rocksdb_get_cf(db, read_options, cf.Handle, ptr, skLength, out valueLength, out errptr);
handle = cf is null
? rocksdb_get_pinned(db, read_options, ptr, skLength, out errptr)
: rocksdb_get_pinned_cf(db, read_options, cf.Handle, ptr, skLength, out errptr);
}

if (errptr != IntPtr.Zero)
{
return false;
ThrowRocksDbException(errptr);
}

if (resultPtr == IntPtr.Zero)
if (handle == IntPtr.Zero)
{
return false;
}

rocksdb_free(resultPtr);
IntPtr valuePtr = rocksdb_pinnableslice_value(handle, out UIntPtr _);
if (valuePtr == IntPtr.Zero)
{
return false;
}

rocksdb_pinnableslice_destroy(handle);

return true;
}
Expand All @@ -290,32 +305,38 @@ public unsafe T rocksdb_get<T>(
ColumnFamilyHandle cf = null)
{
UIntPtr skLength = (UIntPtr)key.Length;
IntPtr resultPtr;
UIntPtr valueLength;
IntPtr handle;
fixed (byte* ptr = &MemoryMarshal.GetReference(key))
{
resultPtr = cf is null
? rocksdb_get(db, read_options, ptr, skLength, out valueLength, out errptr)
: rocksdb_get_cf(db, read_options, cf.Handle, ptr, skLength, out valueLength, out errptr);
handle = cf is null
? rocksdb_get_pinned(db, read_options, ptr, skLength, out errptr)
: rocksdb_get_pinned_cf(db, read_options, cf.Handle, ptr, skLength, out errptr);
}

if (errptr != IntPtr.Zero)
{
ThrowRocksDbException(errptr);
}

if (handle == IntPtr.Zero)
{
return default(T);
}

if (resultPtr == IntPtr.Zero)
IntPtr valuePtr = rocksdb_pinnableslice_value(handle, out UIntPtr valueLength);
if (valuePtr == IntPtr.Zero)
{
return default(T);
}

var span = new ReadOnlySpan<byte>((void*)resultPtr, (int)valueLength);
var span = new ReadOnlySpan<byte>((void*)valuePtr, (int)valueLength);
try
{
return deserializer.Deserialize(span);
}
finally
{
rocksdb_free(resultPtr);
rocksdb_pinnableslice_destroy(handle);
}
}

Expand All @@ -328,34 +349,48 @@ public unsafe T rocksdb_get<T>(
ColumnFamilyHandle cf = null)
{
UIntPtr skLength = (UIntPtr)key.Length;
IntPtr resultPtr;
UIntPtr valueLength;
IntPtr handle;
fixed (byte* ptr = &MemoryMarshal.GetReference(key))
{
resultPtr = cf is null
? rocksdb_get(db, read_options, ptr, skLength, out valueLength, out errptr)
: rocksdb_get_cf(db, read_options, cf.Handle, ptr, skLength, out valueLength, out errptr);
handle = cf is null
? rocksdb_get_pinned(db, read_options, ptr, skLength, out errptr)
: rocksdb_get_pinned_cf(db, read_options, cf.Handle, ptr, skLength, out errptr);
}

if (errptr != IntPtr.Zero)
{
return default(T);
ThrowRocksDbException(errptr);
}

if (resultPtr == IntPtr.Zero)
if (handle == IntPtr.Zero)
{
return default(T);
}

IntPtr valuePtr = rocksdb_pinnableslice_value(handle, out UIntPtr valueLength);
if (valuePtr == IntPtr.Zero)
{
return default(T);
}
try
{
using var stream = new UnmanagedMemoryStream((byte*)resultPtr, (long)valueLength);
using var stream = new UnmanagedMemoryStream((byte*)valuePtr, (long)valueLength);
return deserializer(stream);
}
finally
{
rocksdb_free(resultPtr);
rocksdb_pinnableslice_destroy(handle);
}
}

#if NET6_0_OR_GREATER
[DoesNotReturn]
[StackTraceHidden]
#endif
static unsafe void ThrowRocksDbException(nint errPtr)
{
throw new RocksDbException(errPtr);
}
#endif

/// <summary>
Expand Down