Lindenii Project Forge
Login

hare-lmdb

Hare bindings for LMDB
Commit info
ID
1eb201800f5b063ab7bd9b86927ac37661b852e9
Author
Runxi Yu <me@runxiyu.org>
Author date
Fri, 14 Mar 2025 00:11:35 +0800
Committer
Runxi Yu <me@runxiyu.org>
Committer date
Fri, 14 Mar 2025 00:11:35 +0800
Actions
Fix nullable usage again
// Create a cursor handle.
//
// A cursor is associated with a specific transaction and database.
// A cursor cannot be used when its database handle is closed.  Nor
// when its transaction has ended, except with [[cursor_renew]].
//
// It can be discarded with [[cursor_close]].
//
// A cursor in a write-transaction can be closed before its transaction
// ends, and will otherwise be closed when its transaction ends.
//
// A cursor in a read-only transaction must be closed explicitly, before
// or after its transaction ends. It can be reused with
// [[cursor_renew]] before finally closing it.
//
// - txn: A transaction handle returned by [[txn_begin]]
// - dbi: A database handle returned by [[dbi_open]]
// - cursor: Address where the new [[cursor]] handle will be stored
// - return: EINVAL on failure and 0 on success.
export @symbol("mdb_cursor_open") fn cursor_open(txn: *txn, dbi: *dbi, cursor: nullable **cursor) int;
export @symbol("mdb_cursor_open") fn cursor_open(txn: *txn, dbi: *dbi, cursor: *nullable *cursor) int;

// Close a cursor handle.
//
// The cursor handle will be freed and must not be used again after this call.
// Its transaction must still be live if it is a write-transaction.
//
// - cursor: A cursor handle returned by [[cursor_open]]
export @symbol("mdb_cursor_close") fn cursor_close(cursor: *cursor) void;

// Retrieve by cursor.
//
// This function retrieves key/data pairs from the database. The address and length
// of the key are returned in the object to which key refers (except for the
// case of the [[SET]] option, in which the key object is unchanged), and
// the address and length of the data are returned in the object to which data
// refers.
//
// See [[get]] for restrictions on using the output values.
//
// Parameters:
// - cursor: A cursor handle returned by [[cursor_open]]
// - key: The key for a retrieved item
// - data: The data of a retrieved item
// - op: A cursor operation [[cursor_op]]
//
// Return value: A non-zero error value on failure and 0 on success.
// Some possible errors are:
// - [[NOTFOUND]] - no matching key found;
// - [[EINVAL]] - an invalid parameter was specified.
export @symbol("mdb_cursor_get") fn cursor_get(cursor: *cursor, key: *val, data: *val, op: cursor_op) int;


// Delete current key/data pair
// 
// This function deletes the key/data pair to which the cursor refers.
// This does not invalidate the cursor, so operations such as MDB_NEXT
// can still be used on it.
//
// Both MDB_NEXT and MDB_GET_CURRENT will return the same record after
// this operation.
//
// Parameters:
// - cursor: A cursor handle returned by [[cursor_open]]
// - flags: Options for this operation. This parameter
//   must be set to 0 or one of the values described here.
//
// Flags:
// - [[NODUPDATA]] - delete all of the data items for the current key. This flag
//   may only be specified if the database was opened with [[DUPSORT]].
//
// Return value: A non-zero error value on failure and 0 on success. Some
// possible errors are:
// - EACCES - an attempt was made to write in a read-only transaction.
// - EINVAL - an invalid parameter was specified.
// 
export @symbol("mdb_cursor_del") fn cursor_del(cursor: *cursor, flags: uint) int;
use types::c;

// Create an LMDB environment handle.
// 
// This function allocates memory for a [[env]] structure. To release
// the allocated memory and discard the handle, call [[env_close]].
// Before the handle may be used, it must be opened using [[env_open]].
// Various other options may also need to be set before opening the handle,
// e.g. [[env_set_mapsize]], [[env_set_maxreaders]], [[env_set_maxdbs]],
// depending on usage requirements.
//
// Parameters:
// - env: The address where the new handle will be stored
//
// Return value: A non-zero error value on failure and 0 on success.
export @symbol("mdb_env_create") fn env_create(env: nullable **env) int;
export @symbol("mdb_env_create") fn env_create(env: *nullable *env) int;

// Open an environment handle.
// 
// If this function fails, [[env_close]] must be called to discard the [[env]] handle.
// 
// Parameters:
// - env: An environment handle returned by [[env_create]]
// - path: The directory in which the database files reside. This
//   directory must already exist and be writable.
// - flags: Special options for this environment. This parameter
//   must be set to 0 or by bitwise OR'ing together one or more of the
//   values described here. Flags set by [[env_set_flags]] are also used.
// - mode: The UNIX permissions to set on created files and semaphores. This
//   parameter is ignored on Windows.
//
// - [[FIXEDMAP]]:
//		use a fixed address for the mmap region. This flag must be specified
//		when creating the environment, and is stored persistently in the environment.
//		If successful, the memory map will always reside at the same virtual address
//		and pointers used to reference data items in the database will be constant
//		across multiple invocations. This option may not always work, depending on
//		how the operating system has allocated memory to shared libraries and other uses.
//		The feature is highly experimental.
// - [[NOSUBDIR]]:
//		By default, LMDB creates its environment in a directory whose
//		pathname is given in path, and creates its data and lock files
//		under that directory. With this option, path is used as-is for
//		the database main data file. The database lock file is the path
//		with "-lock" appended.
// - [[RDONLY]]:
//		Open the environment in read-only mode. No write operations will be
//		allowed. LMDB will still modify the lock file - except on read-only
//		filesystems, where LMDB does not use locks.
// - [[WRITEMAP]]:
//		Use a writeable memory map unless MDB_RDONLY is set. This uses
//		fewer mallocs but loses protection from application bugs
//		like wild pointer writes and other bad updates into the database.
//		This may be slightly faster for DBs that fit entirely in RAM, but
//		is slower for DBs larger than RAM.
//		Incompatible with nested transactions.
//		Do not mix processes with and without MDB_WRITEMAP on the same
//		environment.  This can defeat durability (#mdb_env_sync etc).
// - [[NOMETASYNC]]:
//		Flush system buffers to disk only once per transaction, omit the
//		metadata flush. Defer that until the system flushes files to disk,
//		or next non-MDB_RDONLY commit or [[env_sync]]. This optimization
//		maintains database integrity, but a system crash may undo the last
//		committed transaction. I.e. it preserves the ACI (atomicity,
//		consistency, isolation) but not D (durability) database property.
//		This flag may be changed at any time using [[env_set_flags]].
// - [[NOSYNC]]:
//		Don't flush system buffers to disk when committing a transaction.
//		This optimization means a system crash can corrupt the database or
//		lose the last transactions if buffers are not yet flushed to disk.
//		The risk is governed by how often the system flushes dirty buffers
//		to disk and how often [[env_sync]] is called.  However, if the
//		filesystem preserves write order and the [[WRITEMAP]] flag is not
//		used, transactions exhibit ACI (atomicity, consistency, isolation)
//		properties and only lose D (durability).  I.e. database integrity
//		is maintained, but a system crash may undo the final transactions.
//		Note that ([[NOSYNC]] | [[WRITEMAP)]] leaves the system with no
//		hint for when to write transactions to disk, unless [[env_sync]]
//		is called. ([[MAPASYNC]] | [[WRITEMAP)]] may be preferable.
//		This flag may be changed at any time using [[env_set_flags]].
// - [[MAPASYNC]]:
//		When using [[WRITEMAP]], use asynchronous flushes to disk.
//		As with [[NOSYNC]], a system crash can then corrupt the
//		database or lose the last transactions. Calling [[env_sync]]
//		ensures on-disk database integrity until next commit.
//		This flag may be changed at any time using [[env_set_flags]].
// - [[NOTLS]]:
//		Don't use Thread-Local Storage. Tie reader locktable slots to
//		[[txn]] objects instead of to threads. I.e. [[txn_reset]] keeps
//		the slot reserved for the [[txn]] object. A thread may use parallel
//		read-only transactions. A read-only transaction may span threads if
//		the user synchronizes its use. Applications that multiplex many
//		user threads over individual OS threads need this option. Such an
//		application must also serialize the write transactions in an OS
//		thread, since LMDB's write locking is unaware of the user threads.
// - [[NOLOCK]]:
//		Don't do any locking. If concurrent access is anticipated, the
//		caller must manage all concurrency itself. For proper operation
//		the caller must enforce single-writer semantics, and must ensure
//		that no readers are using old transactions while a writer is
//		active. The simplest approach is to use an exclusive lock so that
//		no readers may be active at all when a writer begins.
// - [[NORDAHEAD]]:
//		Turn off readahead. Most operating systems perform readahead on
//		read requests by default. This option turns it off if the OS
//		supports it. Turning it off may help random read performance
//		when the DB is larger than RAM and system RAM is full.
//		The option is not implemented on Windows.
// - [[NOMEMINIT]]:
//		Don't initialize malloc'd memory before writing to unused spaces
//		in the data file. By default, memory for pages written to the data
//		file is obtained using malloc. While these pages may be reused in
//		subsequent transactions, freshly malloc'd pages will be initialized
//		to zeroes before use. This avoids persisting leftover data from other
//		code (that used the heap and subsequently freed the memory) into the
//		data file. Note that many other system libraries may allocate
//		and free memory from the heap for arbitrary uses. E.g., stdio may
//		use the heap for file I/O buffers. This initialization step has a
//		modest performance cost so some applications may want to disable
//		it using this flag. This option can be a problem for applications
//		which handle sensitive data like passwords, and it makes memory
//		checkers like Valgrind noisy. This flag is not needed with [[WRITEMAP]],
//		which writes directly to the mmap instead of using malloc for pages. The
//		initialization is also skipped if [[RESERVE]] is used; the
//		caller is expected to overwrite all of the memory that was
//		reserved in that case.
//		This flag may be changed at any time using [[env_set_flags]].
//
// Return value: A non-zero error value on failure and 0 on success. Some possible
// errors are:
// - [[VERSION_MISMATCH]] - the version of the LMDB library doesn't match the
//   version that created the database environment.
// - [[INVALID]] - the environment file headers are corrupted.
// - ENOENT - the directory specified by the path parameter doesn't exist.
// - EACCES - the user didn't have permission to access the environment files.
// - EAGAIN - the environment was locked by another process.
export @symbol("mdb_env_open") fn env_open(env: *env, path: const *c::char, flag: uint, mode: mode_t) int;

// Close the environment and release the memory map.
// 
// Only a single thread may call this function. All transactions, databases,
// and cursors must already be closed before calling this function. Attempts to
// use any such handles after calling this function will cause a SIGSEGV.
// The environment handle will be freed and must not be used again after this call.
//
// Parameters:
// - env: An environment handle returned by [[env_create]]
export @symbol("mdb_env_close") fn env_close(env: *env) void;

// Set the size of the memory map to use for this environment.
//
// The size should be a multiple of the OS page size. The default is
// 10485760 bytes. The size of the memory map is also the maximum size
// of the database. The value should be chosen as large as possible,
// to accommodate future growth of the database.
//
// This function should be called after [[env_create]] and before [[env_open]].
// It may be called at later times if no transactions are active in
// this process. Note that the library does not check for this condition,
// the caller must ensure it explicitly.
//
// The new size takes effect immediately for the current process but
// will not be persisted to any others until a write transaction has been
// committed by the current process. Also, only mapsize increases are
// persisted into the environment.
//
// If the mapsize is increased by another process, and data has grown
// beyond the range of the current mapsize, [[txn_begin]] will
// return [[MAP_RESIZED]]. This function may be called with a size
// of zero to adopt the new size.
//
// Any attempt to set a size smaller than the space already consumed
// by the environment will be silently changed to the current size of the used space.
//
// Parameters
// - env: An environment handle returned by [[env_create]]
// - size: The size in bytes
//
// Return value: A non-zero error value on failure and 0 on success. Some possible
// errors are:
// - EINVAL - an invalid parameter was specified, or the environment has
//   an active write transaction.
export @symbol("mdb_env_set_mapsize") fn env_set_mapsize(env: *env, size_: size) int;

// Set the maximum number of named databases for the environment.
//
// This function is only needed if multiple databases will be used in the
// environment. Simpler applications that use the environment as a single
// unnamed database can ignore this option.
//
// This function may only be called after [[env_create]] and before [[env_open]].
//
// Currently a moderate number of slots are cheap but a huge number gets
// expensive: 7-120 words per transaction, and every [[dbi_open]]
// does a linear search of the opened slots.
//
// Parameters
// - env: An environment handle returned by [[env_create]]
// - dbs: The maximum number of databases
//
// Return value: A non-zero error value on failure and 0 on success. Some possible
// errors are:
// - EINVAL - an invalid parameter was specified, or the environment is already open.
export @symbol("mdb_env_set_maxdbs") fn env_set_maxdbs(env: *env, dbs: dbi) int;
// Create a transaction for use with the environment.
// 
// The transaction handle may be discarded using [[txn_abort]] or [[txn_commit]].
//
// A transaction and its cursors must only be used by a single
// thread, and a thread may only have a single transaction at a time.
// If [[NOTLS]] is in use, this does not apply to read-only transactions.
//
// Cursors may not span transactions.
//
// Parameters
// - env: An environment handle returned by [[env_create]]
// - parent: If this parameter is non-NULL, the new transaction
//   will be a nested transaction, with the transaction indicated by parent
//   as its parent. Transactions may be nested to any level. A parent
//   transaction and its cursors may not issue any other operations than
//   mdb_txn_commit and mdb_txn_abort while it has active child transactions.
// - flags: Special options for this transaction. This parameter
//   must be set to 0 or by bitwise OR'ing together one or more of the
//   values described here.
// - txn: Address where the new [[txn]] handle will be stored
//
// Flags
// - [[MDB_RDONLY]]
//      	This transaction will not perform any write operations.
//
// Return value: A non-zero error value on failure and 0 on success. Some possible
// errors are:
// - [[PANIC]] - a fatal error occurred earlier and the environment
// -     must be shut down.
// - [[MAP_RESIZED]] - another process wrote data beyond this MDB_env's
// -     mapsize and this environment's map must be resized as well.
// -     See [[env_set_mapsize]].
// - [[READERS_FULL]] - a read-only transaction was requested and
// -     the reader lock table is full. See [[env_set_maxreaders]].
// - ENOMEM - out of memory.
export @symbol("mdb_txn_begin") fn txn_begin(env: *env, parent: *txn, flags: uint, txn: nullable **txn) int;
export @symbol("mdb_txn_begin") fn txn_begin(env: *env, parent: nullable *txn, flags: uint, txn: *nullable *txn) int;

// Commit all the operations of a transaction into the database.
// 
// The transaction handle is freed. It and its cursors must not be used
// again after this call, except with [[cursor_renew]].
//
// Parameters
// - txn: A transaction handle returned by [[txn_begin]]
//
// Return value: A non-zero error value on failure and 0 on success. Some possible
// errors are:
// - EINVAL - an invalid parameter was specified.
// - ENOSPC - no more disk space.
// - EIO - a low-level I/O error occurred while writing.
// - ENOMEM - out of memory.
export @symbol("mdb_txn_commit") fn txn_commit(txn: *txn) int;

// Abandon all the operations of the transaction instead of saving them.
// 
// The transaction handle is freed. It and its cursors must not be used
// again after this call, except with [[cursor_renew]].
//
// Parameters
// - txn: A transaction handle returned by [[txn_begin]]
export @symbol("mdb_txn_abort") fn txn_abort(txn: *txn) int;