internal(3)
๐ internal(3) โ LMDB Internals ๐
okay bestie, this is the internal(3) page from the Library Functions Manual, and it's giving LMDB Internals. This is the backstage, the source-code group chat, the deep lore. No cap: every struct, macro, typedef and enum from this part is here, exact, no skips. โจ
โจ NAME โจ
internal - LMDB Internals
bestie, the name says it all. internal is about LMDB Internals. Periodt. ๐ฆ
๐ฆ SYNOPSIS ๐ฆ
okay so here's the whole internal map. Topics? Data structures? Macros? Typedefs? Enumerations? We have literally all of it. Buckle up, this is the main character energy of source docs. ๐
๐ Topics ๐
- ID List Management
- Compatibility Macros
- Debug Macros
- Reader Lock Table
- Page Flags
- Node Flags
- Transaction DB Flags
- Transaction Flags
- Cursor Flags
๐ง Data Structures ๐ง
struct MDB_pagestruct MDB_page2struct MDB_nodestruct MDB_dbstruct MDB_metaunion MDB_metabufstruct MDB_dbxstruct MDB_txnโ Opaque structure for a transaction handle.struct MDB_cursorโ Opaque structure for navigating through a database.struct MDB_xcursorstruct MDB_pgstatestruct MDB_envโ Opaque structure for a database environment.struct MDB_ntxnstruct MDB_namestruct mdb_copy
๐ฅ Macros ๐ฅ
bestie, this is the macro wall. Every single #define from this part, exactly as written. Do not touch the spacing, do not rename, do not "fix" โ it's iconic as is. ๐ญ
#define LOCK_MUTEX(rc, env, mutex)
#define mdb_mutex_failed(env, mutex, rc)
#define MDB_DSYNC O_SYNC
#define MDB_FDATASYNC fdatasync
#define MDB_MSYNC(addr, len, flags)
#define MS_SYNC 1
#define MS_ASYNC 0
#define MAX_PAGESIZE (PAGEBASE ? 0x10000 : 0x8000)
#define MDB_MINKEYS 2
#define MDB_MAGIC 0xBEEFC0DE
#define MDB_DATA_VERSION ((MDB_DEVEL) ? 999 : 1)
#define MDB_LOCK_VERSION 1
#define MDB_MAXKEYSIZE ((MDB_DEVEL) ? 0 : 511)
#define ENV_MAXKEY(env)
#define MAXDATASIZE 0xffffffffUL
#define DKBUF
#define DDBUF
#define DKEY(x)
#define P_INVALID (~(pgno_t)0)
#define F_ISSET(w, f)
#define EVEN(n)
#define DEFAULT_MAPSIZE 1048576
#define MP_PGNO(p)
#define MP_PAD(p)
#define MP_FLAGS(p)
#define MP_LOWER(p)
#define MP_UPPER(p)
#define MP_PTRS(p)
#define PAGEHDRSZ ((unsigned) offsetof(MDB_page, mp_ptrs))
#define METADATA(p)
#define PAGEBASE ((MDB_DEVEL) ? PAGEHDRSZ : 0)
#define NUMKEYS(p)
#define SIZELEFT(p)
#define PAGEFILL(env, p)
#define FILL_THRESHOLD 250
#define IS_LEAF(p)
#define IS_LEAF2(p)
#define IS_BRANCH(p)
#define IS_OVERFLOW(p)
#define IS_SUBP(p)
#define OVPAGES(size, psize)
#define NEXT_LOOSE_PAGE(p)
#define NODESIZE offsetof(MDB_node, mn_data)
#define PGNO_TOPWORD ((pgno_t)-1 > 0xffffffffu ? 32 : 0)
#define INDXSIZE(k)
#define LEAFSIZE(k, d)
#define NODEPTR(p, i)
#define NODEKEY(node)
#define NODEDATA(node)
#define NODEPGNO(node)
#define SETPGNO(node, pgno)
#define NODEDSZ(node)
#define SETDSZ(node, size)
#define NODEKSZ(node)
#define COPY_PGNO(dst, src)
#define LEAF2KEY(p, i, ks)
#define MDB_GET_KEY(node, keyptr)
#define MDB_GET_KEY2(node, key)
#define MDB_VALID 0x8000
#define PERSISTENT_FLAGS (0xffff & ~(MDB_VALID))
#define VALID_FLAGS
#define FREE_DBI 0
#define MAIN_DBI 1
#define CORE_DBS 2
#define NUM_METAS 2
#define CURSOR_STACK 32
#define XCURSOR_INITED(mc)
#define XCURSOR_REFRESH(mc, top, mp)
#define MDB_COMMIT_PAGES 64
#define MAX_WRITE (0x40000000U >> (sizeof(ssize_t) == 4))
#define TXN_DBI_EXIST(txn, dbi, validity)
#define TXN_DBI_CHANGED(txn, dbi)
#define MDB_END_NAMES
#define MDB_END_OPMASK 0x0F
#define MDB_END_UPDATE 0x10
#define MDB_END_FREE 0x20
#define MDB_END_SLOT MDB_NOTLS
#define MDB_PS_MODIFY 1
#define MDB_PS_ROOTONLY 2
#define MDB_PS_FIRST 4
#define MDB_PS_LAST 8
#define MDB_SPLIT_REPLACE MDB_APPENDDUP
#define mdb_env_close0(env, excl)
#define mdb_cmp_clong mdb_cmp_cint
#define mdb_cassert(mc, expr)
#define mdb_tassert(txn, expr)
#define mdb_eassert(env, expr)
#define mdb_assert0(env, expr, expr_txt)
#define MDB_NAME(str)
#define mdb_name_cpy strcpy
#define MDB_SUFFLEN 9
#define mdb_fname_destroy(fname)
#define MDB_CLOEXEC 0
#define CHANGEABLE
(MDB_NOSYNC|MDB_NOMETASYNC|MDB_MAPASYNC|MDB_NOMEMINIT)
#define CHANGELESS
#define MDB_NOSPILL 0x8000
#define WITH_CURSOR_TRACKING(mn, act)
#define MDB_WBUF (1024*1024)
#define MDB_EOF 0x10
oh and the three macros that came with descriptions in the original? MAX_PAGESIZE is the maximum size of a database page. MDB_MAXKEYSIZE is the max size of a key we can write, or 0 for computed max. MAXDATASIZE is the maximum size of a data item. Slay. ๐
๐ Typedefs ๐
these are the type aliases, no cap:
typedef MDB_ID pgno_t
typedef MDB_ID txnid_t
typedef uint16_t indx_t
typedef char mdb_nchar_t
๐ Enumerations ๐
and finally the enums, bestie. Look at those values, look at that formatting, it's giving compiler-core realness. ๐ง
enum { MDB_END_COMMITTED, MDB_END_EMPTY_COMMIT, MDB_END_ABORT,
MDB_END_RESET, MDB_END_RESET_TMP, MDB_END_FAIL_BEGIN,
MDB_END_FAIL_BEGINCHILD }
enum Pidlock_op { Pidset = F_SETLK, Pidcheck = F_GETLK }
enum mdb_fopen_type { MDB_O_RDONLY = O_RDONLY, MDB_O_RDWR = O_RDWR
|O_CREAT, MDB_O_META = O_WRONLY|MDB_DSYNC |MDB_CLOEXEC, MDB_O_COPY =
O_WRONLY|O_CREAT|O_EXCL|MDB_CLOEXEC, MDB_O_MASK =
MDB_O_RDWR|MDB_CLOEXEC | MDB_O_RDONLY|MDB_O_META|MDB_O_COPY,
MDB_O_LOCKS = MDB_O_RDWR|MDB_CLOEXEC | ((MDB_O_MASK+1) &
~MDB_O_MASK) }
โจ Functions โจ
okay bestie, THIS is the list. like, the whole crew. some of these are public API (they get a little blurb), and some are static internals where the original page just... doesn't say anything, so what you get from me is the signature and my love ๐ซถ not me being shady, that's genuinely all there is.
static int mdb_page_alloc (MDB_cursor *mc, int num, MDB_page **mp)โ internals only, no blurb on this one ๐static int mdb_page_new (MDB_cursor *mc, uint32_t flags, int num, MDB_page **mp)โ backstage crew, no description given โจstatic int mdb_page_touch (MDB_cursor *mc)โ static helper, just vibes here ๐static void mdb_txn_end (MDB_txn *txn, unsigned mode)โ internal, no blurb ๐ธstatic int mdb_page_get (MDB_cursor *mc, pgno_t pgno, MDB_page **mp, int *lvl)โ private business ๐static int mdb_page_search_root (MDB_cursor *mc, MDB_val *key, int modify)โ internal, nothing to add ๐static int mdb_page_search (MDB_cursor *mc, MDB_val *key, int flags)โ static, no description ๐static int mdb_page_merge (MDB_cursor *csrc, MDB_cursor *cdst)โ internals, keeping it mysterious ๐static int mdb_page_split (MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno, unsigned int nflags)โ static helper, no blurb ๐ฆstatic int mdb_env_read_header (MDB_env *env, MDB_meta *meta)โ internal only โจstatic MDB_meta * mdb_env_pick_meta (const MDB_env *env)โ backstage, no description ๐ธstatic int mdb_env_write_meta (MDB_txn *txn)โ statics stay mysterious ๐static void mdb_env_close0 (MDB_env *env, int excl)โ internal, that's all we've got ๐ซถstatic MDB_node * mdb_node_search (MDB_cursor *mc, MDB_val *key, int *exactp)โ private, no blurb ๐static int mdb_node_add (MDB_cursor *mc, indx_t indx, MDB_val *key, MDB_val *data, pgno_t pgno, unsigned int flags)โ internals ๐static void mdb_node_del (MDB_cursor *mc, int ksize)โ no description here, bestie ๐ญstatic void mdb_node_shrink (MDB_page *mp, indx_t indx)โ static, so, y'know ๐static int mdb_node_move (MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)โ behind-the-scenes โจstatic int mdb_node_read (MDB_cursor *mc, MDB_node *leaf, MDB_val *data)โ internal, no blurb ๐ฆstatic size_t mdb_leaf_size (MDB_env *env, MDB_val *key, MDB_val *data)โ internals ๐static size_t mdb_branch_size (MDB_env *env, MDB_val *key)โ static helper, nothing else ๐ธstatic int mdb_rebalance (MDB_cursor *mc)โ private, no description ๐static int mdb_update_key (MDB_cursor *mc, MDB_val *key)โ internals only ๐static void mdb_cursor_pop (MDB_cursor *mc)โ no blurb, just the signature ๐static int mdb_cursor_push (MDB_cursor *mc, MDB_page *mp)โ static, off-limits ๐static int _mdb_cursor_del (MDB_cursor *mc, unsigned int flags)โ internal, nothing to add ๐static int _mdb_cursor_put (MDB_cursor *mc, MDB_val *key, MDB_val *data, unsigned int flags)โ internals โจstatic int mdb_cursor_del0 (MDB_cursor *mc)โ backstage crew ๐static int mdb_del0 (MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned flags)โ no description given ๐static int mdb_cursor_sibling (MDB_cursor *mc, int move_right)โ static helper, that's it ๐ซถstatic int mdb_cursor_next (MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)โ internal only ๐ธstatic int mdb_cursor_prev (MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)โ private business ๐static int mdb_cursor_set (MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op, int *exactp)โ internals, no blurb ๐static int mdb_cursor_first (MDB_cursor *mc, MDB_val *key, MDB_val *data)โ static, mysterious ๐static int mdb_cursor_last (MDB_cursor *mc, MDB_val *key, MDB_val *data)โ no description here ๐static void mdb_cursor_init (MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx)โ internals โจstatic void mdb_xcursor_init0 (MDB_cursor *mc)โ backstage ๐static void mdb_xcursor_init1 (MDB_cursor *mc, MDB_node *node)โ static helper, nothing else ๐ซถstatic void mdb_xcursor_init2 (MDB_cursor *mc, MDB_xcursor *src_mx, int force)โ internal only ๐static int mdb_drop0 (MDB_cursor *mc, int subs)โ no blurb ๐ธstatic void mdb_default_cmp (MDB_txn *txn, MDB_dbi dbi)โ private ๐static int mdb_reader_check0 (MDB_env *env, int rlocked, int *dead)โ internals, that's all ๐char *ESECT mdb_version (int *major, int *minor, int *patch)โ hands you the LMDB library version info, bestie ๐ that's literally its whole job.char * mdb_strerror (int err)โ you give it an error code, it gives you back a string that describes that error. translating for the group chat โจstatic void ESECT mdb_assert_fail (MDB_env *env, const char *expr_txt, const char *func, const char *file, int line)โ internal, no blurb ๐int mdb_cmp (MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b)โ compares two data items according to a particular database ๐ iconic.int mdb_dcmp (MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b)โ also compares two data items according to a particular database. yes it's the same sentence, no I'm not messing with you ๐ซถstatic MDB_page * mdb_page_malloc (MDB_txn *txn, unsigned num)โ internals ๐ธstatic void mdb_page_free (MDB_env *env, MDB_page *mp)โ static, no description ๐static void mdb_dpage_free (MDB_env *env, MDB_page *dp)โ backstage ๐static void mdb_dlist_free (MDB_txn *txn)โ internals only ๐static int mdb_page_loose (MDB_cursor *mc, MDB_page *mp)โ no blurb ๐static int mdb_pages_xkeep (MDB_cursor *mc, unsigned pflags, int all)โ private business โจstatic int mdb_page_flush (MDB_txn *txn, int keep)โ internal ๐static int mdb_page_spill (MDB_cursor *m0, MDB_val *key, MDB_val *data)โ static helper, that's it ๐static txnid_t mdb_find_oldest (MDB_txn *txn)โ internals ๐ธstatic void mdb_page_dirty (MDB_txn *txn, MDB_page *mp)โ no description given ๐static void mdb_page_copy (MDB_page *dst, MDB_page *src, unsigned int psize)โ backstage crew ๐static int mdb_page_unspill (MDB_txn *txn, MDB_page *mp, MDB_page **ret)โ internal only ๐ซถint mdb_env_sync (MDB_env *env, int force)โ flushes the data buffers to disk. actually pushing the vibes onto the drive fr fr ๐พโจstatic int mdb_cursor_shadow (MDB_txn *src, MDB_txn *dst)โ internals ๐static void mdb_cursors_close (MDB_txn *txn, unsigned merge)โ static, no blurb ๐static int mdb_reader_pid (MDB_env *env, enum Pidlock_op op, MDB_PID_T pid)โ private ๐ธstatic int mdb_txn_renew0 (MDB_txn *txn)โ internals, keeping it lowkey ๐int mdb_txn_renew (MDB_txn *txn)โ renews a read-only transaction ๐ periodt.int mdb_txn_begin (MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)โ creates a transaction for use with the environment. the main character energy of this list, honestly ๐MDB_env * mdb_txn_env (MDB_txn *txn)โ returns the transaction'sMDB_env๐size_t mdb_txn_id (MDB_txn *txn)โ returns the transaction's ID ๐ขstatic void mdb_dbis_update (MDB_txn *txn, int keep)โ static internals ๐void mdb_txn_reset (MDB_txn *txn)โ resets a read-only transaction ๐static void _mdb_txn_abort (MDB_txn *txn)โ internal, no blurb ๐void mdb_txn_abort (MDB_txn *txn)โ abandons ALL the operations of the transaction instead of saving them. like closing the app without hitting save, on purpose ๐ญ bye bestie.static int mdb_freelist_save (MDB_txn *txn)โ backstage ๐ธstatic int _mdb_txn_commit (MDB_txn *txn)โ internals ๐int mdb_txn_commit (MDB_txn *txn)โ commits all the operations of a transaction into the database. the "post it" button ๐static void ESECT mdb_env_init_meta0 (MDB_env *env, MDB_meta *meta)โ static, no description ๐static int ESECT mdb_env_init_meta (MDB_env *env, MDB_meta *meta)โ internals โจint ESECT mdb_env_create (MDB_env **env)โ creates an LMDB environment handle. your blank canvas, bestie ๐จstatic int ESECT mdb_env_map (MDB_env *env, void *addr)โ internal only ๐int ESECT mdb_env_set_mapsize (MDB_env *env, size_t size)โ sets the size of the memory map to use for this environment ๐int ESECT mdb_env_set_maxdbs (MDB_env *env, MDB_dbi dbs)โ sets the max number of named databases for the environment ๐๏ธint ESECT mdb_env_set_maxreaders (MDB_env *env, unsigned int readers)โ sets the max number of threads/reader slots for the environment ๐งตint ESECT mdb_env_get_maxreaders (MDB_env *env, unsigned int *readers)โ gets the max number of threads/reader slots for the environment ๐งต๐static int ESECT mdb_fsize (HANDLE fd, size_t *size)โ backstage ๐ซถstatic int ESECT mdb_fname_init (const char *path, unsigned envflags, MDB_name *fname)โ internals, no blurb ๐ธstatic int ESECT mdb_fopen (const MDB_env *env, MDB_name *fname, enum mdb_fopen_type which, mdb_mode_t mode, HANDLE *res)โ static helper ๐static int ESECT mdb_env_open2 (MDB_env *env)โ private business ๐static void mdb_env_reader_dest (void *ptr)โ no description here โจstatic int ESECT mdb_env_share_locks (MDB_env *env, int *excl)โ internals ๐static int ESECT mdb_env_excl_lock (MDB_env *env, int *excl)โ static, mysterious ๐static int ESECT mdb_env_setup_locks (MDB_env *env, MDB_name *fname, int mode, int *excl)โ internals only ๐int ESECT mdb_env_open (MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode)โ opens an environment handle ๐ชโจvoid ESECT mdb_env_close (MDB_env *env)โ closes the environment AND releases the memory map. closing time, you don't gotta go home but you gotta get out of here ๐static int mdb_cmp_long (const MDB_val *a, const MDB_val *b)โ static comparer, no blurb ๐ธstatic int mdb_cmp_int (const MDB_val *a, const MDB_val *b)โ internals ๐static int mdb_cmp_cint (const MDB_val *a, const MDB_val *b)โ backstage ๐static int mdb_cmp_memn (const MDB_val *a, const MDB_val *b)โ static โจstatic int mdb_cmp_memnr (const MDB_val *a, const MDB_val *b)โ no description given ๐static int mdb_page_search_lowest (MDB_cursor *mc)โ internal only ๐ซถstatic int mdb_ovpage_free (MDB_cursor *mc, MDB_page *mp)โ internals ๐int mdb_get (MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data)โ gets items out of a database. the little grabby hands ๐ซด๐int mdb_cursor_get (MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)โ retrieves by cursor ๐ฑ๏ธโจstatic int mdb_cursor_touch (MDB_cursor *mc)โ static, no blurb ๐ธint mdb_cursor_put (MDB_cursor *mc, MDB_val *key, MDB_val *data, unsigned int flags)โ stores by cursor ๐ฅint mdb_cursor_del (MDB_cursor *mc, unsigned int flags)โ deletes the current key/data pair. gone, reduced to atoms ๐int mdb_cursor_open (MDB_txn *txn, MDB_dbi dbi, MDB_cursor **ret)โ creates a cursor handle ๐int mdb_cursor_renew (MDB_txn *txn, MDB_cursor *mc)โ renews a cursor handle ๐int mdb_cursor_count (MDB_cursor *mc, size_t *countp)โ gives you the count of duplicates for the current key ๐ขvoid mdb_cursor_close (MDB_cursor *mc)โ closes a cursor handle ๐MDB_txn * mdb_cursor_txn (MDB_cursor *mc)โ returns the cursor's transaction handle ๐MDB_dbi mdb_cursor_dbi (MDB_cursor *mc)โ returns the cursor's database handle ๐๏ธstatic void mdb_cursor_copy (const MDB_cursor *csrc, MDB_cursor *cdst)โ internals, no blurb ๐int mdb_del (MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data)โ deletes items from a database ๐๏ธint mdb_put (MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned int flags)โ stores items into a database ๐ฅโจstatic THREAD_RET ESECT CALL_CONV mdb_env_copythr (void *arg)โ thread internals, no blurb ๐งตstatic int ESECT mdb_env_cthr_toggle (mdb_copy *my, int adjust)โ backstage ๐ธstatic int ESECT mdb_env_cwalk (mdb_copy *my, pgno_t *pg, int flags)โ static, no description ๐static int ESECT mdb_env_copyfd1 (MDB_env *env, HANDLE fd)โ internals ๐static int ESECT mdb_env_copyfd0 (MDB_env *env, HANDLE fd)โ private โจint ESECT mdb_env_copyfd2 (MDB_env *env, HANDLE fd, unsigned int flags)โ no blurb, just the signature ๐int ESECT mdb_env_copyfd (MDB_env *env, HANDLE fd)โ same, no description ๐ซถint ESECT mdb_env_copy2 (MDB_env *env, const char *path, unsigned int flags)โ copies an LMDB environment to the specified path, with options ๐ fancy.int ESECT mdb_env_copy (MDB_env *env, const char *path)โ copies an LMDB environment to the specified path ๐int ESECT mdb_env_set_flags (MDB_env *env, unsigned int flag, int onoff)โ sets environment flags ๐ฉint ESECT mdb_env_get_flags (MDB_env *env, unsigned int *arg)โ gets environment flags ๐ฉ๐int ESECT mdb_env_set_userctx (MDB_env *env, void *ctx)โ sets application information associated with theMDB_env๐void *ESECT mdb_env_get_userctx (MDB_env *env)โ gets the application information associated with theMDB_env๐๐int ESECT mdb_env_set_assert (MDB_env *env, MDB_assert_func *func)โ internal, no blurb โจint ESECT mdb_env_get_path (MDB_env *env, const char **arg)โ returns the path that was used inmdb_env_open()๐ค๏ธint ESECT mdb_env_get_fd (MDB_env *env, mdb_filehandle_t *arg)โ returns the filedescriptor for the given environment ๐static int ESECT mdb_stat0 (MDB_env *env, MDB_db *db, MDB_stat *arg)โ internals ๐ธint ESECT mdb_env_stat (MDB_env *env, MDB_stat *arg)โ returns statistics about the LMDB environment ๐int ESECT mdb_env_info (MDB_env *env, MDB_envinfo *arg)โ returns information about the LMDB environment โน๏ธint mdb_dbi_open (MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi)โ opens a database in the environment ๐๐๏ธ
and that's the roster ๐ not me scrolling through eighty-something signatures like it's a group chat roster. next part's got more, so don't go anywhere bestie โ
int ESECT mdb_stat (MDB_txn *txn, MDB_dbi dbi, MDB_stat *arg)โ bestie, this one retrieves statistics for a database. stats queen ๐void mdb_dbi_close (MDB_env *env, MDB_dbi dbi)โ closes a database handle. Normally unnecessary. Use with care: she's a little spicy, handle with care ๐int mdb_dbi_flags (MDB_txn *txn, MDB_dbi dbi, unsigned int *flags)โ retrieves the DB flags for a database handle. flags? iconic.int mdb_drop (MDB_txn *txn, MDB_dbi dbi, int del)โ empty or delete+close a database. bye bestie ๐int mdb_set_compare (MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)โ set a custom key comparison function for a database. custom compare? we love to see it.int mdb_set_dupsort (MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)โ set a custom data comparison function for aMDB_DUPSORTdatabase. dupsort girlies riseint mdb_set_relfunc (MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel)โ set a relocation function for aMDB_FIXEDMAPdatabase. relocate, periodt.int mdb_set_relctx (MDB_txn *txn, MDB_dbi dbi, void *ctx)โ set a context pointer for aMDB_FIXEDMAPdatabase's relocation function. context? we love context.int ESECT mdb_env_get_maxkeysize (MDB_env *env)โ get the maximum size of keys andMDB_DUPSORTdata we can write. max keysize, no cap ๐int ESECT mdb_reader_list (MDB_env *env, MDB_msg_func *func, void *ctx)โ dump the entries in the reader lock table. reader lock table said spill the tea.static int ESECT mdb_pid_insert (MDB_PID_T *ids, MDB_PID_T pid)โ no description, just serving looks โจint ESECT mdb_reader_check (MDB_env *env, int *dead)โ check for stale entries in the reader lock table. stale? not on our watch ๐
โจ Variables โจ
static char *const mdb_errstr []static const mdb_nchar_t *const mdb_suffixes [2][2]
these two just exist, no description, mysterious like that ๐
โจ Detailed Description โจ
๐ Data Structure Documentation ๐
struct MDB_page
okay so this is the common header for all page types, and the page type depends on mp_flags. P_BRANCH and P_LEAF pages have unsorted MDB_nodes at the end, with sorted mp_ptrs[] entries referring to them. Exception: P_LEAF2 pages omit mp_ptrs and pack sorted MDB_DUPFIXED values after the page header. P_OVERFLOW records occupy one or more contiguous pages where only the first has a page header. They hold the real data of F_BIGDATA nodes. P_SUBP sub-pages are small leaf "pages" with duplicate data. A node with flag F_DUPDATA but not F_SUBDATA contains a sub-page. (Duplicate data can also go in sub-databases, which use normal pages.) P_META pages contain MDB_meta, the start point of an LMDB snapshot. Each non-metapage up to MDB_meta.mm_last_pg is reachable exactly once in the snapshot: Either used by a database or listed in a freeDB record.
Data Fields
union {
pgno_t p_pgno
struct MDB_page * p_next
} mp_p
uint16_t mp_pad
uint16_t mp_flags
union {
struct {
indx_t pb_lower
indx_t pb_upper
} pb
uint32_t pb_pages
} mp_pb
indx_t mp_ptrs [0]
Field Documentation
pgno_t MDB_page::p_pgnoโ page number obvi ๐struct MDB_page* MDB_page::p_nextโ for in-memory list of freed pages the free list said hiuint16_t MDB_page::mp_padโ key size if this is a LEAF2 page LEAF2 codeduint16_t MDB_page::mp_flagsโ Page Flags flags eraindx_t MDB_page::pb_lowerโ lower bound of free space lower bound, lower stressindx_t MDB_page::pb_upperโ upper bound of free space upper bound, upper blessuint32_t MDB_page::pb_pagesโ number of overflow pages overflow? we been knewindx_t MDB_page::mp_ptrs[0]โ dynamic size dynamic size, main character energy
struct MDB_page2
alternate page header, for 2-byte aligned access โจ
Data Fields
uint16_t mp2_p [sizeof(pgno_t)/2]
uint16_t mp2_pad
uint16_t mp2_flags
indx_t mp2_lower
indx_t mp2_upper
indx_t mp2_ptrs [0]
struct MDB_node
Header for a single key/data pair within a page. Used in pages of type P_BRANCH and P_LEAF without P_LEAF2. We guarantee 2-byte alignment for MDB_nodes. mn_lo and mn_hi are used for data size on leaf nodes, and for child pgno on branch nodes. On 64 bit platforms, mn_flags is also used for pgno. (Branch nodes have no flags). Lo and hi are in host byte order in case some accesses can be optimized to 32-bit word access. Leaf node flags describe node contents. F_BIGDATA says the node's data part is the page number of an overflow page with actual data. F_DUPDATA and F_SUBDATA can be combined giving duplicate data in a sub-page/sub-database, and named databases (just F_SUBDATA).
Data Fields
unsigned short mn_flags
unsigned short mn_ksize
char mn_data [1]
unsigned short mn_lo
unsigned short mn_hi
Field Documentation
unsigned short MDB_node::mn_loโ part of data size or pgno tiny but fierceunsigned short MDB_node::mn_hiโ part of data size or pgno hi bestieunsigned short MDB_node::mn_flagsโ Node Flags flags again? iconic.unsigned short MDB_node::mn_ksizeโ key size key size check โchar MDB_node::mn_data[1]โ key and data are appended here appended? we love an append.
struct MDB_db
Information about a single database in the environment. just one db living her life
Data Fields
uint32_t md_pad
uint16_t md_flags
uint16_t md_depth
pgno_t md_branch_pages
pgno_t md_leaf_pages
pgno_t md_overflow_pages
size_t md_entries
pgno_t md_root
Field Documentation
uint32_t MDB_db::md_padโ also ksize for LEAF2 pages also ksize? multitasking queenuint16_t MDB_db::md_flagsโ Database Flags flags, but make it databaseuint16_t MDB_db::md_depthโ depth of this tree depth? she's deep ๐pgno_t MDB_db::md_branch_pagesโ number of internal pages internal pages, internal thoughtspgno_t MDB_db::md_leaf_pagesโ number of leaf pages leaf pages, nature vibes ๐pgno_t MDB_db::md_overflow_pagesโ number of overflow pages overflow? we overflow.size_t MDB_db::md_entriesโ number of data items data items countedpgno_t MDB_db::md_rootโ the root page of this tree root page, rooted and unbothered
struct MDB_meta
Meta page content. A meta page is the start point for accessing a database snapshot. Pages 0-1 are meta pages. Transaction N writes meta page #(N % 2). meta meta meta
Data Fields
uint32_t mm_magic
uint32_t mm_version
void * mm_address
size_t mm_mapsize
MDB_db mm_dbs [CORE_DBS]
pgno_t mm_last_pg
volatile txnid_t mm_txnid
Field Documentation
uint32_t MDB_meta::mm_magicโ Stamp identifying this as an LMDB file. It must be set toMDB_MAGIC. magic must be magic โจuint32_t MDB_meta::mm_versionโ Version number of this file. Must be set toMDB_DATA_VERSION. version check bestievoid* MDB_meta::mm_addressโ address for fixed mapping address? we're not doxxingsize_t MDB_meta::mm_mapsizeโ size of mmap region mmap size, big brainMDB_db MDB_meta::mm_dbs[CORE_DBS]โ first is free space, 2nd is main db first free, second main โ order matterspgno_t MDB_meta::mm_last_pgโ Last used page in the datafile. Actually the file may be shorter if the freeDB lists the final pages. last page said maybe shorter, don't assume ๐volatile txnid_t MDB_meta::mm_txnidโ txnid that committed this page commit txnid, slay
union MDB_metabuf
Buffer for a stack-allocated meta page. The members define size and alignment, and silence type aliasing warnings. They are not used directly; that could mean incorrectly using several union members in parallel. don't use them directly, bestie, that's undefined vibe territory ๐
Data Fields
MDB_page mb_page
struct {
char mm_pad [PAGEHDRSZ]
MDB_meta mm_meta
} mb_metabuf
struct MDB_dbx
Auxiliary DB info. The information here is mostly static/read-only. There is only a single copy of this record in the environment. one copy only, exclusive ๐
Data Fields
MDB_val md_name
MDB_cmp_func * md_cmp
MDB_cmp_func * md_dcmp
MDB_rel_func * md_rel
void * md_relctx
Field Documentation
MDB_val MDB_dbx::md_nameโ name of the database name? we love a name.MDB_cmp_func* MDB_dbx::md_cmpโ function for comparing keys compare keys, no capMDB_cmp_func* MDB_dbx::md_dcmpโ function for comparing data items compare data, data queenMDB_rel_func* MDB_dbx::md_relโ user relocate function user relocate? she moves.void* MDB_dbx::md_relctxโ user-provided context formd_relcontext is key ๐
struct MDB_txn
Opaque structure for a transaction handle. A database transaction. Every operation requires a transaction handle. All database operations require a transaction handle. Transactions may be read-only or read-write. txn handle, main character energy
Data Fields
MDB_txn * mt_parent
MDB_txn * mt_child
pgno_t mt_next_pgno
txnid_t mt_txnid
MDB_env * mt_env
MDB_IDL mt_free_pgs
MDB_page * mt_loose_pgs
int mt_loose_count
MDB_IDL mt_spill_pgs
union {
MDB_ID2L dirty_list
MDB_reader * reader
} mt_u
MDB_dbx * mt_dbxs
MDB_db * mt_dbs
unsigned int * mt_dbiseqs
MDB_cursor ** mt_cursors
unsigned char * mt_dbflags
MDB_dbi mt_numdbs
unsigned int mt_flags
unsigned int mt_dirty_room
Field Documentation
MDB_txn* MDB_txn::mt_parentโ parent of a nested txn parent txn, family treeMDB_txn* MDB_txn::mt_childโ Nested txn under this txn, set together with flagMDB_TXN_HAS_CHILDchild txn, nepo babypgno_t MDB_txn::mt_next_pgnoโ next unallocated page next page, unallocated and readytxnid_t MDB_txn::mt_txnidโ The ID of this transaction. IDs are integers incrementing from 1. Only committed write transactions increment the ID. If a transaction aborts, the ID may be re-used by the next writer. ID increments from 1, only committed writes bump it; abort and it might get reused โ periodt.MDB_env* MDB_txn::mt_envโ the DB environment the env, the vibeMDB_IDL MDB_txn::mt_free_pgsโ The list of pages that became unused during this transaction. free pages from this txnMDB_page* MDB_txn::mt_loose_pgsโ The list of loose pages that became unused and may be reused in this transaction, linked throughNEXT_LOOSE_PAGE(page). loose pages, linked through NEXT_LOOSE_PAGE(page) โ iykykint MDB_txn::mt_loose_countโ Number of loose pages (mt_loose_pgs) count them loose pagesMDB_IDL MDB_txn::mt_spill_pgsโ The sorted list of dirty pages we temporarily wrote to disk because the dirty list was full. page numbers in here are shifted left by 1, deleted slots have the LSB set. spill pages: sorted, shifted left by 1, LSB set on deleted slots โ no cap.MDB_ID2L MDB_txn::dirty_listโ For write txns: Modified pages. Sorted when notMDB_WRITEMAP. dirty list for write txns, sorted unless MDB_WRITEMAPMDB_reader* MDB_txn::readerโ For read txns: This thread/txn's reader table slot, orNULL. reader slot for read txns, or NULL โ she's optionalMDB_dbx* MDB_txn::mt_dbxsโ Array of records for each DB known in the environment. array of dbx records, one per known DBMDB_db* MDB_txn::mt_dbsโ Array ofMDB_dbrecords for each known DB array of MDB_db recordsunsigned int* MDB_txn::mt_dbiseqsโ Array of sequence numbers for each DB handle array of sequence numbers, per handleMDB_cursor** MDB_txn::mt_cursorsโ In write txns, array of cursors for each DB write txns get an array of cursors per DBunsigned char* MDB_txn::mt_dbflagsโ Array of flags for each DB array of flags, per DBMDB_dbi MDB_txn::mt_numdbsโ Number of DB records in use, or 0 when the txn is finished. This number only ever increments until the txn finishes; we don't decrement it when individual DB handles are closed. numdbs: in-use count or 0 when txn done; only increments until finish, never decrements on individual handle close โ important lore.unsigned int MDB_txn::mt_flagsโ Transaction Flags txn flags, slayunsigned int MDB_txn::mt_dirty_roomโ dirty_list room: Array size - #dirty pages visible to this txn. Includes ancestor txns' dirty pages not hidden by other txns' dirty/spilled pages. Thus commit(nested txn) has room to merge dirty_list intomt_parentafter freeing hiddenmt_parentpages. dirty_list room math: array size minus #dirty pages visible to this txn; includes ancestor dirty pages not hidden by others' dirty/spilled pages. So commit(nested txn) can merge dirty_list into mt_parent after freeing hidden mt_parent pages. big brain energy ๐ง
๐ฆ struct MDB_cursor ๐ฆ
Opaque structure for navigating through a database. Bestie, this is the lil navigator that scoots around your DB. Cursors are used for all DB operations. A cursor holds a path of (page pointer, key index) from the DB root to a position in the DB, plus other state. MDB_DUPSORT cursors include an xcursor to the current data item. Write txns track their cursors and keep them up to date when data moves. Exception: An xcursor's pointer to a P_SUBP page can be stale. (A node with F_DUPDATA but no F_SUBDATA contains a subpage).
Data Fields
MDB_cursor * mc_nextMDB_cursor * mc_backupstruct MDB_xcursor * mc_xcursorMDB_txn * mc_txnMDB_dbi mc_dbiMDB_db * mc_dbMDB_dbx * mc_dbxunsigned char * mc_dbflagunsigned short mc_snumunsigned short mc_topunsigned int mc_flagsMDB_page * mc_pg [CURSOR_STACK]indx_t mc_ki [CURSOR_STACK]
Field Documentation
MDB_cursor* MDB_cursor::mc_next
Next cursor on this DB in this txn. Chain gang energy fr.
MDB_cursor* MDB_cursor::mc_backup
Backup of the original cursor if this cursor is a shadow. It's giving understudy but make it database.
struct MDB_xcursor* MDB_cursor::mc_xcursor
Context used for databases with MDB_DUPSORT, otherwise NULL.
MDB_txn* MDB_cursor::mc_txn
The transaction that owns this cursor. Main character txn energy.
MDB_dbi MDB_cursor::mc_dbi
The database handle this cursor operates on.
MDB_db* MDB_cursor::mc_db
The database record for this cursor.
MDB_dbx* MDB_cursor::mc_dbx
The database auxiliary record for this cursor.
unsigned char* MDB_cursor::mc_dbflag
The Transaction DB Flags for this database.
unsigned short MDB_cursor::mc_snum
number of pushed pages.
unsigned short MDB_cursor::mc_top
index of top page, normally mc_snum-1.
unsigned int MDB_cursor::mc_flags
Cursor Flags. โจ flags, but make them cursor-y โจ
MDB_page* MDB_cursor::mc_pg[CURSOR_STACK]
stack of pushed pages.
indx_t MDB_cursor::mc_ki[CURSOR_STACK]
stack of page indices.
๐ฆ struct MDB_xcursor ๐ฆ
Context for sorted-dup records. We could have gone to a fully recursive design, with arbitrarily deep nesting of sub-databases. But for now we only handle these levels - main DB, optional sub-DB, sorted-duplicate DB. Three levels max, bestie, keep it cute.
Data Fields
MDB_cursor mx_cursorMDB_db mx_dbMDB_dbx mx_dbxunsigned char mx_dbflag
Field Documentation
MDB_cursor MDB_xcursor::mx_cursor
A sub-cursor for traversing the Dup DB.
MDB_db MDB_xcursor::mx_db
The database record for this Dup DB.
MDB_dbx MDB_xcursor::mx_dbx
The auxiliary DB record for this Dup DB.
unsigned char MDB_xcursor::mx_dbflag
The Transaction DB Flags for this Dup DB.
๐ฆ struct MDB_pgstate ๐ฆ
State of FreeDB old pages, stored in the MDB_env. Ancient page lore, but make it useful.
Data Fields
pgno_t * mf_pgheadtxnid_t mf_pglast
Field Documentation
pgno_t* MDB_pgstate::mf_pghead
Reclaimed freeDB pages, or NULL before use.
txnid_t MDB_pgstate::mf_pglast
ID of last used record, or 0 if !mf_pghead.
๐ฆ struct MDB_env ๐ฆ
Opaque structure for a database environment. The database environment. A DB environment supports multiple databases, all residing in the same shared-memory map.
Data Fields
HANDLE me_fdHANDLE me_lfdHANDLE me_mfduint32_t me_flagsunsigned int me_psizeunsigned int me_os_psizeunsigned int me_maxreadersvolatile int me_close_readersMDB_dbi me_numdbsMDB_dbi me_maxdbsMDB_PID_T me_pidchar * me_pathchar * me_mapMDB_txninfo * me_txnsMDB_meta * me_metas [NUM_METAS]void * me_pbufMDB_txn * me_txnMDB_txn * me_txn0size_t me_mapsizeoff_t me_sizepgno_t me_maxpgMDB_dbx * me_dbxsuint16_t * me_dbflagsunsigned int * me_dbiseqspthread_key_t me_txkeytxnid_t me_pgoldestMDB_pgstate me_pgstateMDB_page * me_dpagesMDB_IDL me_free_pgsMDB_ID2L me_dirty_listint me_maxfree_1pgunsigned int me_nodemaxint me_live_readervoid * me_userctxMDB_assert_func * me_assert_func
Field Documentation
HANDLE MDB_env::me_fd
The main data file. Your actual data lives here, periodt.
HANDLE MDB_env::me_lfd
The lock file.
HANDLE MDB_env::me_mfd
For writing and syncing the meta pages.
uint32_t MDB_env::me_flags
Environment Flags.
unsigned int MDB_env::me_psize
DB page size, inited from me_os_psize.
unsigned int MDB_env::me_os_psize
OS page size, from GET_PAGESIZE.
unsigned int MDB_env::me_maxreaders
size of the reader table.
volatile int MDB_env::me_close_readers
Max MDB_txninfo.mti_numreaders of interest to mdb_env_close().
MDB_dbi MDB_env::me_numdbs
number of DBs opened.
MDB_dbi MDB_env::me_maxdbs
size of the DB table.
MDB_PID_T MDB_env::me_pid
process ID of this env.
char* MDB_env::me_path
path to the DB files.
char* MDB_env::me_map
the memory map of the data file.
MDB_txninfo* MDB_env::me_txns
the memory map of the lock file or NULL.
MDB_meta* MDB_env::me_metas[NUM_METAS]
pointers to the two meta pages.
void* MDB_env::me_pbuf
scratch area for DUPSORT put().
MDB_txn* MDB_env::me_txn
current write transaction.
MDB_txn* MDB_env::me_txn0
prealloc'd write transaction. Reuse era.
size_t MDB_env::me_mapsize
size of the data memory map.
off_t MDB_env::me_size
current file size.
pgno_t MDB_env::me_maxpg
me_mapsize / me_psize.
MDB_dbx* MDB_env::me_dbxs
array of static DB info.
uint16_t* MDB_env::me_dbflags
array of flags from MDB_db.md_flags.
unsigned int* MDB_env::me_dbiseqs
array of dbi sequence numbers.
pthread_key_t MDB_env::me_txkey
thread-key for readers.
txnid_t MDB_env::me_pgoldest
ID of oldest reader last time we looked.
MDB_pgstate MDB_env::me_pgstate
state of old pages from freeDB.
MDB_page* MDB_env::me_dpages
list of malloc'd blocks for re-use.
MDB_IDL MDB_env::me_free_pgs
IDL of pages that became unused in a write txn.
MDB_ID2L MDB_env::me_dirty_list
ID2L of pages written during a write txn. Length MDB_IDL_UM_SIZE.
int MDB_env::me_maxfree_1pg
Max number of freelist items that can fit in a single overflow page.
unsigned int MDB_env::me_nodemax
Max size of a node on a page.
int MDB_env::me_live_reader
have liveness lock in reader table.
void* MDB_env::me_userctx
User-settable context.
MDB_assert_func* MDB_env::me_assert_func
Callback for assertion failures.
๐ฆ struct MDB_ntxn ๐ฆ
Nested transaction. Txns within txns, inception vibes.
Data Fields
MDB_txn mnt_txnMDB_pgstate mnt_pgstate
Field Documentation
MDB_txn MDB_ntxn::mnt_txn
the transaction.
MDB_pgstate MDB_ntxn::mnt_pgstate
parent transaction's saved freestate.
๐ฆ struct MDB_name ๐ฆ
Filename - string of mdb_nchar_t[]. Filenames but make them fancy.
Data Fields
int mn_lenint mn_allocedmdb_nchar_t * mn_val
Field Documentation
int MDB_name::mn_len
Length.
int MDB_name::mn_alloced
True if mn_val was malloced.
mdb_nchar_t* MDB_name::mn_val
Contents.
๐ฆ struct mdb_copy ๐ฆ
State needed for a double-buffering compacting copy. Double buffering, compacting, copy โ the holy trinity of slay.
Data Fields
MDB_env * mc_envMDB_txn * mc_txnpthread_mutex_t mc_mutexpthread_cond_t mc_condchar * mc_wbuf [2]char * mc_over [2]size_t mc_wlen [2]size_t mc_olen [2]pgno_t mc_next_pgnoHANDLE mc_fdint mc_toggleint mc_newvolatile int mc_error
Field Documentation
pthread_cond_t mdb_copy::mc_cond
Condition variable for mc_new.
int mdb_copy::mc_toggle
Buffer number in provider.
int mdb_copy::mc_new
(0-2 buffers to write) | (MDB_EOF at end).
volatile int mdb_copy::mc_error
Error code. Never cleared if set. Both threads can set nonzero to fail the copy. Not mutex-protected, LMDB expects atomic int. Do not ignore this one, bestie.
โจ Macro Definition Documentation โจ
#define LOCK_MUTEX( rc, env, mutex)
Value:
((rc) = LOCK_MUTEX0(mutex))
#define mdb_mutex_failed( env, mutex, rc)
Value:
(rc)
#define MDB_DSYNC O_SYNC
A flag for opening a file and requesting synchronous data writes. This is only used when writing a meta page. It's not strictly needed; we could just do a normal write and then immediately perform a flush. But if this flag is available it saves us an extra system call.
Note IfO_DSYNCis undefined but exists in/usr/include, preferably set some compiler flag to get the definition.
#define MDB_FDATASYNC fdatasync
Function for flushing the data of a file. Define this to fsync if fdatasync() is not supported.
#define MDB_MSYNC( addr, len, flags)
Value:
msync(addr,len,flags)
#define MAX_PAGESIZE (PAGEBASE ? 0x10000 : 0x8000)
The maximum size of a database page. It is 32k or 64k, since value-PAGEBASE must fit in MDB_page.mp_upper.
LMDB will use database pages < OS pages if needed. That causes more I/O in write transactions: The OS must know (read) the whole page before writing a partial page.
Note that we don't currently support Huge pages. On Linux, regular data files cannot use Huge pages, and in general Huge pages aren't actually pageable. We rely on the OS demand-pager to read our data and page it out when memory pressure from other processes is high. So until OSs have actual paging support for Huge pages, they're not viable.
#define MDB_MINKEYS 2
The minimum number of keys required in a database page. Setting this to a larger value will place a smaller bound on the maximum size of a data item. Data items larger than this size will be pushed into overflow pages instead of being stored directly in the B-tree node. This value used to default to 4. With a page size of 4096 bytes that meant that any item larger than 1024 bytes would go into an overflow page. That also meant that on average 2-3KB of each overflow page was wasted space. The value cannot be lower than 2 because then there would no longer be a tree structure. With this value, items larger than 2KB will go into overflow pages, and on average only 1KB will be wasted. Math but make it cute? We tried.
#define MDB_MAGIC 0xBEEFC0DE
A stamp that identifies a file as an LMDB file. There's nothing special about this value other than that it is easily recognizable, and it will reflect any byte order mismatches. BEEFC0DE, iconic.
#define MDB_DATA_VERSION ((MDB_DEVEL) ? 999 : 1)
The version number for a database's datafile format.
#define MDB_LOCK_VERSION 1
The version number for a database's lockfile format.
#define MDB_MAXKEYSIZE ((MDB_DEVEL) ? 0 : 511)
The max size of a key we can write, or 0 for computed max. This macro should normally be left alone or set to 0. Note that a database with big keys or dupsort data cannot be reliably modified by a liblmdb which uses a smaller max. The default is 511 for backwards compat, or 0 when MDB_DEVEL.
Other values are allowed, for backwards compat. However: A value bigger than the computed max can break if you do not know what you are doing, and liblmdb <= 0.9.10 can break when modifying a DB with keys/dupsort data bigger than its max.
Data items in an MDB_DUPSORT database are also limited to this size, since they're actually keys of a sub-DB. Keys and MDB_DUPSORT data items must fit on a node in a regular page. So maybe don't freestyle this one unless you're built different.
#define ENV_MAXKEY( env)
Value:
(MDB_MAXKEYSIZE)
MAXKEYSIZE โ nope wait, bestie, first up we got:
#define MAXKEYSIZE
The maximum size of a key we can write to the environment. Periodt, that's the ceiling, don't try to sneak past it. ๐
#define MAXDATASIZE 0xffffffffUL
The maximum size of a data item. We only store a 32 bit value for node sizes. So like, the data can be HUGE but the size number is only gonna be a 32 bit thing, okay? That's the whole tea. ๐ซ
#define DKEY( x)
Value:
0
#define P_INVALID (~(pgno_t)0)
An invalid page number. Mainly used to denote an empty tree. It's giving "no page here, nothing to see, move along." ๐
#define F_ISSET( w, f)
Value:
(((w) & (f)) == (f))
Test if the flags f are set in a flag word w. Basically a little vibe check on your bits. โจ
#define EVEN( n)
Value:
(((n) + 1U) & -2) /* sign-extending -2 to match n+1U */
Round n up to an even number. No odd numbers allowed on this campus, bestie. ๐
#define DEFAULT_MAPSIZE 1048576
Default size of memory map. This is certainly too small for any actual applications. Apps should always set the size explicitly using mdb_env_set_mapsize(). Like, seriously, set it yourself โ do not rely on this default, it's tiny. ๐
#define MP_PGNO( p)
Value:
(((MDB_page2 *)(void *)(p))->mp2_p)
#define MP_PAD( p)
Value:
(((MDB_page2 *)(void *)(p))->mp2_pad)
#define MP_FLAGS( p)
Value:
(((MDB_page2 *)(void *)(p))->mp2_flags)
#define MP_LOWER( p)
Value:
(((MDB_page2 *)(void *)(p))->mp2_lower)
#define MP_UPPER( p)
Value:
(((MDB_page2 *)(void *)(p))->mp2_upper)
#define MP_PTRS( p)
Value:
(((MDB_page2 *)(void *)(p))->mp2_ptrs)
#define PAGEHDRSZ ((unsigned) offsetof(MDB_page, mp_ptrs))
Size of the page header, excluding dynamic data at the end. Just the header, the fixed bit, no extras. ๐
#define METADATA( p)
Value:
((void *)((char *)(p) + PAGEHDRSZ))
Address of first usable data byte in a page, after the header. The good stuff starts right here. ๐
#define PAGEBASE ((MDB_DEVEL) ? PAGEHDRSZ : 0)
ITS#7713, change PAGEBASE to handle 65536 byte pages. (Yes, that's the actual comment, I'm not making it up.) ๐
#define NUMKEYS( p)
Value:
((MP_LOWER(p) - (PAGEHDRSZ-PAGEBASE)) >> 1)
Number of nodes on a page. Counting the roster. ๐ข
#define SIZELEFT( p)
Value:
(indx_t)(MP_UPPER(p) - MP_LOWER(p))
The amount of space remaining in the page. Your remaining budget, fr fr. ๐ธ
#define PAGEFILL( env, p)
Value:
(1000L * ((env)->me_psize - PAGEHDRSZ - SIZELEFT(p)) / \
((env)->me_psize - PAGEHDRSZ))
The percentage of space used in the page, in tenths of a percent. Yes, tenths of a percent โ that's 1000 scale, not 100. ๐ธ
#define FILL_THRESHOLD 250
The minimum page fill factor, in tenths of a percent. Pages emptier than this are candidates for merging. So under 25% full? You're getting merged, sorry bestie. ๐ซถ
#define IS_LEAF( p)
Value:
F_ISSET(MP_FLAGS(p), P_LEAF)
Test if a page is a leaf page. ๐
#define IS_LEAF2( p)
Value:
F_ISSET(MP_FLAGS(p), P_LEAF2)
Test if a page is a LEAF2 page. ๐๐
#define IS_BRANCH( p)
Value:
F_ISSET(MP_FLAGS(p), P_BRANCH)
Test if a page is a branch page. ๐ฟ
#define IS_OVERFLOW( p)
Value:
F_ISSET(MP_FLAGS(p), P_OVERFLOW)
Test if a page is an overflow page. It's giving "too much, couldn't fit." ๐ญ
#define IS_SUBP( p)
Value:
F_ISSET(MP_FLAGS(p), P_SUBP)
Test if a page is a sub page. sub-โจ
#define OVPAGES( size, psize)
Value:
((PAGEHDRSZ-1 + (size)) / (psize) + 1)
The number of overflow pages needed to store the given size. Math! ๐
#define NEXT_LOOSE_PAGE( p)
Value:
(*(MDB_page **)((p) + 2))
Link in MDB_txn.mt_loose_pgs list. Kept outside the page header, which is needed when reusing the page. Iconic little workaround, honestly. ๐
#define NODESIZE offsetof(MDB_node, mn_data)
Size of the node header, excluding dynamic data at the end. Just the header, babe. ๐
#define PGNO_TOPWORD ((pgno_t)-1 > 0xffffffffu ? 32 : 0)
Bit position of top word in page number, for shifting mn_flags. Conditional vibes depending on your pgno_t width. ๐
#define INDXSIZE( k)
Value:
(NODESIZE + ((k) == NULL ? 0 : (k)->mv_size))
Size of a node in a branch page with a given key. This is just the node header plus the key, there is no data. Branch pages: no data, just keys. Simple. โจ
#define LEAFSIZE( k, d)
Value:
(NODESIZE + (k)->mv_size + (d)->mv_size)
Size of a node in a leaf page with a given key and data. This is node header plus key plus data size. Leaf pages get everything. Main character energy. ๐๐
#define NODEPTR( p, i)
Value:
((MDB_node *)((char *)(p) + MP_PTRS(p)[i] + PAGEBASE))
Address of node i in page p. ๐
#define NODEKEY( node)
Value:
(void *)((node)->mn_data)
Address of the key for the node. ๐
#define NODEDATA( node)
Value:
(void *)((char *)(node)->mn_data + (node)->mn_ksize)
Address of the data for a node. ๐ฆ
#define NODEPGNO( node)
Value:
((node)->mn_lo | ((pgno_t) (node)->mn_hi << 16) | \
(PGNO_TOPWORD ? ((pgno_t) (node)->mn_flags << PGNO_TOPWORD) : 0))
Get the page number pointed to by a branch node. Branch node, so it's pointing somewhere โ follow the pointers, bestie. ๐
#define SETPGNO( node, pgno)
Value:
do { \
(node)->mn_lo = (pgno) & 0xffff; (node)->mn_hi = (pgno) >> 16; \
if (PGNO_TOPWORD) (node)->mn_flags = (pgno) >> PGNO_TOPWORD; } while(0)
Set the page number in a branch node. Note the do { ... } while(0) โ that's the classic macro-in-a-block trick, don't @ me. โ
#define NODEDSZ( node)
Value:
((node)->mn_lo | ((unsigned)(node)->mn_hi << 16))
Get the size of the data in a leaf node. ๐
#define SETDSZ( node, size)
Value:
do { \
(node)->mn_lo = (size) & 0xffff; (node)->mn_hi = (size) >> 16;} while(0)
Set the size of the data for a leaf node. Again with the do { ... } while(0). Consistent queen. ๐
#define NODEKSZ( node)
Value:
((node)->mn_ksize)
The size of a key in a node. ๐
#define COPY_PGNO( dst, src)
Value:
do { \
unsigned short *s, *d; \
s = (unsigned short *)&(src); \
d = (unsigned short *)&(dst); \
*d++ = *s++; \
*d = *s; \
} while (0)
Copy a page number from src to dst. Two unsigned shorts, one at a time. Handled. ๐
#define LEAF2KEY( p, i, ks)
Value:
((char *)(p) + PAGEHDRSZ + ((i)*(ks)))
The address of a key in a LEAF2 page. LEAF2 pages are used for MDB_DUPFIXED sorted-duplicate sub-DBs. There are no node headers, keys are stored contiguously. So it's just back-to-back keys, no headers, no fluff. ๐ธ
#define MDB_GET_KEY( node, keyptr)
Value:
{ if ((keyptr) != NULL) { \
(keyptr)->mv_size = NODEKSZ(node); (keyptr)->mv_data = NODEKEY(node); } }
Set the node's key into keyptr, if requested. Only if you asked, otherwise we mind our business. โจ
#define MDB_GET_KEY2( node, key)
Value:
{ key.mv_size = NODEKSZ(node); key.mv_data = NODEKEY(node); }
Set the node's key into key. No NULL check here โ this one just goes. ๐
#define MDB_VALID 0x8000
DB handle is valid, for me_dbflags. The little flag that says "yep, this handle is real." โ
#define VALID_FLAGS
Value:
(MDB_REVERSEKEY|MDB_DUPSORT|MDB_INTEGERKEY|MDB_DUPFIXED|\
MDB_INTEGERDUP|MDB_REVERSEDUP|MDB_CREATE)
mdb_dbi_open() flags. All the flags that mdb_dbi_open() will accept. ๐
#define FREE_DBI 0
Handle for the DB used to track free pages. ๐
#define MAIN_DBI 1
Handle for the default DB. ๐
#define CORE_DBS 2
Number of DBs in metapage (free and main) - also hardcoded elsewhere. Yes, it says "also hardcoded elsewhere," I'm just the messenger. ๐
#define NUM_METAS 2
Number of meta pages - also hardcoded elsewhere. Again with the hardcoding, we love consistency. ๐
#define CURSOR_STACK 32
Enough space for 2^32 nodes with minimum of 2 keys per node. I.e., plenty. At 4 keys per node, enough for 2^64 nodes, so there's probably no need to raise this on a 64 bit machine. Literally plenty, bestie, calm down. ๐งโโ๏ธ
#define XCURSOR_INITED( mc)
Value:
((mc)->mc_xcursor && ((mc)->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED))
Check if there is an inited xcursor. โจ
#define XCURSOR_REFRESH( mc, top, mp)
Value:
do { \
MDB_page *xr_pg = (mp); \
MDB_node *xr_node; \
if (!XCURSOR_INITED(mc) || (mc)->mc_ki[top] >= NUMKEYS(xr_pg)) break; \
xr_node = NODEPTR(xr_pg, (mc)->mc_ki[top]); \
if ((xr_node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA) \
(mc)->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(xr_node); \
} while (0)
Update the xcursor's sub-page pointer, if any, in mc. Needed when the node which contains the sub-page may have moved. Called with leaf page mp = mc->mc_pg[top]. That's three sentences of pure lore, copy it exactly. ๐
#define MDB_COMMIT_PAGES 64
max number of pages to commit in one writev() call. Sixty-four at a time, that's the move. ๐ค
#define MAX_WRITE (0x40000000U >> (sizeof(ssize_t) == 4))
max bytes to write in one call. Note the sneaky shift that halves it on 32-bit ssize_t. ๐คฏ
#define TXN_DBI_EXIST( txn, dbi, validity)
Value:
((txn) && (dbi)<(txn)->mt_numdbs && ((txn)->mt_dbflags[dbi] & (validity)))
Check txn and dbi arguments to a function. Guard clause core. ๐ก๏ธ
#define TXN_DBI_CHANGED( txn, dbi)
Value:
((txn)->mt_dbiseqs[dbi] != (txn)->mt_env->me_dbiseqs[dbi])
Check for misused dbi handles. If this is true, bestie, you misused a handle. ๐ญ
#define MDB_END_NAMES
Value:
{"committed", "empty-commit", "abort", "reset", \
"reset-tmp", "fail-begin", "fail-beginchild"}
#define MDB_END_OPMASK 0x0F
mask for mdb_txn_end() operation number. ๐ญ
#define MDB_END_UPDATE 0x10
update env state (DBIs). ๐
#define MDB_END_FREE 0x20
free txn unless it is MDB_env.me_txn0. Except the special one, obviously. ๐
#define MDB_END_SLOT MDB_NOTLS
release any reader slot if MDB_NOTLS. ๐
#define MDB_SPLIT_REPLACE MDB_APPENDDUP
newkey is not new. The tea: it looks new but it isn't. ๐
#define mdb_env_close0( env, excl)
Value:
mdb_env_close1(env)
#define mdb_cmp_clong mdb_cmp_cint
Compare two items pointing at size_t's of unknown alignment. Same as mdb_cmp_cint, just alias'd. โจ
#define mdb_cassert( mc, expr)
Value:
mdb_assert0((mc)->mc_txn->mt_env, expr, #expr)
assert(3) variant in cursor context. Cursor says: prove it. ๐
#define mdb_tassert( txn, expr)
Value:
mdb_assert0((txn)->mt_env, expr, #expr)
assert(3) variant in transaction context. Transaction says: prove it. ๐
#define mdb_eassert( env, expr)
Value:
mdb_assert0(env, expr, #expr)
assert(3) variant in environment context. Environment says: prove it. ๐
#define mdb_assert0( env, expr, expr_txt)
Value:
((expr) ? (void)0 : \
mdb_assert_fail(env, expr_txt, mdb_func_, __FILE__, __LINE__))
The one that actually does the work โ ternary, and if it fails, it hollers with the function, file and line. __FILE__ and __LINE__, we love a useful error. ๐ฃ๏ธ
#define MDB_NAME( str)
Value:
str
mdb_nchar_t[] string literal. ๐
#define mdb_name_cpy strcpy
Copy name (mdb_nchar_t string). Straight up just strcpy. ๐
#define MDB_SUFFLEN 9
Max string length in mdb_suffixes[]. Nine characters, that's the limit. 9๏ธโฃ
#define mdb_fname_destroy( fname)
Value:
do { if ((fname).mn_alloced) free((fname).mn_val); } while (0)
Destroy fname from mdb_fname_init(). Only frees it if it was actually alloced โ respectful. ๐งน
#define CHANGEABLE (MDB_NOSYNC|MDB_NOMETASYNC|MDB_MAPASYNC|MDB_NOMEMINIT)
Only a subset of the Environment Flags flags can be changed at runtime. Changing other flags requires closing the environment and re-opening it with the new flags. So like, these four? You can switch them whenever. Anything else? Close it and reopen, bestie. ๐ช
#define CHANGELESS
Value:
(MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY| \
MDB_WRITEMAP|MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD)
These ones do NOT change at runtime. Locked in. ๐
#define MDB_NOSPILL 0x8000
Do not spill pages to disk if txn is getting full, may fail instead. So instead of spilling, it might just... give up. Heads up! โ ๏ธ
#define WITH_CURSOR_TRACKING( mn, act)
Value:
do { \
MDB_cursor dummy, *tracked, **tp = &(mn).mc_txn->mt_cursors[mn.mc_dbi]; \
if ((mn).mc_flags & C_SUB) { \
dummy.mc_flags = C_INITIALIZED; \
dummy.mc_xcursor = (MDB_xcursor *)&(mn); \
tracked = &dummy; \
} else { \
tracked = &(mn); \
} \
tracked->mc_next = *tp; \
*tp = tracked; \
{ act; } \
*tp = tracked->mc_next; \
} while (0)
Perform act while tracking temporary cursor mn. Push onto the list, do the thing, pop back off. Clean. ๐
#define MDB_EOF 0x10
mdb_env_copyfd1() is done reading. That's a wrap, folks. ๐
๐ธ Typedef Documentation ๐ธ
โจ pgno_t
typedef MDB_ID pgno_t
A page number in the database, bestie. Now, the tea: 64-bit page numbers are overkill โ because pages themselves already rep 12โ13 bits of addressable memory, and the OS is always gonna cap applications at a max of 63 bits of address space. Like, why so extra ๐
Note ๐ In the MDB_node structure, we only store 48 bits of this value, which thus limits us to only 60 bits of addressable data.
โจ txnid_t
typedef MDB_ID txnid_t
A transaction ID. See struct MDB_txn.mt_txnid for the full lore ๐
โจ indx_t
typedef uint16_t indx_t
Used for offsets within a single page ๐ Since memory pages are typically 4 or 8KB in size โ that's 12โ13 bits โ this is plenty. no notes, it ate.
โจ mdb_nchar_t
typedef char mdb_nchar_t
Character type for file names: char on Unix, wchar_t on Windows ๐ (yes, it's giving duality, and we love that for it)
๐ Enumeration Type Documentation ๐
mdb_fopen_type
enum mdb_fopen_type
File type, access mode etc. for mdb_fopen() ๐ซ
Enumerator ๐ซถ
MDB_O_RDONLYโ for RDONLYme_fdMDB_O_RDWRโ forme_fdMDB_O_METAโ forme_mfdMDB_O_COPYโ formdb_env_copy()MDB_O_MASKโ Bitmask foropen()flags inenum mdb_fopen_type. The other bits distinguish otherwise-equalMDB_O_*constants from each other ๐MDB_O_LOCKSโ forme_lfd
๐ Function Documentation ๐
mdb_page_alloc
int mdb_page_alloc (MDB_cursor * mc, int num, MDB_page ** mp) [static]
Allocate page numbers and memory for writing ๐ฅ Maintains me_pglast, me_pghead and mt_next_pgno. Sets MDB_TXN_ERROR on failure, so like, be careful.
If there are free pages available from older transactions, they get re-used first. Otherwise it allocates a new page at mt_next_pgno. It does not modify the freedB โ it just merges freeDB records into me_pghead[] and moves me_pglast to say which records were consumed. And listen: only this function can create me_pghead and move me_pglast/mt_next_pgno. main character energy only โจ
Parameters
mcโ cursor. A cursor handle identifying the transaction and database for which we are allocating.numโ the number of pages to allocate.mpโ Address of the allocated page(s). Requests for multiple pages will always be satisfied by a single contiguous chunk of memory ๐งฉ
Returns
0 on success, non-zero on failure.
mdb_page_new
int mdb_page_new (MDB_cursor * mc, uint32_t flags, int num, MDB_page ** mp) [static]
Allocate and initialize new pages for a database ๐ฑ Sets MDB_TXN_ERROR on failure.
Parameters
mcโ a cursor on the database being added to.flagsโ flags defining what type of page is being allocated.numโ the number of pages to allocate. This is usually1, unless allocating overflow pages for a large record ๐mpโ Address of a page, orNULLon failure.
Returns
0 on success, non-zero on failure.
mdb_page_touch
int mdb_page_touch (MDB_cursor * mc) [static]
Touch a page: make it dirty and re-insert into tree with updated pgno ๐ Sets MDB_TXN_ERROR on failure.
Parameters
mcโ cursor pointing to the page to be touched
Returns
0 on success, non-zero on failure.
mdb_txn_end
void mdb_txn_end (MDB_txn * txn, unsigned mode) [static]
End a transaction โ except successful commit of a nested transaction, okay? Just so we're clear ๐ซ May be called twice for readonly txns: first reset it, then abort. (twice?! yes bestie, twice ๐)
Parameters
txnโ the transaction handle to endmodeโ why and how to end the transaction
mdb_page_get
int mdb_page_get (MDB_cursor * mc, pgno_t pgno, MDB_page ** ret, int * lvl) [static]
Find the address of the page corresponding to a given page number ๐ Sets MDB_TXN_ERROR on failure.
Parameters
mcโ the cursor accessing the page.pgnoโ the page number for the page to retrieve.retโ address of a pointer where the page's address will be stored.lvlโ dirty_list inheritance level of found page.1=current txn,0=mapped page.
Returns
0 on success, non-zero on failure.
mdb_page_search_root
int mdb_page_search_root (MDB_cursor * mc, MDB_val * key, int flags) [static]
Finish mdb_page_search() / mdb_page_search_lowest() ๐ The cursor is at the root page, set up the rest of it.
mdb_page_search
int mdb_page_search (MDB_cursor * mc, MDB_val * key, int flags) [static]
Search for the page a given key should be in. Push it and its parent pages on the cursor stack ๐
Parameters
mcโ the cursor for this operation.keyโ the key to search for, orNULLfor first/last page.flagsโ IfMDB_PS_MODIFYis set, visited pages in the DB are touched (updated with new page numbers). IfMDB_PS_FIRSTorMDB_PS_LASTis set, find first or last leaf. This is used bymdb_cursor_first()andmdb_cursor_last(). IfMDB_PS_ROOTONLYset, just fetch root node, no further lookups ๐ฏ
Returns
0 on success, non-zero on failure.
mdb_page_merge
int mdb_page_merge (MDB_cursor * csrc, MDB_cursor * cdst) [static]
Merge one page into another ๐ซ The nodes from the page pointed to by csrc will be copied to the page pointed to by cdst and then the csrc page will be freed. bye girl, it was real ๐
Parameters
csrcโ Cursor pointing to the source page.cdstโ Cursor pointing to the destination page.
Returns
0 on success, non-zero on failure.
mdb_page_split
int mdb_page_split (MDB_cursor * mc, MDB_val * newkey, MDB_val * newdata, pgno_t newpgno, unsigned int nflags) [static]
Split a page and insert a new node โ๏ธ Sets MDB_TXN_ERROR on failure.
Parameters
mcโ Cursor pointing to the page and desired insertion index. The cursor will be updated to point to the actual page and index where the node got inserted after the split ๐newkeyโ The key for the newly inserted node.newdataโ The data for the newly inserted node.newpgnoโ The page number, if the new node is a branch node.nflagsโ TheNODE_ADD_FLAGSfor the new node.
Returns
0 on success, non-zero on failure.
mdb_env_read_header
int ESECT mdb_env_read_header (MDB_env * env, MDB_meta * meta) [static]
Read the environment parameters of a DB environment before mapping it into memory ๐ง โจ
Parameters
envโ the environment handlemetaโ address of where to store the meta information
Returns
0 on success, non-zero on failure.
mdb_env_pick_meta
MDB_meta * mdb_env_pick_meta (const MDB_env * env) [static]
Check both meta pages to see which one is newer ๐ต๏ธโ๏ธ (it's giving sibling rivalry, but make it data)
Parameters
envโ the environment handle
Returns
newest MDB_meta.
mdb_env_write_meta
int mdb_env_write_meta (MDB_txn * txn) [static]
Update the environment info to commit a transaction ๐๐
Parameters
txnโ the transaction that's being committed
Returns
0 on success, non-zero on failure.
mdb_env_close0
void ESECT mdb_env_close0 (MDB_env * env, int excl) [static]
Destroy resources from mdb_env_open(), clear our readers & DBIs ๐งนโจ clean girl aesthetic, honestly
mdb_node_search
MDB_node * mdb_node_search (MDB_cursor * mc, MDB_val * key, int * exactp) [static]
Search for key within a page, using binary search ๐ Returns the smallest entry larger or equal to the key. If exactp is non-null, stores whether the found entry was an exact match in *exactp (1 or 0) ๐ฏ Updates the cursor index with the index of the found entry. If no entry larger or equal to the key is found, returns NULL. (yes, NULL, as in nothing, as in ๐)
mdb_node_add
int mdb_node_add (MDB_cursor * mc, indx_t indx, MDB_val * key, MDB_val * data, pgno_t pgno, unsigned int flags) [static]
Add a node to the page pointed to by the cursor โ Sets MDB_TXN_ERROR on failure.
Parameters
mcโ The cursor for this operation.indxโ The index on the page where the new node should be added.keyโ The key for the new node.dataโ The data for the new node, if any.pgnoโ The page number, if adding a branch node.flagsโ Flags for the node.
Returns
0 on success, non-zero on failure. Possible errors are:
ENOMEMโ failed to allocate overflow pages for the node.MDB_PAGE_FULLโ there is insufficient room in the page. This error should never happen since all callers already calculate the page's free space before calling this function. (so if you see it, something's deeply cursed ๐)
mdb_node_del
void mdb_node_del (MDB_cursor * mc, int ksize) [static]
Delete the specified node from a page ๐๏ธ
Parameters
mcโ Cursor pointing to the node to delete.ksizeโ The size of a node. Only used if the page is part of aMDB_DUPFIXEDdatabase.
mdb_node_shrink
void mdb_node_shrink (MDB_page * mp, indx_t indx) [static]
Compact the main page after deleting a node on a subpage ๐ชโจ (glow up after the loss, we stan a bounce-back)
Parameters
mpโ The main page to operate on.indxโ The index of the subpage on the main page.
mdb_node_move
int mdb_node_move (MDB_cursor * csrc, MDB_cursor * cdst, int fromleft) [static]
Move a node from csrc to cdst ๐ no further notes, it literally just does the thing
mdb_node_read
int mdb_node_read (MDB_cursor * mc, MDB_node * leaf, MDB_val * data) [static]
Return the data associated with a given node ๐
Parameters
mcโ The cursor for this operation.leafโ The node being read.dataโ Updated to point to the node's data.
Returns
0 on success, non-zero on failure.
mdb_leaf_size
size_t mdb_leaf_size (MDB_env * env, MDB_val * key, MDB_val * data) [static]
(and that's literally where this part ends โ the description is queued up for the next one, hold on bestie ๐ ๐ฆ)
okay so this one โจ calculates the size of a leaf node ๐ and the size depends on the environment's page size, bestie. And here's the tea: if a data item is too large, it gets yeeted onto an overflow page, and then the node size only counts the key and not the data ๐. Sizes are always rounded up to an even number of bytes, so the MDB_node headers get their 2-byte alignment guaranteed ๐
Parameters ๐ธ
envโ The environment handle.keyโ The key for the node.dataโ The data for the node.
Returns ๐
The number of bytes needed to store the node.
size_t mdb_branch_size (MDB_env * env, MDB_val * key) [static]
Calculates the size of a branch node ๐ฆ. In theory the size should depend on the environment's page size, but the way that we currently don't support spilling large keys onto overflow pages, it's literally just the size of the MDB_node header plus the size of the key, periodt. Sizes get rounded up to an even number of bytes always, to guarantee that sweet 2-byte alignment of the MDB_node headers ๐
Parameters ๐ธ
envโ The environment handle.keyโ The key for the node.
Returns ๐
The number of bytes needed to store the node.
int mdb_rebalance (MDB_cursor * mc) [static]
Rebalances the tree after a delete operation. We love a little cleanup moment ๐๐งน
Parameters ๐ธ
mcโ Cursor pointing to the page where rebalancing should begin.
Returns ๐
0 on success, non-zero on failure.
int mdb_update_key (MDB_cursor * mc, MDB_val * key) [static]
Replaces the key for a branch node with a new key ๐ซ. If it flops, it sets MDB_TXN_ERROR โ so like, heads up ๐
Parameters ๐ธ
mcโ Cursor pointing to the node to operate on.keyโ The new key to use.
Returns ๐
0 on success, non-zero on failure.
void mdb_cursor_pop (MDB_cursor * mc) [static]
Pops a page off the top of the cursor's stack ๐ (yes like a stack of plates, and yes it's exactly as satisfying as it sounds)
int mdb_cursor_push (MDB_cursor * mc, MDB_page * mp) [static]
Pushes a page onto the top of the cursor's stack ๐โจ. Sets MDB_TXN_ERROR on failure, no cap.
int mdb_cursor_del0 (MDB_cursor * mc) [static]
Completes a delete operation that was started by mdb_cursor_del() ๐๏ธ๐
int mdb_cursor_sibling (MDB_cursor * mc, int move_right) [static]
Finds a sibling for a page ๐ซถ. It replaces the page at the top of the cursor's stack with the specified sibling โ if one exists, key word if ๐
Parameters ๐ธ
mcโ The cursor for this operation.move_rightโ Non-zero if the right sibling is requested, otherwise the left sibling.
Returns ๐
0 on success, non-zero on failure.
int mdb_cursor_next (MDB_cursor * mc, MDB_val * key, MDB_val * data, MDB_cursor_op op) [static]
Moves the cursor to the next data item โก๏ธโจ
int mdb_cursor_prev (MDB_cursor * mc, MDB_val * key, MDB_val * data, MDB_cursor_op op) [static]
Moves the cursor to the previous data item โฌ ๏ธโจ
int mdb_cursor_set (MDB_cursor * mc, MDB_val * key, MDB_val * data, MDB_cursor_op op, int * exactp) [static]
Sets the cursor on a specific data item ๐ฏ๐
int mdb_cursor_first (MDB_cursor * mc, MDB_val * key, MDB_val * data) [static]
Moves the cursor to the first item in the database ๐ฅ๐
int mdb_cursor_last (MDB_cursor * mc, MDB_val * key, MDB_val * data) [static]
Moves the cursor to the last item in the database ๐๐
void mdb_cursor_init (MDB_cursor * mc, MDB_txn * txn, MDB_dbi dbi, MDB_xcursor * mx) [static]
Initializes a cursor for a given transaction and database ๐ฑโจ
void mdb_xcursor_init0 (MDB_cursor * mc) [static]
The initial setup of a sorted-dups cursor ๐ง. Okay so here's the lore: sorted duplicates are implemented as a sub-database for the given key, and the duplicate data items are actually keys of that sub-database ๐. Operations on the duplicate data items get performed using a sub-cursor, which is initialized when the sub-database is first accessed. This function does the preliminary setup of the sub-cursor, filling in the fields that depend only on the parent DB ๐
Parameters ๐ธ
mcโ The main cursor whose sorted-dups cursor is to be initialized.
void mdb_xcursor_init1 (MDB_cursor * mc, MDB_node * node) [static]
The final setup of a sorted-dups cursor ๐. This one sets up the fields that depend on the data from the main cursor ๐ซ
Parameters ๐ธ
mcโ The main cursor whose sorted-dups cursor is to be initialized.nodeโ The data containing theMDB_dbrecord for the sorted-dup database.
void mdb_xcursor_init2 (MDB_cursor * mc, MDB_xcursor * src_mx, int new_dupdata) [static]
Fixup time ๐
โ this one fixes up a sorted-dups cursor because of an underlying update ๐. It sets up some fields that depend on the data from the main cursor. Almost the same as init1, except it skips initialization steps if the xcursor had already been used ๐โจ
Parameters ๐ธ
mcโ The main cursor whose sorted-dups cursor is to be fixed up.src_mxโ The xcursor of an up-to-date cursor.new_dupdataโ True if converting from a non-F_DUPDATAitem.
int mdb_drop0 (MDB_cursor * mc, int subs) [static]
Adds all the DB's pages to the free list ๐๏ธ๐ฆ
Parameters ๐ธ
mcโ Cursor on the DB to free.subsโ non-Zero to check for sub-DBs in this DB.
Returns ๐
0 on success, non-zero on failure.
void mdb_default_cmp (MDB_txn * txn, MDB_dbi dbi) [static]
Sets the default comparison functions for a database โ๏ธโจ. It's called immediately after a database is opened, to set the defaults. And then the user can totally override them with mdb_set_compare() or mdb_set_dupsort() โ main character energy, honestly ๐
Parameters ๐ธ
txnโ A transaction handle returned bymdb_txn_begin()dbiโ A database handle returned bymdb_dbi_open()
int ESECT mdb_reader_check0 (MDB_env * env, int rlocked, int * dead) [static]
As mdb_reader_check() ๐. rlocked is set if the caller locked me_rmutex ๐
char *ESECT mdb_version (int * major, int * minor, int * patch)
Returns the LMDB library version information ๐โจ Return the library version info ๐
char * mdb_strerror (int err)
Returns a string describing a given error code ๐. Okay so this function is a superset of the ANSI C X3.159-1989 (ANSI C) strerror(3) function โ iconic behavior ๐
- If the error code is greater than or equal to
0, then the string returned by the system functionstrerror(3)is returned ๐ซถ - If the error code is less than
0, an error string corresponding to the LMDB library error is returned ๐ญ
See Return Codes for a list of LMDB-specific error codes ๐
Parameters ๐ธ
errโ The error code
Return values ๐
- error message โ The description of the error
int mdb_cmp (MDB_txn * txn, MDB_dbi dbi, const MDB_val * a, const MDB_val * b)
Compares two data items according to a particular database ๐ฅโจ. This returns a comparison as if the two data items were keys in the specified database ๐
Parameters ๐ธ
txnโ A transaction handle returned bymdb_txn_begin()dbiโ A database handle returned bymdb_dbi_open()aโ The first item to comparebโ The second item to compare
Returns ๐
< 0 if a < b, 0 if a == b, > 0 if a > b
int mdb_dcmp (MDB_txn * txn, MDB_dbi dbi, const MDB_val * a, const MDB_val * b)
Compares two data items according to a particular database ๐ฅโจ. This one returns a comparison as if the two items were data items of the specified database. Important: the database must have the MDB_DUPSORT flag, no exceptions ๐
Parameters ๐ธ
txnโ A transaction handle returned bymdb_txn_begin()dbiโ A database handle returned bymdb_dbi_open()aโ The first item to comparebโ The second item to compare
Returns ๐
< 0 if a < b, 0 if a == b, > 0 if a > b
MDB_page * mdb_page_malloc (MDB_txn * txn, unsigned num) [static]
Allocates memory for a page ๐ง โจ. It re-uses old malloc'd pages first for singletons, otherwise it just mallocs. Sets MDB_TXN_ERROR on failure ๐
void mdb_page_free (MDB_env * env, MDB_page * mp) [static]
Frees a single page ๐. It saves single pages to a list for future reuse ๐ซถ (and just so you know, this is not used for multi-page overflow pages ๐)
void mdb_dpage_free (MDB_env * env, MDB_page * dp) [static]
Frees a dirty page ๐งผ๐
void mdb_dlist_free (MDB_txn * txn) [static]
Returns all dirty pages to the dpage list ๐โจ
int mdb_page_loose (MDB_cursor * mc, MDB_page * mp) [static]
Loosens or frees a single page ๐ฆ. It saves single pages to a list for future reuse in this same txn. Here's the vibe: it has been pulled from the freeDB and already resides on the dirty list, but it's been deleted. So use these pages first before pulling again from the freeDB, bestie ๐
And if the page wasn't dirtied in this txn, just add it to this txn's free list โจ
int mdb_pages_xkeep (MDB_cursor * mc, unsigned pflags, int all) [static]
Sets or clears P_KEEP in dirty, non-overflow, non-sub pages watched by txn ๐๐
Parameters ๐ธ
mcโ A cursor handle for the current operation.pflagsโ Flags of the pages to update:P_DIRTYto setP_KEEP,P_DIRTY|P_KEEPto clear it.allโ No shortcuts. Needed except after a fullmdb_page_flush().
Returns ๐
0 on success, non-zero on failure.
int mdb_page_flush (MDB_txn * txn, int keep) [static]
Flushes (some) dirty pages to the map, after clearing their dirty flag ๐ฟโจ
Parameters ๐ธ
txnโ the transaction that's being committedkeepโ number of initial pages indirty_listto keep dirty.
Returns ๐
0 on success, non-zero on failure.
int mdb_page_spill (MDB_cursor * m0, MDB_val * key, MDB_val * data) [static]
Spills pages from the dirty list back to disk ๐พ๐ฆ
This is intended to prevent running into MDB_TXN_FULL situations, but note that they may still occur in a few cases ๐ญ:
- our estimate of the txn size could be too small. Currently this seems unlikely, except with a large number of
MDB_MULTIPLEitems. - child txns may run out of space if their parents dirtied a lot of pages and never spilled them. TODO: we probably should do a preemptive spill during
mdb_txn_begin()of a child txn, if the parent'sdirty_roomis below a given threshold.
Otherwise, if you're not using nested txns, it's expected that apps will not run into MDB_TXN_FULL any more ๐ The pages are flushed to disk the same way as for a txn commit, e.g. their P_DIRTY flag is cleared. So:
- If the txn never references them again, they can be left alone ๐
- If the txn only reads them, they can be used without any fuss ๐
- If the txn writes them again, they can be dirtied immediately without going thru all of the work of
mdb_page_touch()๐ฅ Such references are handled bymdb_page_unspill().
Also note ๐ โ we never spill DB root pages, nor pages of active cursors, because we'll need these back again soon anyway ๐. And in nested txns, we can't spill a page in a child txn if it was already spilled in a parent txn ๐. That would alter the parent txns' data even though the child hasn't committed yet, and we'd have no way to undo it if the child aborted. So like, don't. Periodt.
(okay bestie we are literally mid-function right now so the params just start, no heading, we ball ๐)
m0cursor โ a cursor handle identifying the transaction and database for which we are checking space.keyโ for a put operation, the key being stored.dataโ for a put operation, the data being stored.
Returns โ 0 on success, non-zero on failure. โจ
txnid_t mdb_find_oldest (MDB_txn * txn) [static]
Find the oldest txnid that's still being referenced. It expects txn->mt_txnid > 0, no cap. ๐ต๏ธ
void mdb_page_dirty (MDB_txn * txn, MDB_page * mp) [static]
Adds a page to the transaction's dirty list. That's it, that's the whole vibe. ๐
void mdb_page_copy (MDB_page * dst, MDB_page * src, unsigned int psize) [static]
Copies the used portions of a non-overflow page. Non-overflow, bestie โ important.
Parameters
dstโ page to copy into.srcโ page to copy from.psizeโ size of a page.
int mdb_page_unspill (MDB_txn * txn, MDB_page * mp, MDB_page ** ret) [static]
Pulls a page off the transaction's spill list, if it's on there. Like, if a page being referenced got spilled to disk inside this txn, this brings it back and makes it dirty/writable again. resurrection era ๐ฆ
Parameters
txnโ the transaction handle.mpโ the page being referenced. It must not be dirty.retโ the writable page, if any.retis left unchanged ifmpwasn't spilled.
int mdb_env_sync (MDB_env * env, int force)
Flushes the data buffers to disk. So like โ data is always written to disk when mdb_txn_commit() gets called, but the operating system may just be keeping it buffered. Rude of it honestly. LMDB always flushes the OS buffers on commit too, unless the environment was opened with MDB_NOSYNC or in part MDB_NOMETASYNC.
โ ๏ธ This call is not valid if the environment was opened with MDB_RDONLY.
Parameters
envโ an environment handle returned bymdb_env_create().forceโ if non-zero, force a synchronous flush. Otherwise, if the environment has theMDB_NOSYNCflag set, the flushes will be omitted, and withMDB_MAPASYNCthey'll be asynchronous.
Returns โ a non-zero error value on failure and 0 on success. Some possible errors are:
EACCESโ the environment is read-only.EINVALโ an invalid parameter was specified.EIOโ an error occurred during synchronization.
int mdb_cursor_shadow (MDB_txn * src, MDB_txn * dst) [static]
Backs up the parent txn's cursors, then grabs the originals for tracking. Sneaky but legal. ๐
void mdb_cursors_close (MDB_txn * txn, unsigned merge) [static]
Closes this write txn's cursors and hands the parent txn's cursors back to the parent. ๐ซถ
Parameters
txnโ the transaction handle.mergeโtrueto keep changes to parent cursors,falseto revert.
Returns โ 0 on success, non-zero on failure.
int mdb_reader_pid (MDB_env * env, enum Pidlock_op op, MDB_PID_T pid) [static]
Sets or checks a pid lock. Set returns 0 on success. Check returns 0 if the process is certainly dead, and nonzero if it may be alive (the lock exists, or an error happened so we genuinely do not know). ๐ญ
On Windows Pidset is a no-op โ we just check whether the process with the given pid exists. On POSIX we use a single byte lock on the lockfile, set at an offset equal to the pid. iykyk ๐
int mdb_txn_renew0 (MDB_txn * txn) [static]
The common code shared by mdb_txn_begin() and mdb_txn_renew(). Two icons, one implementation.
Parameters
txnโ the transaction handle to initialize.
Returns โ 0 on success, non-zero on failure.
int mdb_txn_renew (MDB_txn * txn)
Renews a read-only transaction. This grabs a new reader lock for a transaction handle that had been released by mdb_txn_reset(). It must be called before a reset transaction may be used again. No skipping steps, bestie. โจ
Parameters
txnโ a transaction handle returned bymdb_txn_begin().
Returns โ a non-zero error value on failure and 0 on success. Some possible errors are:
MDB_PANICโ a fatal error occurred earlier and the environment must be shut down.EINVALโ an invalid parameter was specified.
int mdb_txn_begin (MDB_env * env, MDB_txn * parent, unsigned int flags, MDB_txn ** txn)
Creates a transaction for use with the environment. The transaction handle can be yeeted with mdb_txn_abort() or mdb_txn_commit(). Your call, main character. ๐
๐ Note A transaction and its cursors may only be used by a single thread, and a thread may only have a single transaction at a time. If MDB_NOTLS is in use, this does not apply to read-only transactions. Cursors may not span transactions.
Parameters
envโ an environment handle returned bymdb_env_create().parentโ if this parameter is non-NULL, the new transaction will be a nested transaction, with the transaction indicated byparentas its parent. Transactions may be nested to any level. A parent transaction and its cursors may not issue any other operations thanmdb_txn_commitandmdb_txn_abortwhile it has active child transactions.flagsโ special options for this transaction. This parameter must be set to0or by bitwise OR'ing together one or more of the values described here.MDB_RDONLYโ this transaction will not perform any write operations.
txnโ address where the newMDB_txnhandle will be stored.
Returns โ a non-zero error value on failure and 0 on success. Some possible errors are:
MDB_PANICโ a fatal error occurred earlier and the environment must be shut down.MDB_MAP_RESIZEDโ another process wrote data beyond thisMDB_env's mapsize and this environment's map must be resized as well. Seemdb_env_set_mapsize().MDB_READERS_FULLโ a read-only transaction was requested and the reader lock table is full. Seemdb_env_set_maxreaders().ENOMEMโ out of memory.
MDB_env * mdb_txn_env (MDB_txn * txn)
Returns the transaction's MDB_env. Short and sweet, fr fr. ๐
Parameters
txnโ a transaction handle returned bymdb_txn_begin().
size_t mdb_txn_id (MDB_txn * txn)
Returns the transaction's ID. This returns the identifier associated with this transaction. For a read-only transaction, this corresponds to the snapshot being read; concurrent readers will frequently have the same transaction ID. Twinsies. ๐
Parameters
txnโ a transaction handle returned bymdb_txn_begin().
Returns โ a transaction ID, valid if the input is an active transaction.
void mdb_dbis_update (MDB_txn * txn, int keep) [static]
Exports or closes the DBI handles opened in this txn. โจ
void mdb_txn_reset (MDB_txn * txn)
Resets a read-only transaction. It aborts the transaction like mdb_txn_abort() does, but it keeps the transaction handle, and mdb_txn_renew() may reuse that handle. This saves allocation overhead if the process is gonna start a new read-only transaction soon, and it also saves locking overhead if MDB_NOTLS is in use. The reader table lock is released, but the table slot stays tied to its thread or MDB_txn. Use mdb_txn_abort() to discard a reset handle, and to free its lock table slot if MDB_NOTLS is in use.
Cursors opened within the transaction must not be used again after this call, except with mdb_cursor_renew().
Reader locks generally don't interfere with writers, but they do keep old versions of database pages allocated. So they prevent those old pages from being reused when writers commit new data โ which means under heavy load the database size may grow much more rapidly than it otherwise would. ๐ญ
Parameters
txnโ a transaction handle returned bymdb_txn_begin().
void mdb_txn_abort (MDB_txn * txn)
Abandons 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 mdb_cursor_renew().
๐ Note Earlier documentation incorrectly said all cursors would be freed. Only write-transactions free cursors.
Parameters
txnโ a transaction handle returned bymdb_txn_begin().
int mdb_freelist_save (MDB_txn * txn) [static]
Saves the freelist as of this transaction to the freeDB. This changes the freelist โ so keep trying until it stabilizes. Persistence era. ๐ฅ
int mdb_txn_commit (MDB_txn * txn)
Commits 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 mdb_cursor_renew().
๐ Note Earlier documentation incorrectly said all cursors would be freed. Only write-transactions free cursors.
Parameters
txnโ a transaction handle returned bymdb_txn_begin().
Returns โ 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.
void ESECT mdb_env_init_meta0 (MDB_env * env, MDB_meta * meta) [static]
Fills in most of the zeroed MDB_meta for an empty database environment. Half the job, all the vibes. ๐ง
int ESECT mdb_env_init_meta (MDB_env * env, MDB_meta * meta) [static]
Writes the environment parameters of a freshly created DB environment. Fresh start, clean slate, slay. โจ
Parameters
envโ the environment handle.metaโ theMDB_metato write.
Returns โ 0 on success, non-zero on failure.
int ESECT mdb_env_create (MDB_env ** env)
Creates an LMDB environment handle. This function allocates memory for a MDB_env structure. To release that allocated memory and discard the handle, call mdb_env_close(). Before the handle may be used, it must be opened using mdb_env_open(). Various other options may also need to be set before you open the handle โ e.g. mdb_env_set_mapsize(), mdb_env_set_maxreaders(), mdb_env_set_maxdbs() โ depending on your usage requirements. ๐
Parameters
envโ the address where the new handle will be stored.
Returns โ a non-zero error value on failure and 0 on success.
int ESECT mdb_env_set_mapsize (MDB_env * env, size_t size)
Sets 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, so the value should be chosen as large as possible, to accommodate future growth of the database. This function should be called after mdb_env_create() and before mdb_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. No hand-holding here, bestie. ๐ญ
The new size takes effect immediately for the current process, but it 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, mdb_txn_begin() will return MDB_MAP_RESIZED. This function may be called with a size of zero to adopt the new size. ๐
Quick lil heads up bestie: any attempt to set a size that's smaller than the space the environment has already eaten up will be silently changed to the current size of the used space. Like, it just quietly ignores you. No error, no drama, just vibes. ๐
Parameters
envโ an environment handle returned bymdb_env_create()sizeโ the size in bytes
Returns
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.
๐๏ธ mdb_env_set_maxdbs
int ESECT mdb_env_set_maxdbs (MDB_env * env, MDB_dbi dbs)
Sets the max number of named databases for the environment. You literally only need this if you're gonna have multiple databases chilling in the environment. If your app is a simple lil thing using the environment as one single unnamed database, you can just skip this entirely, no thoughts needed. โจ
โ ๏ธ This one may only be called aftermdb_env_create()and beforemdb_env_open(). Like, the window is specific.
rn a moderate number of slots is cheap, but a huge number gets expensive: 7-120 words per transaction, and every single mdb_dbi_open() does a linear search through the opened slots. So like. be a little mindful. ๐
Parameters
envโ an environment handle returned bymdb_env_create()dbsโ the maximum number of databases
Returns
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.
๐งต mdb_env_set_maxreaders
int ESECT mdb_env_set_maxreaders (MDB_env * env, unsigned int readers)
Sets the max number of threads / reader slots for the environment. This is literally defining how many slots live in the lock table that tracks readers in the environment. The default is 126, bestie, write that down. ๐
Starting a read-only transaction normally ties a lock table slot to the current thread until the environment closes or the thread exits. But if MDB_NOTLS is in use, mdb_txn_begin() instead ties the slot to the MDB_txn object until it or the MDB_env object is destroyed. Two completely different attachment styles, iykyk. ๐
โ ๏ธ Same rule as before: this may only be called aftermdb_env_create()and beforemdb_env_open().
Parameters
envโ an environment handle returned bymdb_env_create()readersโ the maximum number of reader lock table slots
Returns
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.
๐ mdb_env_get_maxreaders
int ESECT mdb_env_get_maxreaders (MDB_env * env, unsigned int * readers)
Gets the max number of threads / reader slots for the environment. The read-only bestie to mdb_env_set_maxreaders, no cap. ๐ธ
Parameters
envโ an environment handle returned bymdb_env_create()readersโ address of an integer to store the number of readers
Returns
A non-zero error value on failure and 0 on success. Some possible errors are:
EINVALโ an invalid parameter was specified.
๐ง mdb_fname_init (static)
int ESECT mdb_fname_init (const char * path, unsigned envflags, MDB_name * fname) [static]
Sets up the filename + scratch area for the filename suffix, for opening files. This is internal plumbing, so like, you're seeing backstage. ๐ญ
It should be freed with mdb_fname_destroy(). On Windows, paths get converted from char *UTF-8 to wchar_t *UTF-16 โ iconic lil platform glow-up. ๐
pathโ the pathname you're handing tomdb_env_open()๐envflagsโ tells ya whether a subdir and/or a lockfile is gonna be usedfnameโ the resulting filename, with room left over for a suffix if it needs one
int ESECT mdb_fopen (const MDB_env * env, MDB_name * fname, enum mdb_fopen_type which, mdb_mode_t mode, HANDLE * res) [static]
Bestie this one opens an LMDB file, that's the whole job โจ
Parameters
envโ the LMDB environment, obvs ๐fnameโ the path that came out ofmdb_fname_init(). A suffix gets appended if it's needed to actually make the filename, but without touchingmn_len๐whichโ decides the file type, the access mode, all that jazzmodeโ the Unix permissions for the file, if we end up creating itresโ the resulting file handle ๐ซถ
Returns
0 when it works, non-zero when it doesn't ๐
int ESECT mdb_env_open2 (MDB_env * env) [static]
Extra setup that's still required for opening an LMDB environment. Like, the second half of the getting-ready routine ๐
void mdb_env_reader_dest (void * ptr) [static]
Releases a reader thread's slot in the reader lock table ๐ and the cutest part is it gets called automatically when a thread exits, you don't have to do a thing, it's giving self-care fr fr
Parameters
ptrโ points at the slot in the reader lock table ๐ธ
int ESECT mdb_env_share_locks (MDB_env * env, int * excl) [static]
Downgrades the exclusive lock on the region back down to shared. Glow down, not glow up โจ
int ESECT mdb_env_excl_lock (MDB_env * env, int * excl) [static]
Tries to grab an exclusive lock, and if it can't, settles for shared ๐ and it maintains *excl like this:
-1โ no lock, or an unknown lock0โ shared1โ exclusive
int ESECT mdb_env_setup_locks (MDB_env * env, MDB_name * fname, int mode, int * excl) [static]
Opens and/or initializes the lock region for the environment. The lock region's whole moment ๐
Parameters
envโ the LMDB environment ๐fnameโ filename + scratch area, frommdb_fname_init()modeโ the Unix permissions for the file, if we create itexclโ in comes a lock type, out goes a lock type:-1none,0shared,1exclusive
Returns
0 on success, non-zero on failure ๐ซ
int ESECT mdb_env_open (MDB_env * env, const char * path, unsigned int flags, mdb_mode_t mode)
Opens an environment handle. Big main character energy function, ngl ๐
โ ๏ธ If this function fails,mdb_env_close()must be called to discard theMDB_envhandle. No leaving it lying around, bestie.
Parameters
envโ an environment handle that came back frommdb_env_create()๐pathโ the directory where the database files live. This directory has to already exist, and it has to be writable, no exceptions ๐flagsโ special options for this environment. You set this to0, or you bitwise-OR together one or more of the values described here. Flags set bymdb_env_set_flags()are in play too ๐ซMDB_FIXEDMAPโ use a fixed address for the mmap region. You've gotta specify this flag when you create the environment, and it's stored persistently in the environment. If it works, the memory map will always sit 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, it depends on how the operating system has allocated memory to shared libraries and other uses. The feature is highly experimental ๐งชMDB_NOSUBDIRโ by default, LMDB creates its environment in a directory whose pathname is given inpath, and it creates its data and lock files under that directory. With this option,pathgets used as-is for the database main data file. The database lock file is thepathwith"-lock"appended ๐MDB_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 ๐MDB_WRITEMAPโ use a writeable memory map unlessMDB_RDONLYis set. This uses fewermallocs but it 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 it's slower for DBs bigger than RAM. Incompatible with nested transactions. Do not mix processes with and withoutMDB_WRITEMAPon the same environment. This can defeat durability (mdb_env_syncetc) ๐ญMDB_NOMETASYNCโ flush system buffers to disk only once per transaction, and omit the metadata flush. Defer that until the system flushes files to disk, or the next non-MDB_RDONLYcommit, ormdb_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 the D (durability) database property ๐ฌ This flag can be changed at any time usingmdb_env_set_flags()MDB_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 haven't been flushed to disk yet. The risk is governed by how often the system flushes dirty buffers to disk and how oftenmdb_env_sync()is called ๐ซฃ However, if the filesystem preserves write order and theMDB_WRITEMAPflag 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 (MDB_NOSYNC|MDB_WRITEMAP) leaves the system with no hint for when to write transactions to disk, unlessmdb_env_sync()is called. (MDB_MAPASYNC|MDB_WRITEMAP) may be preferable โจ This flag can be changed at any time usingmdb_env_set_flags()MDB_MAPASYNCโ when usingMDB_WRITEMAP, use asynchronous flushes to disk. Same as withMDB_NOSYNC, a system crash can then corrupt the database or lose the last transactions ๐ต Callingmdb_env_sync()ensures on-disk database integrity until the next commit. This flag can be changed at any time usingmdb_env_set_flags()MDB_NOTLSโ don't use Thread-Local Storage. Tie reader locktable slots toMDB_txnobjects instead of to threads. I.e.mdb_txn_reset()keeps the slot reserved for theMDB_txnobject ๐งท 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 ๐งตMDB_NOLOCKโ don't do any locking at all ๐ซ๐ 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 beginsMDB_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 WindowsMDB_NOMEMINITโ don't initializemalloc'd memory before writing to unused spaces in the data file. By default, memory for pages written to the data file is obtained usingmalloc. While these pages may be reused in subsequent transactions, freshlymalloc'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 withMDB_WRITEMAP, which writes directly to the mmap instead of usingmallocfor pages. The initialization is also skipped ifMDB_RESERVEis used; the caller is expected to overwrite all of the memory that was reserved in that case. This flag can be changed at any time usingmdb_env_set_flags()
modeโ the UNIX permissions to set on created files and semaphores. This parameter is ignored on Windows ๐ช
Returns
A non-zero error value on failure and 0 on success. Some possible errors are ๐ซถ
MDB_VERSION_MISMATCHโ the version of the LMDB library doesn't match the version that created the database environmentMDB_INVALIDโ the environment file headers are corrupted ๐ENOENTโ the directory specified by thepathparameter doesn't existEACCESโ the user didn't have permission to access the environment filesEAGAINโ the environment was locked by another process ๐
void ESECT mdb_env_close (MDB_env * env)
Closes the environment and releases the memory map. Only a single thread may call this function ๐จ All transactions, databases, and cursors must already be closed before you call this. 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. It's gone, bestie, let it go ๐ญ
Parameters
envโ an environment handle returned bymdb_env_create()๐
int mdb_cmp_long (const MDB_val * a, const MDB_val * b) [static]
Compares two items pointing at aligned size_t's ๐งฎ
int mdb_cmp_int (const MDB_val * a, const MDB_val * b) [static]
Compares two items pointing at aligned unsigned int's. Same vibe, different type, periodt ๐
okay so also? this exact same thing gets set as MDB_INTEGERDUP|MDB_DUPFIXED's MDB_dbx.md_dcmp โ but bestie listen, if the data type is size_t then mdb_cmp_clong() is the one that gets called instead. not mdb_cmp_long(). different girl. ๐
int mdb_cmp_cint (const MDB_val * a, const MDB_val * b)[static]
compares two items that are pointing at unsigned ints whose alignment is a mystery ๐ โ unknown alignment, we don't know her. the good news? nodes and keys are guaranteed to be 2-byte aligned, so it's not total chaos. lowkey reassuring fr fr.
int mdb_cmp_memn (const MDB_val * a, const MDB_val * b)[static]
compares two items lexically โจ just vibes, alphabetically, byte by byte, the classic.
int mdb_cmp_memnr (const MDB_val * a, const MDB_val * b)[static]
same energy but in reverse byte order ๐ it's giving main character who reads the book backwards. iconic honestly.
int mdb_page_search_lowest (MDB_cursor * mc)[static]
searches for the lowest key under the current branch page ๐ฆ
and like, it literally just bypasses a NUMKEYS check in the current page before it calls mdb_page_search_root() โ because bestie, every single caller is already in a situation where the current page is known to be underfilled. no need to double-check what we already know ๐
periodt.
๐ฅ the big one: mdb_get ๐ฅ
int mdb_get (MDB_txn * txn, MDB_dbi dbi, MDB_val * key, MDB_val * data)
โจ Get items from a database. โจ
okay so this function retrieves key/data pairs from the database. the address and the length of the data that goes with your specified key get returned inside the structure that data points at. cute, right? ๐
now โ if the database supports duplicate keys (MDB_DUPSORT) then bestie, you only get the first data item for that key. that's it. that's the one. if you want the other items you gotta go use mdb_cursor_get(), no shortcuts ๐.
Note โ ๏ธ The memory pointed to by the returned values is owned by the database ๐. The caller need not dispose of the memory, and may not modify it in any way. And for values returned in a read-only transaction? any modification attempts will cause a SIGSEGV ๐ญ not a warning, not a gentle error, a full-on crash. do not touch. hands off. look with your eyes, not your hands ๐ซถ
Okay so real talk about those values you just pulled out of the database โ they're only valid until the next update operation, or until the transaction ends. That's it. That's the window. Don't be out here holding onto them like they're yours forever, because they are not ๐
Parameters ๐ซถ
txnโ a transaction handle that came frommdb_txn_begin()dbiโ a database handle that came frommdb_dbi_open()keyโ the key you're searching for in the databasedataโ the data that matches that key
Returns โจ
A non-zero error value if it flops, and 0 if it slays. Some possible errors:
MDB_NOTFOUNDโ that key was not in the database, bestie ๐ญEINVALโ you handed it an invalid parameter
๐ซ int mdb_cursor_get (MDB_cursor * cursor, MDB_val * key, MDB_val * data, MDB_cursor_op op)
Retrieve by cursor. This one grabs key/data pairs straight out of the database. The address and length of the key get returned in the object that key points to (except in the case of the MDB_SET option, where the key object just stays unchanged, iconic), and the address and length of the data get returned in the object that data points to. And hey โ go look at mdb_get() for the restrictions on using those output values, because they apply here too ๐
Parameters
cursorโ a cursor handle that came frommdb_cursor_open()keyโ the key for a retrieved itemdataโ the data of a retrieved itemopโ a cursor operation, anMDB_cursor_op
Returns
Non-zero error value on failure, 0 on success. Some possible errors:
MDB_NOTFOUNDโ no matching key found ๐EINVALโ an invalid parameter was specified
๐ int mdb_cursor_touch (MDB_cursor * mc) (static)
Touch all the pages in the cursor stack. Sets mc_top. Basically it makes sure all the pages are writable before you go attempting a write operation. Pre-flight check energy โ๏ธ
Parameters
mcโ the cursor to operate on.
๐ธ int mdb_cursor_put (MDB_cursor * cursor, MDB_val * key, MDB_val * data, unsigned int flags)
Store by cursor, bestie. This stores key/data pairs into the database, and the cursor ends up positioned at the new item โ or on failure, usually somewhere near it. Not exact, just near ๐
Note โ earlier documentation incorrectly said errors would leave the state of the cursor unchanged. That was wrong. We said what we said ๐
Parameters
cursorโ a cursor handle that came frommdb_cursor_open()keyโ the key operated on.dataโ the data operated on.flagsโ options for this operation. This parameter must be set to0or one of the values described here.MDB_CURRENTโ replace the item at the current cursor position. Thekeyparameter must still be provided, and it must match. If you're using sorted duplicates (MDB_DUPSORT) the data item must still sort into the same place. This is intended for when the new data is the same size as the old โ otherwise it will simply perform a delete of the old record followed by an insert. So like, respectfully, just know which one you're getting ๐ซMDB_NODUPDATAโ only enter the new key/data pair if it does not already appear in the database. This flag may only be specified if the database was opened withMDB_DUPSORT. The function returnsMDB_KEYEXISTif the key/data pair already appears in the database.MDB_NOOVERWRITEโ only enter the new key/data pair if the key does not already appear in the database. The function returnsMDB_KEYEXISTif the key already appears in the database, even if the database supports duplicates (MDB_DUPSORT).MDB_RESERVEโ reserve space for data of the given size, but don't copy the given data. Instead, return a pointer to the reserved space, which the caller can fill in later โ before the next update operation or the transaction ends. This saves an extramemcpyif the data is being generated later. This flag must not be specified if the database was opened withMDB_DUPSORT.MDB_APPENDโ append the given key/data pair to the end of the database. No key comparisons are performed. This option allows fast bulk loading when the keys are already known to be in the correct order. Loading unsorted keys with this flag will cause anMDB_KEYEXISTerror. Sorted or it's over, no in-between ๐ฅMDB_APPENDDUPโ as above, but for sorted dup data.MDB_MULTIPLEโ store multiple contiguous data elements in a single request. This flag may only be specified if the database was opened withMDB_DUPFIXED. Thedataargument must be an array of twoMDB_vals. Themv_sizeof the firstMDB_valmust be the size of a single data element. Themv_dataof the firstMDB_valmust point to the beginning of the array of contiguous data elements. Themv_sizeof the secondMDB_valmust be the count of the number of data elements to store. On return this field will be set to the count of the number of elements actually written. Themv_dataof the secondMDB_valis unused.
Returns
Non-zero error value on failure, 0 on success. Some possible errors:
MDB_MAP_FULLโ the database is full, go seemdb_env_set_mapsize()MDB_TXN_FULLโ the transaction has too many dirty pages ๐ตโ๐ซEACCESโ an attempt was made to write in a read-only transactionEINVALโ an invalid parameter was specified
๐ฆ int mdb_cursor_del (MDB_cursor * cursor, unsigned int flags)
Delete the current key/data pair. This deletes the key/data pair that the cursor is referring to. Now listen โ this does not invalidate the cursor, so operations like MDB_NEXT can still be used on it. Both MDB_NEXT and MDB_GET_CURRENT will return the same record after this operation. She's still standing ๐
Parameters
cursorโ a cursor handle that came frommdb_cursor_open()flagsโ options for this operation. This parameter must be set to0or one of the values described here.MDB_NODUPDATAโ delete all of the data items for the current key. This flag may only be specified if the database was opened withMDB_DUPSORT.
Returns
Non-zero error value on failure, 0 on success. Some possible errors:
EACCESโ an attempt was made to write in a read-only transactionEINVALโ an invalid parameter was specified
๐ int mdb_cursor_open (MDB_txn * txn, MDB_dbi dbi, MDB_cursor ** cursor)
Create a cursor handle. A cursor is associated with one specific transaction and one specific database. Facts are facts ๐
A cursor cannot be used when its database handle is closed. Nor when its transaction has ended โ except with mdb_cursor_renew(). It can be discarded with mdb_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 mdb_cursor_renew() before you finally close it.
Note โ earlier documentation said that cursors in every transaction were closed when the transaction committed or aborted. That was not it. It was wrong ๐ข
Parameters
txnโ a transaction handle that came frommdb_txn_begin()dbiโ a database handle that came frommdb_dbi_open()cursorโ address where the newMDB_cursorhandle will be stored
Returns
Non-zero error value on failure, 0 on success. Some possible errors:
EINVALโ an invalid parameter was specified
๐ int mdb_cursor_renew (MDB_txn * txn, MDB_cursor * cursor)
Renew a cursor handle. A cursor is associated with one specific transaction and one specific database. Cursors that are only used in read-only transactions may be re-used, so you dodge all that unnecessary malloc/free overhead โ sustainable queen behavior ๐ฑ
The cursor may be associated with a new read-only transaction, and it references the same database handle as the one it was created with. You can do this whether the previous transaction is live or dead. No vibe check required.
Parameters
txnโ a transaction handle that came frommdb_txn_begin()cursorโ a cursor handle that came frommdb_cursor_open()
Returns
Non-zero error value on failure, 0 on success. Some possible errors:
EINVALโ an invalid parameter was specified
๐ int mdb_cursor_count (MDB_cursor * cursor, size_t * countp)
Return the count of duplicates for the current key. This call is only valid on databases that support sorted duplicate data items, MDB_DUPSORT. So if you're not on a MDB_DUPSORT databaseโฆ this is not for you, babe ๐ซถ
Parameters
cursorโ a cursor handle that came frommdb_cursor_open()countpโ address where the count will be stored
Returns
Non-zero error value on failure, 0 on success. Some possible errors:
EINVALโ cursor is not initialized, or an invalid parameter was specified.
๐ง void mdb_cursor_close (MDB_cursor * cursor)
Close a cursor handle. The cursor handle gets freed and must not be used again after this call. Like, gone gone. Also, its transaction must still be live if it's a write-transaction.
Parameters
cursorโ a cursor handle that came frommdb_cursor_open()
โจ MDB_txn * mdb_cursor_txn (MDB_cursor * cursor)
Return the cursor's transaction handle. That's it, that's the whole function ๐
Parameters
cursorโ a cursor handle that came frommdb_cursor_open()
๐ MDB_dbi mdb_cursor_dbi (MDB_cursor * cursor)
Return the cursor's database handle. Short king of a function ๐
Parameters
cursorโ a cursor handle that came frommdb_cursor_open()
๐
void mdb_cursor_copy (const MDB_cursor * csrc, MDB_cursor * cdst) (static)
Copy the contents of a cursor. Duplicate. Dupe. Clone her ๐ช
Parameters
csrcโ the cursor to copy from.cdstโ the cursor to copy to.
๐ฅ int mdb_del (MDB_txn * txn, MDB_dbi dbi, MDB_val * key, MDB_val * data)
Delete items from a database. This removes key/data pairs from the database. Here's the breakdown:
- If the database does not support sorted duplicate data items (
MDB_DUPSORT), thedataparameter is ignored. Straight up ignored, she said nothing ๐ซฅ - If the database does support sorted duplicates and the
dataparameter isNULL, all of the duplicate data items for the key will be deleted. Mass deletion, no survivors. - Otherwise, if the
dataparameter is non-NULL, only the matching data item will be deleted โ surgical, precise.
This function will return MDB_NOTFOUND if the specified key/data pair is not in the database.
Parameters
txnโ a transaction handle that came frommdb_txn_begin()dbiโ a database handle that came frommdb_dbi_open()keyโ the key to delete from the databasedataโ the data to delete
Returns
Non-zero error value on failure, 0 on success. Some possible errors:
EACCESโ an attempt was made to write in a read-only transactionEINVALโ an invalid parameter was specified
๐ int mdb_put (MDB_txn * txn, MDB_dbi dbi, MDB_val * key, MDB_val * data, unsigned int flags)
Store items into a database. This stores key/data pairs in the database. The default behavior is to enter the new key/data pair, replacing any previously existing key if duplicates are disallowed, or adding a duplicate data item if duplicates are allowed (MDB_DUPSORT). Either way, she's going in ๐ซ
Parameters
txnโ a transaction handle that came frommdb_txn_begin()dbiโ a database handle that came frommdb_dbi_open()keyโ the key to store in the databasedataโ the data to storeflagsโ special options for this operation. This parameter must be set
So bestie, this parameter? Set it to 0, or bitwise-OR together one or more of the values described right here ๐
MDB_NODUPDATAโ only enters that new key/data pair if it does not already live in the database. You may only specify this flag if the database was opened withMDB_DUPSORT. If the key/data pair is already in there, the function returnsMDB_KEYEXIST๐MDB_NOOVERWRITEโ only enters the new key/data pair if the key doesn't already exist in the database. Function returnsMDB_KEYEXISTif the key is already there, even if the database supports duplicates (MDB_DUPSORT). And thedataparameter gets set to point at the existing item. sneaky but helpful ๐MDB_RESERVEโ reserves space for data of the given size, but does not copy the given data. Instead it returns a pointer to the reserved space, and the caller fills that in later โ before the next update operation, or before the transaction ends. This saves an extramemcpyif the data is being generated later. LMDB does nothing else with this memory, so the caller is expected to modify all of the space requested. This flag must not be specified if the database was opened withMDB_DUPSORT. ๐ซMDB_APPENDโ appends the given key/data pair to the end of the database. This option allows fast bulk loading when the keys are already known to be in the correct order. Loading unsorted keys with this flag will cause aMDB_KEYEXISTerror. โ ๏ธMDB_APPENDDUPโ as above, but for sorted dup data.
Returns
A non-zero error value on failure and 0 on success. Some possible errors are:
MDB_MAP_FULLโ the database is full, seemdb_env_set_mapsize().MDB_TXN_FULLโ the transaction has too many dirty pages. ๐ญEACCESโ an attempt was made to write in a read-only transaction.EINVALโ an invalid parameter was specified.
โจ THREAD_RET ESECT CALL_CONV mdb_env_copythr (void * arg) [static]
THREAD_RET ESECT CALL_CONV mdb_env_copythr (void * arg)
Dedicated writer thread for compacting copy. ๐งต she's the one doing the actual writing, periodt
โจ int ESECT mdb_env_cthr_toggle (mdb_copy * my, int adjust) [static]
int ESECT mdb_env_cthr_toggle (mdb_copy * my, int adjust)
Give buffer and/or MDB_EOF to writer thread, await unused buffer. ๐ฆ
Parameters
myโ control structure.adjustโ (1to hand off 1 buffer) | (MDB_EOFwhen ending).
โจ int ESECT mdb_env_cwalk (mdb_copy * my, pgno_t * pg, int flags) [static]
int ESECT mdb_env_cwalk (mdb_copy * my, pgno_t * pg, int flags)
Depth-first tree traversal for compacting copy. ๐ณ going deep, one page at a time
Parameters
myโ control structure.pgโ database root.flagsโ includesF_DUPDATAif it is a sorted-duplicate sub-DB.
โจ int ESECT mdb_env_copyfd1 (MDB_env * env, HANDLE fd) [static]
int ESECT mdb_env_copyfd1 (MDB_env * env, HANDLE fd)
Copy environment with compaction. ๐ฅ
โจ int ESECT mdb_env_copyfd0 (MDB_env * env, HANDLE fd) [static]
int ESECT mdb_env_copyfd0 (MDB_env * env, HANDLE fd)
Copy environment as-is. ๐ no glow-up, just the raw copy
โจ int ESECT mdb_env_copy2 (MDB_env * env, const char * path, unsigned int flags)
int ESECT mdb_env_copy2 (MDB_env * env, const char * path, unsigned int flags)
Copy an LMDB environment to the specified path, with options. This function may be used to make a backup of an existing environment. No lockfile is created, since it gets recreated at need. ๐
Note โ This call can trigger significant file size growth if run in parallel with write transactions, because it employs a read-only transaction. See long-lived transactions under Caveats. ๐ณ
Parameters
envโ An environment handle returned bymdb_env_create(). It must have already been opened successfully.pathโ The directory in which the copy will reside. This directory must already exist and be writable but must otherwise be empty.flagsโ Special options for this operation. This parameter must be set to0or by bitwise OR'ing together one or more of the values described here.MDB_CP_COMPACTโ Perform compaction while copying: omit free pages and sequentially renumber all pages in output. This option consumes more CPU and runs more slowly than the default. Currently it fails if the environment has suffered a page leak.
Returns
A non-zero error value on failure and 0 on success.
โจ int ESECT mdb_env_copy (MDB_env * env, const char * path)
int ESECT mdb_env_copy (MDB_env * env, const char * path)
Copy an LMDB environment to the specified path. This function may be used to make a backup of an existing environment. No lockfile is created, since it gets recreated at need. ๐ซถ
Note โ This call can trigger significant file size growth if run in parallel with write transactions, because it employs a read-only transaction. See long-lived transactions under Caveats. ๐ญ
Parameters
envโ An environment handle returned bymdb_env_create(). It must have already been opened successfully.pathโ The directory in which the copy will reside. This directory must already exist and be writable but must otherwise be empty.
Returns
A non-zero error value on failure and 0 on success.
โจ int ESECT mdb_env_set_flags (MDB_env * env, unsigned int flags, int onoff)
int ESECT mdb_env_set_flags (MDB_env * env, unsigned int flags, int onoff)
Set environment flags. This may be used to set some flags in addition to those from mdb_env_open(), or to unset these flags. If several threads change the flags at the same time, the result is undefined. ๐ bestie do not do that
Parameters
envโ An environment handle returned bymdb_env_create()flagsโ The flags to change, bitwise OR'ed togetheronoffโ A non-zero value sets the flags, zero clears them.
Returns
A non-zero error value on failure and 0 on success. Some possible errors are:
EINVALโ an invalid parameter was specified.
โจ int ESECT mdb_env_get_flags (MDB_env * env, unsigned int * flags)
int ESECT mdb_env_get_flags (MDB_env * env, unsigned int * flags)
Get environment flags. ๐
Parameters
envโ An environment handle returned bymdb_env_create()flagsโ The address of an integer to store the flags
Returns
A non-zero error value on failure and 0 on success. Some possible errors are:
EINVALโ an invalid parameter was specified.
โจ int ESECT mdb_env_set_userctx (MDB_env * env, void * ctx)
int ESECT mdb_env_set_userctx (MDB_env * env, void * ctx)
Set application information associated with the MDB_env. ๐
Parameters
envโ An environment handle returned bymdb_env_create()ctxโ An arbitrary pointer for whatever the application needs.
Returns
A non-zero error value on failure and 0 on success.
โจ void *ESECT mdb_env_get_userctx (MDB_env * env)
void *ESECT mdb_env_get_userctx (MDB_env * env)
Get the application information associated with the MDB_env. ๐
Parameters
envโ An environment handle returned bymdb_env_create()
Returns
The pointer set by mdb_env_set_userctx().
โจ int ESECT mdb_env_set_assert (MDB_env * env, MDB_assert_func * func)
int ESECT mdb_env_set_assert (MDB_env * env, MDB_assert_func * func)
Set or reset the assert() callback of the environment. Disabled if liblmdb is built with NDEBUG.
Note โ This hack should become obsolete as lmdb's error handling matures. it said it itself, not me
Parameters
envโ An environment handle returned bymdb_env_create().funcโ AnMDB_assert_funcfunction, or0.
Returns
A non-zero error value on failure and 0 on success.
โจ int ESECT mdb_env_get_path (MDB_env * env, const char ** path)
int ESECT mdb_env_get_path (MDB_env * env, const char ** path)
Return the path that was used in mdb_env_open(). ๐ค๏ธ
Parameters
envโ An environment handle returned bymdb_env_create()pathโ Address of a string pointer to contain the path. This is the actual string in the environment, not a copy. It should not be altered in any way. ๐ซ
Returns
A non-zero error value on failure and 0 on success. Some possible errors are:
EINVALโ an invalid parameter was specified.
โจ int ESECT mdb_env_get_fd (MDB_env * env, mdb_filehandle_t * fd)
int ESECT mdb_env_get_fd (MDB_env * env, mdb_filehandle_t * fd)
Return the filedescriptor for the given environment. This function may be called after fork(), so the descriptor can be closed before exec*(). Other LMDB file descriptors have FD_CLOEXEC. (Until LMDB 0.9.18, only the lockfile had that.) ๐ฏ
Parameters
envโ An environment handle returned bymdb_env_create()fdโ Address of amdb_filehandle_tto contain the descriptor.
Returns
A non-zero error value on failure and 0 on success. Some possible errors are:
EINVALโ an invalid parameter was specified.
โจ int ESECT mdb_stat0 (MDB_env * env, MDB_db * db, MDB_stat * arg) [static]
int ESECT mdb_stat0 (MDB_env * env, MDB_db * db, MDB_stat * arg)
Common code for mdb_stat() and mdb_env_stat(). shared brain cell energy
Parameters
envโ the environment to operate in.dbโ theMDB_dbrecord containing the stats to return.argโ the address of anMDB_statstructure to receive the stats.
Returns
0, this function always succeeds. ๐
โจ int ESECT mdb_env_stat (MDB_env * env, MDB_stat * stat)
int ESECT mdb_env_stat (MDB_env * env, MDB_stat * stat)
Return statistics about the LMDB environment. ๐
Parameters
envโ An environment handle returned bymdb_env_create()statโ The address of anMDB_statstructure where the statistics will be copied
โจ int ESECT mdb_env_info (MDB_env * env, MDB_envinfo * stat)
int ESECT mdb_env_info (MDB_env * env, MDB_envinfo * stat)
Return information about the LMDB environment. โน๏ธ
Parameters
envโ An environment handle returned bymdb_env_create()statโ The address of anMDB_envinfostructure where the information will be copied
โจ int mdb_dbi_open (MDB_txn * txn, const char * name, unsigned int flags, MDB_dbi * dbi)
int mdb_dbi_open (MDB_txn * txn, const char * name, unsigned int flags, MDB_dbi * dbi)
Open a database in the environment. A database handle denotes the name and parameters of a database, independently of whether such a database exists. The database handle may be discarded by calling mdb_dbi_close(). The old database handle is returned if the database was already open. The handle may only be closed once. ๐
The database handle will be private to the current transaction until the transaction is successfully committed. If the transaction is aborted the handle will be closed automatically. After a successful commit the handle will reside in the shared environment, and may be used by other transactions. โจ
This function must not be called from multiple concurrent transactions in the same process. A transaction that uses this function must finish (either commit or abort) before any other transaction in the process may use this function. โ ๏ธ concurrency girlies, this one is not for you
To use named databases (with name != NULL), mdb_env_set_maxdbs() must be called before opening the environment. Database names are keys in the unnamed database, and may be read but not written. ๐๏ธ
๐ซถ Parameters ๐ซถ
txnโ a transaction handle thatmdb_txn_begin()handed you, bestie ๐nameโ the name of the database you wanna open. If the environment only has a single database going on, this can literally just beNULL. Slay.flagsโ special options for this database. You must set this to0, or OR together one or more of the values we're about to list. No in-between, no vibes-based guessing ๐MDB_REVERSEKEYโ keys are strings that get compared in reverse order, like end-of-string to start-of-string. By default, keys are treated as strings and compared from beginning to end.MDB_DUPSORTโ duplicate keys are allowed in the database. (Or, if you flip the POV: keys can have multiple data items, and those are stored in sorted order.) By default, keys have to be unique and can only hold a single data item.MDB_INTEGERKEYโ keys are binary integers in native byte order, likeunsigned intorsize_t, and they get sorted that way. Heads up: the keys must all be the same size, no cap ๐งMDB_DUPFIXEDโ okay so this one can only be used in combination withMDB_DUPSORT. It tells the library that the data items in this database are all the same size, which unlocks further optimizations in storage and retrieval. And when all the data items are the same size, you can use theMDB_GET_MULTIPLE,MDB_NEXT_MULTIPLEandMDB_PREV_MULTIPLEcursor operations to grab multiple items at once. Iconic, honestly.MDB_INTEGERDUPโ this says the duplicate data items are binary integers, similar to whatMDB_INTEGERKEYdoes for keys.MDB_REVERSEDUPโ this one says duplicate data items should be compared as strings, in reverse order.MDB_CREATEโ create the named database if it doesn't already exist. Not allowed in a read-only transaction or a read-only environment, so don't try it ๐
dbiโ the address where the newMDB_dbihandle is gonna be stored
Returns
A non-zero error value on failure and 0 on success. Some possible errors you might run into:
MDB_NOTFOUNDโ the database you asked for doesn't exist in the environment and you didn't specifyMDB_CREATE. Rude, but okay.MDB_DBS_FULLโ too many databases have been opened. Go look atmdb_env_set_maxdbs().
๐ int ESECT mdb_stat (MDB_txn * txn, MDB_dbi dbi, MDB_stat * stat)
Retrieve the stats for a database. Numbers girlies rise up ๐
Parameters
txnโ a transaction handle returned bymdb_txn_begin()dbiโ a database handle returned bymdb_dbi_open()statโ the address of anMDB_statstructure where the statistics will be copied
Returns
A non-zero error value on failure and 0 on success. Some possible errors are:
EINVALโ an invalid parameter was specified.
๐
void mdb_dbi_close (MDB_env * env, MDB_dbi dbi)
Close a database handle. Normally unnecessary, so don't be out here closing handles for fun.
โ ๏ธ Use with care: this call is not mutex protected. Handles should only be closed by a single thread, and only if no other threads are gonna reference the database handle โ or one of its cursors โ ever again. Do not close a handle if an existing transaction has modified its database. Doing so can cause misbehavior ranging from database corruption all the way to errors like MDB_BAD_VALSIZE (because the DB name is gone). Truly giving chaos ๐
Closing a database handle isn't necessary, but it does let mdb_dbi_open() reuse the handle value. Usually it's better to just set a bigger mdb_env_set_maxdbs(), unless that value would be large.
Parameters
envโ an environment handle returned bymdb_env_create()dbiโ a database handle returned bymdb_dbi_open()
๐ฆ int mdb_dbi_flags (MDB_txn * txn, MDB_dbi dbi, unsigned int * flags)
Retrieve the DB flags for a database handle. Little peek behind the curtain, no cap ๐
Parameters
txnโ a transaction handle returned bymdb_txn_begin()dbiโ a database handle returned bymdb_dbi_open()flagsโ address where the flags will be returned
Returns
A non-zero error value on failure and 0 on success.
๐ int mdb_drop (MDB_txn * txn, MDB_dbi dbi, int del)
Empty or delete+close a database. For restrictions about closing the DB handle, go read mdb_dbi_close() โ it's important, bestie ๐ซถ
Parameters
txnโ a transaction handle returned bymdb_txn_begin()dbiโ a database handle returned bymdb_dbi_open()delโ0to empty the DB,1to delete it from the environment and close the DB handle
Returns
A non-zero error value on failure and 0 on success.
๐ฅ int mdb_set_compare (MDB_txn * txn, MDB_dbi dbi, MDB_cmp_func * cmp)
Set a custom key comparison function for a database. This comparison function gets called whenever it's necessary to compare a key that the application specified against a key currently stored in the database. If no comparison function is specified, and no special key flags were given to mdb_dbi_open(), the keys get compared lexically, with shorter keys collating before longer keys. Periodt.
๐จ Warning: this function must be called before any data access functions are used, otherwise data corruption may occur. The same comparison function must be used by every program accessing the database, every single time the database is used. No exceptions, not even for the main character.
Parameters
txnโ a transaction handle returned bymdb_txn_begin()dbiโ a database handle returned bymdb_dbi_open()cmpโ anMDB_cmp_funcfunction
Returns
A non-zero error value on failure and 0 on success. Some possible errors are:
EINVALโ an invalid parameter was specified.
โจ int mdb_set_dupsort (MDB_txn * txn, MDB_dbi dbi, MDB_cmp_func * cmp)
Set a custom data comparison function for an MDB_DUPSORT database. This one gets called whenever it's necessary to compare a data item specified by the application against a data item currently stored in the database. It only takes effect if the database was opened with the MDB_DUPSORT flag. If no comparison function is specified, and no special key flags were specified with mdb_dbi_open(), the data items get compared lexically, with shorter items collating before longer items. Same energy as the key version, just for the data ๐
๐จ Warning: this function must be called before any data access functions are used, otherwise data corruption may occur. The same comparison function must be used by every program accessing the database, every time the database is used.
Parameters
txnโ a transaction handle returned bymdb_txn_begin()dbiโ a database handle returned bymdb_dbi_open()cmpโ anMDB_cmp_funcfunction
Returns
A non-zero error value on failure and 0 on success. Some possible errors are:
EINVALโ an invalid parameter was specified.
๐ง int mdb_set_relfunc (MDB_txn * txn, MDB_dbi dbi, MDB_rel_func * rel)
Set a relocation function for an MDB_FIXEDMAP database.
๐ Todo: the relocation function is called whenever it's necessary to move the data of an item to a different position in the database (like through tree balancing operations, shifts as a result of adds or deletes, etc.). It's intended to let address/position-dependent data items be stored in a database inside an environment opened with the MDB_FIXEDMAP option. Currently the relocation feature is unimplemented and setting this function has no effect. Yeah. It's giving placeholder ๐ญ
Parameters
txnโ a transaction handle returned bymdb_txn_begin()dbiโ a database handle returned bymdb_dbi_open()relโ anMDB_rel_funcfunction
Returns
A non-zero error value on failure and 0 on success. Some possible errors are:
EINVALโ an invalid parameter was specified.
๐ int mdb_set_relctx (MDB_txn * txn, MDB_dbi dbi, void * ctx)
Set a context pointer for an MDB_FIXEDMAP database's relocation function. For more details, go see mdb_set_relfunc and MDB_rel_func. iykyk ๐ธ
Parameters
txnโ a transaction handle returned bymdb_txn_begin()dbiโ a database handle returned bymdb_dbi_open()ctxโ an arbitrary pointer for whatever the application needs. It'll be passed to the callback function set bymdb_set_relfuncas its relctx parameter whenever the callback is invoked.
Returns
A non-zero error value on failure and 0 on success. Some possible errors are:
EINVALโ an invalid parameter was specified.
๐ int ESECT mdb_env_get_maxkeysize (MDB_env * env)
Get the maximum size of keys and MDB_DUPSORT data that we can write. It depends on the compile-time constant MDB_MAXKEYSIZE. Default is 511. See MDB_val, bestie ๐
Parameters
envโ an environment handle returned bymdb_env_create()
Returns
The maximum size of a key we can write.
๐ int ESECT mdb_reader_list (MDB_env * env, MDB_msg_func * func, void * ctx)
Dump the entries in the reader lock table. Receipts, basically ๐งพ
Parameters
envโ an environment handle returned bymdb_env_create()funcโ anMDB_msg_funcfunctionctxโ anything the message function needs
Returns
< 0 on failure, >= 0 on success.
๐ int ESECT mdb_pid_insert (MDB_PID_T * ids, MDB_PID_T pid) [static]
Insert pid into the list if it's not already present. Returns -1 if it's already present. Simple as that โจ
๐ int ESECT mdb_reader_check (MDB_env * env, int * dead)
Check for stale entries in the reader lock table. Cleaning up the group chat ๐งน
Parameters
envโ an environment handle returned bymdb_env_create()deadโ number of stale slots that were cleared
Returns
0 on success, non-zero on failure.
๐ Variable Documentation ๐
okay bestie we made it to the very last stretch, and it's just the two little globals that LMDB uses to keep itself honest โจ
char* const mdb_errstr[] [static]
Not me showing you the initial value because that's literally where all the โจloreโจ lives:
= {
"MDB_KEYEXIST: Key/data pair already exists",
"MDB_NOTFOUND: No matching key/data pair found",
"MDB_PAGE_NOTFOUND: Requested page not found",
"MDB_CORRUPTED: Located page was wrong type",
"MDB_PANIC: Update of meta page failed or environment had fatal error",
"MDB_VERSION_MISMATCH: Database environment version mismatch",
"MDB_INVALID: File is not an LMDB file",
"MDB_MAP_FULL: Environment mapsize limit reached",
"MDB_DBS_FULL: Environment maxdbs limit reached",
"MDB_READERS_FULL: Environment maxreaders limit reached",
"MDB_TLS_FULL: Thread-local storage keys full - too many environments open",
"MDB_TXN_FULL: Transaction has too many dirty pages - transaction too big",
"MDB_CURSOR_FULL: Internal error - cursor stack limit reached",
"MDB_PAGE_FULL: Internal error - page has no more space",
"MDB_MAP_RESIZED: Database contents grew beyond environment mapsize",
"MDB_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed",
"MDB_BAD_RSLOT: Invalid reuse of reader locktable slot",
"MDB_BAD_TXN: Transaction must abort, has a child, or is invalid",
"MDB_BAD_VALSIZE: Unsupported size of key/DB name/data, or wrong DUPFIXED size",
"MDB_BAD_DBI: The specified DBI handle was closed/changed unexpectedly",
}
So this is the Table of descriptions for LMDB Return Codes โ every return code LMDB can throw at you, and the exact human-readable sentence that comes attached to it. If you've ever stared at a weird number coming back from a call and gone "girl what does that mean", this array is where the answer was hiding the whole time. ๐ซถ
const mdb_nchar_t* const mdb_suffixes[2][2] [static]
And here's its initial value, no gatekeeping here ๐
= {
{ MDB_NAME("/data.mdb"), MDB_NAME("") },
{ MDB_NAME("/lock.mdb"), MDB_NAME("-lock") }
}
This one is the Filename suffixes table, indexed as [datafile,lockfile][without,with MDB_NOSUBDIR]. So like โ first index picks which file (the data file or the lock file), second index picks which mode you're in (the normal subdirectory vibe, or the MDB_NOSUBDIR vibe). That's it, that's the whole grid. Two by two, four little strings, and they decide what your files on disk are actually called. iconic behavior honestly ๐ธ
โจ Author โจ
Generated automatically by Doxygen for LMDB from the source code.
and that's a wrap on the whole page bestie ๐ญ๐ it came from LMDB, it's the internal(3) manual page, and it was cooked up automatically by Doxygen straight from the source code โ no human hand-typed any of this, it just appeared, like magic. go forth and slay your transactions ๐งโจ๐
๐ฆ where this page comes from
- ubuntu stonking: lmdb-doc 0.9.35-1 ยท OpenLDAP-2.8
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms