public LightningEnvironment(string directory, EnvironmentOpenFlags openFlags, UnixAccessMode accessMode = UnixAccessMode.Default)
        {
            if (String.IsNullOrWhiteSpace(directory))
                throw new ArgumentException("Invalid directory name");

            IntPtr handle = default(IntPtr);
            Native.Execute(lib => lib.mdb_env_create(out handle));

            _shouldDispose = true;
            
            _handle = handle;
            _accessMode = accessMode;

            this.Directory = directory;
            _openFlags = openFlags;

            _mapSize = DefaultMapSize;
            _maxDbs = DefaultMaxDatabases;

            _openedDatabases = new ConcurrentDictionary<string, LightningDatabase>();
            _databasesForReuse = new HashSet<uint>();

            ConverterStore = new ConverterStore();
            var defaultConverters = new DefaultConverters();
            defaultConverters.RegisterDefault(this);
        }
        /// <summary>
        /// Open the environment.
        /// </summary>
        public void Open(EnvironmentOpenFlags openFlags = EnvironmentOpenFlags.None, UnixAccessMode accessMode = UnixAccessMode.Default)
        {
            if (IsOpened)
            {
                throw new InvalidOperationException("Environment is already opened.");
            }

            if (!openFlags.HasFlag(EnvironmentOpenFlags.NoSubDir) && !Directory.Exists(Path))
            {
                Directory.CreateDirectory(Path);
            }

            if (openFlags.HasFlag(EnvironmentOpenFlags.NoSubDir) && !Directory.Exists(System.IO.Path.GetDirectoryName(Path)))
            {
                Directory.CreateDirectory(System.IO.Path.GetDirectoryName(Path));
            }

            try
            {
                mdb_env_open(_handle, Path, openFlags, accessMode);
            }
            catch (Exception ex)
            {
                throw new LightningException($"Failed to open environment at path {Path}", ex);
            }

            IsOpened = true;
        }
Exemple #3
0
        /// <summary>
        /// Open the environment.
        /// </summary>
        public void Open(EnvironmentOpenFlags openFlags = EnvironmentOpenFlags.None, UnixAccessMode accessMode = UnixAccessMode.Default)
        {
            if (IsOpened)
            {
                throw new InvalidOperationException("Environment is already opened.");
            }

            if (!Directory.Exists(Path))
            {
                Directory.CreateDirectory(Path);
            }

            mdb_env_open(_handle, Path, openFlags, accessMode);

            IsOpened = true;
        }
        /// <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);
        }
Exemple #5
0
 public static int mdb_env_open(IntPtr env, string path, EnvironmentOpenFlags flags, UnixAccessMode mode)
 {
     return(check(LmdbMethods.mdb_env_open(env, path, flags, mode)));
 }
 int INativeLibraryFacade.mdb_env_open(IntPtr env, string path, EnvironmentOpenFlags flags, UnixAccessMode mode)
 {
     return FallbackLibraryFacade.mdb_env_open(env, path, flags, mode);
 }
 private static extern int mdb_env_open(IntPtr env, string path, EnvironmentOpenFlags flags, UnixAccessMode mode);
        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();
            }
        }
Exemple #9
0
 public static extern int mdb_env_open(EnvironmentHandle env, IntPtr path, LMDBEnvironmentFlags flags, UnixAccessMode mode);
 internal static extern int mdb_env_open(IntPtr env, string path, EnvironmentOpenFlags flags, UnixAccessMode mode);
Exemple #11
0
 public static int mdb_env_open(IntPtr env, string path, EnvironmentOpenFlags flags, UnixAccessMode mode)
 {
     return check(LmdbMethods.mdb_env_open(env, path, flags, mode));
 }
 int INativeLibraryFacade.mdb_env_open(IntPtr env, string path, EnvironmentOpenFlags flags, UnixAccessMode mode)
 {
     return(FallbackLibraryFacade.mdb_env_open(env, path, flags, mode));
 }
        /// <summary>
        /// Open the environment.
        /// </summary>
        public void Open(EnvironmentOpenFlags openFlags = EnvironmentOpenFlags.None, UnixAccessMode accessMode = UnixAccessMode.Default)
        {
            if(IsOpened)
                throw new InvalidOperationException("Environment is already opened.");

            if (!openFlags.HasFlag(EnvironmentOpenFlags.NoSubDir) && !Directory.Exists(Path))
                Directory.CreateDirectory(Path);

            try
            {
                mdb_env_open(_handle, Path, openFlags, accessMode);
            }
            catch(Exception ex)
            {
                throw new LightningException($"Failed to open environment at path {Path}", ex);
            }

            IsOpened = true;
        }
        /// <summary>
        /// Open the environment.
        /// </summary>
        public void Open(EnvironmentOpenFlags openFlags = EnvironmentOpenFlags.None, UnixAccessMode accessMode = UnixAccessMode.Default)
        {
            if(IsOpened)
                throw new InvalidOperationException("Environment is already opened.");

            if (!Directory.Exists(Path))
                Directory.CreateDirectory(Path);

            mdb_env_open(_handle, Path, openFlags, accessMode);

            IsOpened = true;
        }