init method
Initializes a new LMDB environment at the specified path with optional configuration and flags.
The dbPath parameter specifies where the database should be created or
opened.
If the directory doesn't exist, it will be created automatically.
The optional config parameter allows fine-tuning of the database
environment:
await db.init('/path/to/db',
config: LMDBInitConfig(
mapSize: 10 * 1024 * 1024, // 10 MB mapped to memory
maxDbs: 5, // Support up to 5 named databases
mode: "0644", // File permissions
)
);
The optional flags parameter enables specific LMDB features:
await db.init('/path/to/db',
flags: LMDBFlagSet()
..add(MDB_NOSUBDIR) // Use path as filename
..add(MDB_NOSYNC) // Don't sync to disk immediately
);
Common flag combinations are available as presets:
await db.init('/path/to/db', flags: LMDBFlagSet.readOnly);
await db.init('/path/to/db', flags: LMDBFlagSet.highPerformance);
If no config is provided, default values will be used:
- mapSize: Minimum allowed size (typically 10MB)
- maxDbs: 1 (single unnamed database)
- mode: "0664" (rw-rw-r--)
Throws StateError if:
- Database is already initialized (call close first)
- Database is closed (create a new instance)
Throws LMDBException if:
- Environment creation fails (insufficient permissions, invalid path)
- Map size setting fails (invalid size)
- Environment opening fails (file system issues, incompatible flags)
Example usage:
final db = LMDB();
// Basic initialization
await db.init('/path/to/db');
// With custom configuration
await db.init('/path/to/db',
config: LMDBInitConfig(mapSize: 1024 * 1024 * 1024), // 1GB
flags: LMDBFlagSet()..add(MDB_NOSUBDIR)
);
// Don't forget to close when done
db.close();
Implementation
Future<void> init(
String dbPath, {
LMDBInitConfig? config,
LMDBFlagSet? flags,
}) async {
if (_env != null) {
close();
}
final effectiveFlags = flags ?? LMDBFlagSet.defaultFlags;
final effectiveConfig = config ??
LMDBInitConfig(
mapSize: LMDBConfig.minMapSize,
maxDbs: _defaultMaxDbs,
mode: _defaultMode,
);
// Determine if we're in NOSUBDIR mode
if (effectiveFlags.contains(MDB_NOSUBDIR)) {
// For NOSUBDIR mode, ensure parent directory exists
final parentDir = Directory(path.dirname(dbPath));
if (!parentDir.existsSync()) {
parentDir.createSync(recursive: true);
}
} else {
// Normal mode: create directory if it doesn't exist
final dir = Directory(dbPath);
if (!dir.existsSync()) {
dir.createSync(recursive: true);
}
}
return _withAllocated<void, Pointer<MDB_env>>((envPtr) {
final result = _lib.mdb_env_create(envPtr);
if (result != 0) {
throw LMDBException('Failed to create environment', result);
}
_env = envPtr.value;
try {
final setSizeResult = _lib.mdb_env_set_mapsize(
env,
effectiveConfig.mapSize,
);
if (setSizeResult != 0) {
throw LMDBException('Failed to set map size', setSizeResult);
}
if (effectiveConfig.maxDbs > 1) {
final setDbsResult = _lib.mdb_env_set_maxdbs(
env,
effectiveConfig.maxDbs,
);
if (setDbsResult != 0) {
throw LMDBException('Failed to set max DBs', setDbsResult);
}
}
final pathPtr = dbPath.toNativeUtf8();
try {
final openResult = _lib.mdb_env_open(
env,
pathPtr.cast(),
effectiveFlags.value,
effectiveConfig.modeAsInt,
);
if (openResult != 0) {
throw LMDBException('Failed to open environment', openResult);
}
} finally {
calloc.free(pathPtr);
}
} catch (e) {
_lib.mdb_env_close(_env!);
_env = null;
rethrow;
}
}, calloc<Pointer<MDB_env>>());
}