private void Dispose(bool disposing) { var isReadOnly = IsReadOnly; if (_state == TransactionState.Disposed) { if (disposing) { ThrowlAlreadyDisposed(); } else { return; } } _state = TransactionState.Disposed; if (isReadOnly) { if (disposing) { NativeMethods.mdb_txn_reset(_handle); _state = TransactionState.Reset; var pooled = _lmdbEnvironment.ReadTxnPool.Return(this); if (pooled) { Debug.Assert(_state == TransactionState.Reset); // set above return; } } else { #if DEBUG Trace.TraceWarning("Finalizing read transaction. Dispose it explicitly. " + StackTrace); #endif } _state = TransactionState.Disposed; NativeMethods.mdb_txn_abort(_handle); _handle = IntPtr.Zero; } else { if (disposing) { if (_state == TransactionState.Active) { NativeMethods.mdb_txn_abort(_handle); if (!LmdbEnvironment.AutoAbort) { ThrowDisposingActiveTransaction(); } } } else { if (_state == TransactionState.Active) { NativeMethods.mdb_txn_abort(_handle); FailFinalizingActiveTransaction(); } else { #if DEBUG Trace.TraceWarning("Finalizing finished write transaction. Dispose it explicitly. " + StackTrace); #endif } } _handle = IntPtr.Zero; } _lmdbEnvironment = null; #if DEBUG StackTrace = null; #endif if (disposing) { TxPool.Return(this); } }
internal Database(string name, TransactionImpl txn, DatabaseConfig config) { if (txn.IsReadOnly) { throw new InvalidOperationException("Cannot create a DB with RO transaction"); } if (txn == null) { throw new ArgumentNullException(nameof(txn)); } _config = config ?? throw new ArgumentNullException(nameof(config)); _name = name; _environment = txn.LmdbEnvironment; _environmentGcHandle = GCHandle.Alloc(_environment, GCHandleType.Normal); NativeMethods.AssertExecute(NativeMethods.mdb_dbi_open(txn.Handle, name, _config.OpenFlags, out var handle)); if (_config.CompareFunction != null) { NativeMethods.AssertExecute(NativeMethods.mdb_set_compare(txn.Handle, handle, _config.CompareFunction)); } if (_config.DupSortFunction != null) { NativeMethods.AssertExecute(NativeMethods.mdb_set_dupsort(txn.Handle, handle, _config.DupSortFunction)); } if (_config.DupSortPrefix > 0) { if (_config.DupSortPrefix == 64 * 64) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint64x64(txn.Handle, handle)); } else if (_config.DupSortPrefix == 128) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint128(txn.Handle, handle)); } else if (_config.DupSortPrefix == 96) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint96(txn.Handle, handle)); } else if (_config.DupSortPrefix == 80) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint80(txn.Handle, handle)); } else if (_config.DupSortPrefix == 64) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint64(txn.Handle, handle)); } else if (_config.DupSortPrefix == 48) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint48(txn.Handle, handle)); } else if (_config.DupSortPrefix == 32) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint32(txn.Handle, handle)); } else if (_config.DupSortPrefix == 16) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint16(txn.Handle, handle)); } else { throw new NotSupportedException("Rethink your design if you need this!"); } } _handle = handle; var poolSize = System.Environment.ProcessorCount * 2; ReadCursorPool = new LockedObjectPool <CursorImpl>(() => null, poolSize, false); }
internal static TransactionImpl Create(LMDBEnvironment lmdbEnvironment, TransactionBeginFlags beginFlags) { lmdbEnvironment.EnsureOpen(); TransactionImpl tx; // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags var isReadOnly = (beginFlags & TransactionBeginFlags.ReadOnly) == TransactionBeginFlags.ReadOnly; if (isReadOnly) { if ((tx = lmdbEnvironment.ReadTxnPool.Rent()) == null) { tx = TxPool.Rent(); tx._isReadOnly = true; if (tx._state != TransactionState.Disposed) { ThrowShoudBeDisposed(); } } else { Debug.Assert(tx._isReadOnly); Debug.Assert(tx._state == TransactionState.Reset); } if (tx.IsInvalid) { // create new handle NativeMethods.AssertExecute(NativeMethods.mdb_txn_begin( lmdbEnvironment._handle.Handle, IntPtr.Zero, beginFlags, out var handle)); tx.SetNewHandle(handle); } else { tx.Renew(); } } else { tx = TxPool.Rent(); tx._isReadOnly = false; NativeMethods.AssertExecute(NativeMethods.mdb_txn_begin( lmdbEnvironment._handle.Handle, IntPtr.Zero, beginFlags, out IntPtr handle)); tx._handle = handle; if (tx._state != TransactionState.Disposed) { ThrowShoudBeDisposed(); } } tx._lmdbEnvironment = lmdbEnvironment; tx._state = TransactionState.Active; #if DEBUG tx.StackTrace = Environment.StackTrace; #endif return(tx); }