public ReadOnlyTransaction BeginReadOnlyTransaction() { var txn = TransactionImpl.Create(this, TransactionBeginFlags.ReadOnly); var rotxn = new ReadOnlyTransaction(txn); return(rotxn); }
public void Read(Action <ReadOnlyTransaction, object> readAction, object state) { using (var txn = TransactionImpl.Create(this, TransactionBeginFlags.ReadOnly)) { var rotxn = new ReadOnlyTransaction(txn); readAction(rotxn, state); } }
public MDB_stat GetStat() { using (var tx = TransactionImpl.Create(Environment, TransactionBeginFlags.ReadOnly)) { NativeMethods.AssertRead(NativeMethods.mdb_stat(tx.Handle, _handle, out var stat)); return(stat); } }
public T Read <T>(Func <ReadOnlyTransaction, object, T> readFunc, object state) { using (var txn = TransactionImpl.Create(this, TransactionBeginFlags.ReadOnly)) { var rotxn = new ReadOnlyTransaction(txn); return(readFunc(rotxn, state)); } }
internal void Renew(TransactionImpl txn) { if (!txn.IsReadOnly) { TransactionImpl.ThrowTransactionIsNotReadOnly(); } NativeMethods.AssertExecute(NativeMethods.mdb_cursor_renew(txn.Handle, _handle)); }
public Transaction BeginTransaction(TransactionBeginFlags flags = TransactionBeginFlags.ReadWrite) { if (((int)flags & (int)TransactionBeginFlags.ReadOnly) != 0) { ThrowShouldUseReadOnlyTxn(); } var impl = TransactionImpl.Create(this, flags); var txn = new Transaction(impl); return(txn); }
internal static CursorImpl Create(Database db, TransactionImpl txn, bool readOnly) { var c = CursorPool.Rent(); c._database = db; c._transaction = txn; c._isReadOnly = readOnly; NativeMethods.AssertExecute(NativeMethods.mdb_cursor_open(txn.Handle, db._handle, out IntPtr handle)); c._handle = handle; #if DEBUG Interlocked.Increment(ref txn._cursorCount); #endif return(c); }
protected void Dispose(bool disposing) { #if DEBUG Interlocked.Decrement(ref _transaction._cursorCount); #endif var isReadOnly = IsReadOnly; if (isReadOnly) { if (disposing) { if (_transaction.IsReadOnly) { var pooled = _database.ReadCursorPool.Return(this); if (pooled) { return; } } } else { #if DEBUG Trace.TraceWarning("Finalizing read cursor. Dispose it explicitly."); #endif } } else if (!disposing) { #if DEBUG Trace.TraceWarning("Finalizing write cursor. Dispose it explicitly."); #endif } NativeMethods.mdb_cursor_close(_handle); _handle = IntPtr.Zero; _database = null; _transaction = null; if (disposing) { CursorPool.Return(this); } }
private LMDBEnvironment(string directory, LMDBEnvironmentFlags openFlags = LMDBEnvironmentFlags.None, UnixAccessMode accessMode = UnixAccessMode.Default, bool disableWriterThread = false, bool disableReadTxnAutoreset = false) { NativeMethods.AssertExecute(NativeMethods.mdb_env_create(out var envHandle)); _handle = envHandle; _accessMode = accessMode; _disableReadTxnAutoreset = disableReadTxnAutoreset; _directory = directory; _openFlags = openFlags; try { CreateDirectoryIfMissing(); } catch { NativeMethods.mdb_env_close(envHandle); throw; } MaxDatabases = Config.DbEnvironment.DefaultMaxDatabases; // Writer Task // In the current process writes are serialized via the blocking queue // Accross processes, writes are synchronized via WriteTxnGate (TODO!) _cts = new CancellationTokenSource(); if (!disableWriterThread) { _writeQueue = new BlockingCollection <Delegates>(); var threadStart = new ThreadStart(() => { while (!_writeQueue.IsCompleted) { try { // BLOCKING var delegates = _writeQueue.Take(_cts.Token); var transactionImpl = TransactionImpl.Create(this, TransactionBeginFlags.ReadWrite); try { // TODO for some methods such as mbd_put we should have a C method // that begins/end txn automatically // we still need to pass call to it here, but we could avoid txn creation // and two P/Invokes var txn = new Transaction(transactionImpl); if (delegates.WriteFunction != null) { var res = delegates.WriteFunction(txn); delegates.Tcs?.SetResult(res); } else if (delegates.WriteAction != null) { delegates.WriteAction(txn); delegates.Tcs?.SetResult(null); } else { Environment.FailFast("Wrong writer thread setup"); } } catch (Exception e) { delegates.Tcs?.SetException(e); transactionImpl?.Abort(); } finally { transactionImpl?.Dispose(); } } catch (InvalidOperationException) { } } _writeTaskCompletion.SetResult(null); }); var writeThread = new Thread(threadStart) { Name = "LMDB Writer thread", IsBackground = true }; writeThread.Start(); } }
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 ReadOnlyTransaction(TransactionImpl txn) { _impl = txn; }
internal Transaction(TransactionImpl txn) { _impl = txn; }