diff --git a/csharp/src/Native.Marshaled.cs b/csharp/src/Native.Marshaled.cs index 80b447f..1d003c1 100644 --- a/csharp/src/Native.Marshaled.cs +++ b/csharp/src/Native.Marshaled.cs @@ -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; @@ -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; } @@ -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; } @@ -290,32 +305,38 @@ public unsafe T 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 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((void*)resultPtr, (int)valueLength); + var span = new ReadOnlySpan((void*)valuePtr, (int)valueLength); try { return deserializer.Deserialize(span); } finally { - rocksdb_free(resultPtr); + rocksdb_pinnableslice_destroy(handle); } } @@ -328,34 +349,48 @@ public unsafe T 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) { - 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 ///