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);
     }
 }
Esempio n. 3
0
 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));
     }
 }
Esempio n. 5
0
 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);
        }
Esempio n. 7
0
        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);
        }
Esempio n. 8
0
        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();
            }
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
 internal ReadOnlyTransaction(TransactionImpl txn)
 {
     _impl = txn;
 }
Esempio n. 12
0
 internal Transaction(TransactionImpl txn)
 {
     _impl = txn;
 }