Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make disposal behave nice 🙂 #77

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
30 changes: 28 additions & 2 deletions RocksDbSharp/RocksDb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
using System.Runtime.InteropServices;
using System.Text;
using Transitional;
// ReSharper disable EmptyGeneralCatchClause

namespace RocksDbSharp
{
public class RocksDb : IDisposable
{
bool disposed;

internal static ReadOptions DefaultReadOptions { get; } = new ReadOptions();
internal static OptionsHandle DefaultOptions { get; } = new DbOptions();
internal static WriteOptions DefaultWriteOptions { get; } = new WriteOptions();
Expand All @@ -29,13 +32,36 @@ private RocksDb(IntPtr handle, dynamic optionsReferences, dynamic cfOptionsRefs,
this.columnFamilies = columnFamilies;
}

~RocksDb()
{
ReleaseUnmanagedResources();
}

public void Dispose()
{
if (disposed) return;

try
{
ReleaseUnmanagedResources();
GC.SuppressFinalize(this);
}
finally
{
disposed = true;
}
}

void ReleaseUnmanagedResources()
{
if (columnFamilies != null)
{
foreach (var cfh in columnFamilies.Values)
{
cfh.Dispose();
}
}

Native.Instance.rocksdb_close(Handle);
}

Expand Down Expand Up @@ -168,7 +194,7 @@ public long Get(byte[] key, long keyLength, byte[] buffer, long offset, long len
}
}

public KeyValuePair<byte[],byte[]>[] MultiGet(byte[][] keys, ColumnFamilyHandle[] cf = null, ReadOptions readOptions = null)
public KeyValuePair<byte[], byte[]>[] MultiGet(byte[][] keys, ColumnFamilyHandle[] cf = null, ReadOptions readOptions = null)
{
return Native.Instance.rocksdb_multi_get(Handle, (readOptions ?? DefaultReadOptions).Handle, keys);
}
Expand Down Expand Up @@ -261,7 +287,7 @@ public void DropColumnFamily(string name)
Native.Instance.rocksdb_drop_column_family(Handle, cf.Handle);
columnFamilies.Remove(name);
}

public ColumnFamilyHandle GetDefaultColumnFamily()
{
return GetColumnFamily(ColumnFamilies.DefaultName);
Expand Down
44 changes: 44 additions & 0 deletions tests/RocksDbSharpTest/LifestyleTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.IO;
using RocksDbSharp;
using Xunit;
// ReSharper disable RedundantArgumentDefaultValue
// ReSharper disable ArgumentsStyleLiteral

namespace RocksDbSharpTest
{
public class LifestyleTest
{
[Fact]
public void DoubleDisposableDoesNotThrow()
{
var testdir = Path.Combine(Path.GetTempPath(), "lifestyle_test");
var testdb = Path.Combine(testdir, "main");
var path = Environment.ExpandEnvironmentVariables(testdb);

if (Directory.Exists(testdir))
{
Directory.Delete(testdir, recursive: true);
}

Directory.CreateDirectory(testdir);

var options = new DbOptions().SetCreateIfMissing(true).EnableStatistics();

var db = RocksDb.Open(options, path);

db.Dispose();

// throws AccessViolationException, which on my machine crashed the process so hard that XUnit coulnd't cope...
//
db.Dispose();
//
// got this in Event Viewer though:
//
// Application: dotnet.exe
// CoreCLR Version: 4.6.28619.1
// Description: The process was terminated due to an internal error in the .NET Runtime at IP 00007FFF39BC5AA3 (00007FFF39A20000) with exit code c0000005.
//
}
}
}