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; }
/// <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); }
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(); } }
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);
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; }