Esempio n. 1
0
 internal BlockMemoryPool(string path, uint maxLogSizeMb,
                          LMDBEnvironmentFlags envFlags,
                          Wpid ownerId,
                          int maxBufferLength     = RmDefaultMaxBufferLength,
                          int maxBuffersPerBucket = RmDefaultMaxBuffersPerBucket)
     : base(path, maxLogSizeMb, envFlags, ownerId, maxBufferLength, maxBuffersPerBucket, rentAlwaysClean: true)
 {
 }
Esempio n. 2
0
        // TODO this is all internal with very limited usage, but refactor

        public BufferRefAllocator(string directoryPath, LMDBEnvironmentFlags envFlags, Wpid wpid, int pageSize = 4096, long maxTotalSize = 64L * 1024 * 1024 * 1024, uint envSizeMb = 128)
        {
            _wpid         = wpid;
            _pageSize     = pageSize;
            _maxTotalSize = maxTotalSize;

            // TODO Log size to settings. Also handle MapFull later and reduce size.
            SetupEnv(directoryPath, envSizeMb, envFlags);
            InitDbs();
        }
Esempio n. 3
0
        internal unsafe SharedMemoryPool(string path, uint maxLogSizeMb,
                                         LMDBEnvironmentFlags envFlags,
                                         Wpid ownerId,
                                         int rmMaxBufferLength     = RmDefaultMaxBufferLength,
                                         int rmMaxBuffersPerBucket = RmDefaultMaxBuffersPerBucket, bool rentAlwaysClean = false)
            : base(
                (pool, bucketSize) =>
        {
            if (bucketSize > pool.MaxBufferSize)
            {
                BuffersThrowHelper.ThrowBadLength();
            }
            var smbp = (SharedMemoryPool)pool;

#pragma warning disable 618
            var sm = smbp.RentNative(bucketSize);

            Debug.Assert(!sm.IsDisposed);
            Debug.Assert(sm.ReferenceCount == 0);
            Debug.Assert(Unsafe.ReadUnaligned <uint>(sm.HeaderPointer) == HeaderFlags.IsOwned);
#pragma warning restore 618

            // TODO review if Releasing -> IsOwned should keep disposed state?
            // RMP calls CreateNew outside lock, so if we call RentNative only here
            // then it could return IsOwned without IsDisposed. But we a technically
            // inside the pool until this factory returns. Buffers from RentNative
            // should be unusable without explicit un-dispose action.

            // Set counter to zero
            sm.CounterRef &= ~AtomicCounter.CountMask;

            return(sm);
        },
                RmMinPoolBufferLength,
                Math.Max(RmDefaultMaxBufferLength, Math.Min(RmMaxPoolBufferLength, BitUtil.FindNextPositivePowerOfTwo(rmMaxBufferLength))),
                // from ProcCount to DefaultMaxNumberOfBuffersPerBucket x 2
                Math.Max(Environment.ProcessorCount, Math.Min(RmDefaultMaxBuffersPerBucket * 2, rmMaxBuffersPerBucket)),
                MaxBucketsToTry, rentAlwaysClean: rentAlwaysClean)
        {
            if (ownerId <= 0)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException("ownerId <= 0");
            }

            Directory.CreateDirectory(path);

            _bra     = new BufferRefAllocator(path, envFlags, ownerId, PageSize, maxLogSizeMb * 1024 * 1024L);
            _buckets = new SharedMemoryBuckets(Path.Combine(path, "buckets"), pageSize: PageSize, maxBucketIndex: BufferRef.MaxBucketIdx);

            StartMonitoringTask();
        }
Esempio n. 4
0
        private void SetupEnv(string path, uint mapSizeMb, LMDBEnvironmentFlags flags)
        {
            var env = LMDBEnvironment.Create(path, flags, disableAsync: true, disableReadTxnAutoreset: true);

            env.MapSize    = mapSizeMb * 1024L * 1024L;
            env.MaxReaders = 1024;
            env.Open();
            var deadReaders = env.ReaderCheck();

            if (deadReaders > 0)
            {
                Trace.TraceWarning($"Cleared {deadReaders} in SharedMemoryBufferPool");
            }
            _env = env;
        }
Esempio n. 5
0
        public StreamBlockManager(string path,
                                  LMDBEnvironmentFlags envFlags,
                                  Wpid wpid,
                                  IStreamBlockStorage blockStorage = null,
                                  long maxTotalSize = 1024L * 1024 * 1024 * 1024 * 1024,
                                  uint envSizeMb    = 1024) // 1Gb takes 2 MB of TLB, do not make it too large TODO calculate realistic required size that is derived from maxTotalSize when using smallest buffers
            : base(path, envFlags, wpid, PageSize, maxTotalSize, envSizeMb)
        {
            _blocksDb = Environment.OpenDatabase("_streamBlocks",
                                                 new DatabaseConfig(DbFlags.Create | DbFlags.DuplicatesSort | DbFlags.IntegerDuplicates | DbFlags.DuplicatesFixed)
            {
                DupSortPrefix = 64 * 64
            }
                                                 );

            _pidDb = Environment.OpenDatabase("_streamLogState", new DatabaseConfig(DbFlags.Create | DbFlags.IntegerKey));

            _buckets = new SharedMemoryBuckets(Path.Combine(path, "buckets"), pageSize: PageSize, maxBucketIndex: BufferRef.MaxBucketIdx);

            _blockStorage = blockStorage;
        }
        /// <summary>
        /// Creates a new instance of Environment.
        /// </summary>
        /// <param name="directory">Relative directory for storing database files.</param>
        /// <param name="openFlags">Database open options.</param>
        /// <param name="accessMode">Unix file access privelegies (optional). Only makes sense on unix operationg systems.</param>
        /// <param name="disableAsync">Disable dedicated writer thread and NO_TLS option.
        /// Fire-and-forget option for write transaction will throw.
        /// .NET async cannot be used in transaction body. True by default. </param>
        /// <param name="disableReadTxnAutoreset">Abort read-only transactions instead of resetting them. Should be true for multiple (a lot of) processes accessing the same env.</param>
        public static LMDBEnvironment Create(string directory,
                                             LMDBEnvironmentFlags openFlags = LMDBEnvironmentFlags.None,
                                             UnixAccessMode accessMode      = UnixAccessMode.Default,
                                             bool disableAsync = true, bool disableReadTxnAutoreset = false)
        {
#pragma warning disable 618
            openFlags = openFlags | LMDBEnvironmentFlags.NoTls;

#pragma warning restore 618

            // this is machine-local storage for each user.
            if (string.IsNullOrWhiteSpace(directory))
            {
                throw new ArgumentNullException(nameof(directory));
            }
            var env = _openEnvs.GetOrAdd(directory, (dir) => new LMDBEnvironment(dir, openFlags, accessMode, disableAsync, disableReadTxnAutoreset));
            if (env._openFlags != openFlags || env._accessMode != accessMode)
            {
                throw new InvalidOperationException("Environment is already open in this process with different flags and access mode.");
            }
            env._instanceCount++;
            return(env);
        }
        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. 8
0
 public static extern int mdb_env_open(EnvironmentHandle env, IntPtr path, LMDBEnvironmentFlags flags, int mode);
Esempio n. 9
0
 public static extern int mdb_env_open(IntPtr env, IntPtr path, LMDBEnvironmentFlags flags, UnixAccessMode mode);