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_page
  • struct MDB_page2
  • struct MDB_node
  • struct MDB_db
  • struct MDB_meta
  • union MDB_metabuf
  • struct MDB_dbx
  • struct MDB_txn โ€” Opaque structure for a transaction handle.
  • struct MDB_cursor โ€” Opaque structure for navigating through a database.
  • struct MDB_xcursor
  • struct MDB_pgstate
  • struct MDB_env โ€” Opaque structure for a database environment.
  • struct MDB_ntxn
  • struct MDB_name
  • struct 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's MDB_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 the MDB_env ๐Ÿ“Ž
  • void *ESECT mdb_env_get_userctx (MDB_env *env) โ€” gets the application information associated with the MDB_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 in mdb_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 a MDB_DUPSORT database. dupsort girlies rise
  • int mdb_set_relfunc (MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel) โ€” set a relocation function for a MDB_FIXEDMAP database. relocate, periodt.
  • int mdb_set_relctx (MDB_txn *txn, MDB_dbi dbi, void *ctx) โ€” set a context pointer for a MDB_FIXEDMAP database's relocation function. context? we love context.
  • int ESECT mdb_env_get_maxkeysize (MDB_env *env) โ€” get the maximum size of keys and MDB_DUPSORT data 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 hi
  • uint16_t MDB_page::mp_pad โ€” key size if this is a LEAF2 page LEAF2 coded
  • uint16_t MDB_page::mp_flags โ€” Page Flags flags era
  • indx_t MDB_page::pb_lower โ€” lower bound of free space lower bound, lower stress
  • indx_t MDB_page::pb_upper โ€” upper bound of free space upper bound, upper bless
  • uint32_t MDB_page::pb_pages โ€” number of overflow pages overflow? we been knew
  • indx_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 fierce
  • unsigned short MDB_node::mn_hi โ€” part of data size or pgno hi bestie
  • unsigned 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 queen
  • uint16_t MDB_db::md_flags โ€” Database Flags flags, but make it database
  • uint16_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 thoughts
  • pgno_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 counted
  • pgno_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 to MDB_MAGIC. magic must be magic โœจ
  • uint32_t MDB_meta::mm_version โ€” Version number of this file. Must be set to MDB_DATA_VERSION. version check bestie
  • void* MDB_meta::mm_address โ€” address for fixed mapping address? we're not doxxing
  • size_t MDB_meta::mm_mapsize โ€” size of mmap region mmap size, big brain
  • MDB_db MDB_meta::mm_dbs[CORE_DBS] โ€” first is free space, 2nd is main db first free, second main โ€” order matters
  • pgno_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 cap
  • MDB_cmp_func* MDB_dbx::md_dcmp โ€” function for comparing data items compare data, data queen
  • MDB_rel_func* MDB_dbx::md_rel โ€” user relocate function user relocate? she moves.
  • void* MDB_dbx::md_relctx โ€” user-provided context for md_rel context 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 tree
  • MDB_txn* MDB_txn::mt_child โ€” Nested txn under this txn, set together with flag MDB_TXN_HAS_CHILD child txn, nepo baby
  • pgno_t MDB_txn::mt_next_pgno โ€” next unallocated page next page, unallocated and ready
  • txnid_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 vibe
  • MDB_IDL MDB_txn::mt_free_pgs โ€” The list of pages that became unused during this transaction. free pages from this txn
  • MDB_page* MDB_txn::mt_loose_pgs โ€” The list of loose pages that became unused and may be reused in this transaction, linked through NEXT_LOOSE_PAGE(page). loose pages, linked through NEXT_LOOSE_PAGE(page) โ€” iykyk
  • int MDB_txn::mt_loose_count โ€” Number of loose pages (mt_loose_pgs) count them loose pages
  • MDB_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 not MDB_WRITEMAP. dirty list for write txns, sorted unless MDB_WRITEMAP
  • MDB_reader* MDB_txn::reader โ€” For read txns: This thread/txn's reader table slot, or NULL. reader slot for read txns, or NULL โ€” she's optional
  • MDB_dbx* MDB_txn::mt_dbxs โ€” Array of records for each DB known in the environment. array of dbx records, one per known DB
  • MDB_db* MDB_txn::mt_dbs โ€” Array of MDB_db records for each known DB array of MDB_db records
  • unsigned int* MDB_txn::mt_dbiseqs โ€” Array of sequence numbers for each DB handle array of sequence numbers, per handle
  • MDB_cursor** MDB_txn::mt_cursors โ€” In write txns, array of cursors for each DB write txns get an array of cursors per DB
  • unsigned char* MDB_txn::mt_dbflags โ€” Array of flags for each DB array of flags, per DB
  • MDB_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, slay
  • unsigned 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 into mt_parent after freeing hidden mt_parent pages. 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_next
  • MDB_cursor * mc_backup
  • struct MDB_xcursor * mc_xcursor
  • MDB_txn * mc_txn
  • MDB_dbi mc_dbi
  • MDB_db * mc_db
  • MDB_dbx * mc_dbx
  • unsigned char * mc_dbflag
  • unsigned short mc_snum
  • unsigned short mc_top
  • unsigned int mc_flags
  • MDB_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_cursor
  • MDB_db mx_db
  • MDB_dbx mx_dbx
  • unsigned 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_pghead
  • txnid_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_fd
  • HANDLE me_lfd
  • HANDLE me_mfd
  • uint32_t me_flags
  • unsigned int me_psize
  • unsigned int me_os_psize
  • unsigned int me_maxreaders
  • volatile int me_close_readers
  • MDB_dbi me_numdbs
  • MDB_dbi me_maxdbs
  • MDB_PID_T me_pid
  • char * me_path
  • char * me_map
  • MDB_txninfo * me_txns
  • MDB_meta * me_metas [NUM_METAS]
  • void * me_pbuf
  • MDB_txn * me_txn
  • MDB_txn * me_txn0
  • size_t me_mapsize
  • off_t me_size
  • pgno_t me_maxpg
  • MDB_dbx * me_dbxs
  • uint16_t * me_dbflags
  • unsigned int * me_dbiseqs
  • pthread_key_t me_txkey
  • txnid_t me_pgoldest
  • MDB_pgstate me_pgstate
  • MDB_page * me_dpages
  • MDB_IDL me_free_pgs
  • MDB_ID2L me_dirty_list
  • int me_maxfree_1pg
  • unsigned int me_nodemax
  • int me_live_reader
  • void * me_userctx
  • MDB_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_txn
  • MDB_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_len
  • int mn_alloced
  • mdb_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_env
  • MDB_txn * mc_txn
  • pthread_mutex_t mc_mutex
  • pthread_cond_t mc_cond
  • char * mc_wbuf [2]
  • char * mc_over [2]
  • size_t mc_wlen [2]
  • size_t mc_olen [2]
  • pgno_t mc_next_pgno
  • HANDLE mc_fd
  • int mc_toggle
  • int mc_new
  • volatile 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 If O_DSYNC is 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 RDONLY me_fd
  • MDB_O_RDWR โ€” for me_fd
  • MDB_O_META โ€” for me_mfd
  • MDB_O_COPY โ€” for mdb_env_copy()
  • MDB_O_MASK โ€” Bitmask for open() flags in enum mdb_fopen_type. The other bits distinguish otherwise-equal MDB_O_* constants from each other ๐Ÿ”Ž
  • MDB_O_LOCKS โ€” for me_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 usually 1, unless allocating overflow pages for a large record ๐Ÿ“
  • mp โ€” Address of a page, or NULL on 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 end
  • mode โ€” 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.


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, or NULL for first/last page.
  • flags โ€” If MDB_PS_MODIFY is set, visited pages in the DB are touched (updated with new page numbers). If MDB_PS_FIRST or MDB_PS_LAST is set, find first or last leaf. This is used by mdb_cursor_first() and mdb_cursor_last(). If MDB_PS_ROOTONLY set, 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 โ€” The NODE_ADD_FLAGS for 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 handle
  • meta โ€” 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 * 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 a MDB_DUPFIXED database.

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 the MDB_db record 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_DUPDATA item.

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 by mdb_txn_begin()
  • dbi โ€” A database handle returned by mdb_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 function strerror(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 by mdb_txn_begin()
  • dbi โ€” A database handle returned by mdb_dbi_open()
  • a โ€” The first item to compare
  • b โ€” 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 by mdb_txn_begin()
  • dbi โ€” A database handle returned by mdb_dbi_open()
  • a โ€” The first item to compare
  • b โ€” 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_DIRTY to set P_KEEP, P_DIRTY|P_KEEP to clear it.
  • all โ€” No shortcuts. Needed except after a full mdb_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 committed
  • keep โ€” number of initial pages in dirty_list to 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 ๐Ÿ˜ญ:

  1. our estimate of the txn size could be too small. Currently this seems unlikely, except with a large number of MDB_MULTIPLE items.
  2. 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's dirty_room is 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 by mdb_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 ๐Ÿ’–)

  • m0 cursor โ€” 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. ret is left unchanged if mp wasn'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 by mdb_env_create().
  • force โ€” if non-zero, force a synchronous flush. Otherwise, if the environment has the MDB_NOSYNC flag set, the flushes will be omitted, and with MDB_MAPASYNC they'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 โ€” true to keep changes to parent cursors, false to 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 by mdb_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 by mdb_env_create().
  • parent โ€” if this parameter is non-NULL, the new transaction will be a nested transaction, with the transaction indicated by parent as its parent. Transactions may be nested to any level. A parent transaction and its cursors may not issue any other operations than mdb_txn_commit and mdb_txn_abort while it has active child transactions.
  • flags โ€” special options for this transaction. This parameter must be set to 0 or by bitwise OR'ing together one or more of the values described here.
    • MDB_RDONLY โ€” this transaction will not perform any write operations.
  • txn โ€” address where the new MDB_txn handle 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 this MDB_env's mapsize and this environment's map must be resized as well. See mdb_env_set_mapsize().
  • MDB_READERS_FULL โ€” a read-only transaction was requested and the reader lock table is full. See mdb_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 by mdb_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 by mdb_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 by mdb_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 by mdb_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 by mdb_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 โ€” the MDB_meta to 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 by mdb_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 after mdb_env_create() and before mdb_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 by mdb_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 after mdb_env_create() and before mdb_env_open().

Parameters

  • env โ€” an environment handle returned by mdb_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 by mdb_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 to mdb_env_open() ๐Ÿ’–
  • envflags โ€” tells ya whether a subdir and/or a lockfile is gonna be used
  • fname โ€” 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 of mdb_fname_init(). A suffix gets appended if it's needed to actually make the filename, but without touching mn_len ๐Ÿ™ˆ
  • which โ€” decides the file type, the access mode, all that jazz
  • mode โ€” the Unix permissions for the file, if we end up creating it
  • res โ€” 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 lock
  • 0 โ€” shared
  • 1 โ€” 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, from mdb_fname_init()
  • mode โ€” the Unix permissions for the file, if we create it
  • excl โ€” in comes a lock type, out goes a lock type: -1 none, 0 shared, 1 exclusive

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 the MDB_env handle. No leaving it lying around, bestie.

Parameters

  • env โ€” an environment handle that came back from mdb_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 to 0, or you bitwise-OR together one or more of the values described here. Flags set by mdb_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 in path, and it creates its data and lock files under that directory. With this option, path gets used as-is for the database main data file. The database lock file is the path with "-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 unless MDB_RDONLY is set. This uses fewer mallocs 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 without MDB_WRITEMAP on the same environment. This can defeat durability (mdb_env_sync etc) ๐Ÿ˜ญ
    • 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_RDONLY commit, or mdb_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 using mdb_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 often mdb_env_sync() is called ๐Ÿซฃ However, if the filesystem preserves write order and the MDB_WRITEMAP flag is not used, transactions exhibit ACI (atomicity, consistency, isolation) properties and only lose D (durability). I.e. database integrity is maintained, but a system crash may undo the final transactions. Note that (MDB_NOSYNC | MDB_WRITEMAP) leaves the system with no hint for when to write transactions to disk, unless mdb_env_sync() is called. (MDB_MAPASYNC | MDB_WRITEMAP) may be preferable โœจ This flag can be changed at any time using mdb_env_set_flags()
    • MDB_MAPASYNC โ€” when using MDB_WRITEMAP, use asynchronous flushes to disk. Same as with MDB_NOSYNC, a system crash can then corrupt the database or lose the last transactions ๐Ÿ˜ต Calling mdb_env_sync() ensures on-disk database integrity until the next commit. This flag can be changed at any time using mdb_env_set_flags()
    • MDB_NOTLS โ€” don't use Thread-Local Storage. Tie reader locktable slots to MDB_txn objects instead of to threads. I.e. mdb_txn_reset() keeps the slot reserved for the MDB_txn object ๐Ÿงท A thread may use parallel read-only transactions. A read-only transaction may span threads if the user synchronizes its use. Applications that multiplex many user threads over individual OS threads need this option. Such an application must also serialize the write transactions in an OS thread, since LMDB's write locking is unaware of the user threads ๐Ÿงต
    • 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 begins
    • MDB_NORDAHEAD โ€” turn off readahead. Most operating systems perform readahead on read requests by default. This option turns it off if the OS supports it. Turning it off may help random read performance when the DB is larger than RAM and system RAM is full ๐ŸŒ The option is not implemented on Windows
    • MDB_NOMEMINIT โ€” don't initialize malloc'd memory before writing to unused spaces in the data file. By default, memory for pages written to the data file is obtained using malloc. While these pages may be reused in subsequent transactions, freshly malloc'd pages will be initialized to zeroes before use. This avoids persisting leftover data from other code (that used the heap and subsequently freed the memory) into the data file ๐Ÿงผ Note that many other system libraries may allocate and free memory from the heap for arbitrary uses. E.g., stdio may use the heap for file I/O buffers. This initialization step has a modest performance cost, so some applications may want to disable it using this flag. This option can be a problem for applications which handle sensitive data like passwords ๐Ÿ” and it makes memory checkers like Valgrind noisy. This flag is not needed with MDB_WRITEMAP, which writes directly to the mmap instead of using malloc for pages. The initialization is also skipped if MDB_RESERVE is 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 using mdb_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 environment
  • MDB_INVALID โ€” the environment file headers are corrupted ๐Ÿ’€
  • ENOENT โ€” the directory specified by the path parameter doesn't exist
  • EACCES โ€” the user didn't have permission to access the environment files
  • EAGAIN โ€” the environment was locked by another process ๐Ÿ”’

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 by mdb_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 from mdb_txn_begin()
  • dbi โ€” a database handle that came from mdb_dbi_open()
  • key โ€” the key you're searching for in the database
  • data โ€” 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 from mdb_cursor_open()
  • key โ€” the key for a retrieved item
  • data โ€” the data of a retrieved item
  • op โ€” a cursor operation, an MDB_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 from mdb_cursor_open()
  • key โ€” the key operated on.
  • data โ€” the data operated on.
  • flags โ€” options for this operation. This parameter must be set to 0 or one of the values described here.
    • MDB_CURRENT โ€” replace the item at the current cursor position. The key parameter 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 with MDB_DUPSORT. The function returns MDB_KEYEXIST if 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 returns MDB_KEYEXIST if 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 extra memcpy if the data is being generated later. This flag must not be specified if the database was opened with MDB_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 an MDB_KEYEXIST error. 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 with MDB_DUPFIXED. The data argument must be an array of two MDB_vals. The mv_size of the first MDB_val must be the size of a single data element. The mv_data of the first MDB_val must point to the beginning of the array of contiguous data elements. The mv_size of the second MDB_val must 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. The mv_data of the second MDB_val is unused.

Returns

Non-zero error value on failure, 0 on success. Some possible errors:

  • MDB_MAP_FULL โ€” the database is full, go see mdb_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

๐Ÿฆ‹ 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 from mdb_cursor_open()
  • flags โ€” options for this operation. This parameter must be set to 0 or 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 with MDB_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 transaction
  • EINVAL โ€” 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 from mdb_txn_begin()
  • dbi โ€” a database handle that came from mdb_dbi_open()
  • cursor โ€” address where the new MDB_cursor handle 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 from mdb_txn_begin()
  • cursor โ€” a cursor handle that came from mdb_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 from mdb_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 from mdb_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 from mdb_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 from mdb_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), the data parameter is ignored. Straight up ignored, she said nothing ๐Ÿซฅ
  • If the database does support sorted duplicates and the data parameter is NULL, all of the duplicate data items for the key will be deleted. Mass deletion, no survivors.
  • Otherwise, if the data parameter 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 from mdb_txn_begin()
  • dbi โ€” a database handle that came from mdb_dbi_open()
  • key โ€” the key to delete from the database
  • data โ€” 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 transaction
  • EINVAL โ€” 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 from mdb_txn_begin()
  • dbi โ€” a database handle that came from mdb_dbi_open()
  • key โ€” the key to store in the database
  • data โ€” the data to store
  • flags โ€” 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 with MDB_DUPSORT. If the key/data pair is already in there, the function returns MDB_KEYEXIST ๐Ÿ™‚
  • MDB_NOOVERWRITE โ€” only enters the new key/data pair if the key doesn't already exist in the database. Function returns MDB_KEYEXIST if the key is already there, even if the database supports duplicates (MDB_DUPSORT). And the data parameter 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 extra memcpy if 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 with MDB_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 a MDB_KEYEXIST error. โš ๏ธ
  • 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, see mdb_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 โ€” (1 to hand off 1 buffer) | (MDB_EOF when 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 โ€” includes F_DUPDATA if 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 by mdb_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 to 0 or 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 by mdb_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 by mdb_env_create()
  • flags โ€” The flags to change, bitwise OR'ed together
  • onoff โ€” 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 by mdb_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 by mdb_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 by mdb_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 by mdb_env_create().
  • func โ€” An MDB_assert_func function, or 0.

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 by mdb_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 by mdb_env_create()
  • fd โ€” Address of a mdb_filehandle_t to 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 โ€” the MDB_db record containing the stats to return.
  • arg โ€” the address of an MDB_stat structure 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 by mdb_env_create()
  • stat โ€” The address of an MDB_stat structure 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 by mdb_env_create()
  • stat โ€” The address of an MDB_envinfo structure 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 that mdb_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 be NULL. Slay.
  • flags โ€” special options for this database. You must set this to 0, 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, like unsigned int or size_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 with MDB_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 the MDB_GET_MULTIPLE, MDB_NEXT_MULTIPLE and MDB_PREV_MULTIPLE cursor operations to grab multiple items at once. Iconic, honestly.
    • MDB_INTEGERDUP โ€” this says the duplicate data items are binary integers, similar to what MDB_INTEGERKEY does 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 new MDB_dbi handle 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 specify MDB_CREATE. Rude, but okay.
  • MDB_DBS_FULL โ€” too many databases have been opened. Go look at mdb_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 by mdb_txn_begin()
  • dbi โ€” a database handle returned by mdb_dbi_open()
  • stat โ€” the address of an MDB_stat structure 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 by mdb_env_create()
  • dbi โ€” a database handle returned by mdb_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 by mdb_txn_begin()
  • dbi โ€” a database handle returned by mdb_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 by mdb_txn_begin()
  • dbi โ€” a database handle returned by mdb_dbi_open()
  • del โ€” 0 to empty the DB, 1 to 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 by mdb_txn_begin()
  • dbi โ€” a database handle returned by mdb_dbi_open()
  • cmp โ€” an MDB_cmp_func function

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 by mdb_txn_begin()
  • dbi โ€” a database handle returned by mdb_dbi_open()
  • cmp โ€” an MDB_cmp_func function

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 by mdb_txn_begin()
  • dbi โ€” a database handle returned by mdb_dbi_open()
  • rel โ€” an MDB_rel_func function

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 by mdb_txn_begin()
  • dbi โ€” a database handle returned by mdb_dbi_open()
  • ctx โ€” an arbitrary pointer for whatever the application needs. It'll be passed to the callback function set by mdb_set_relfunc as 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 by mdb_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 by mdb_env_create()
  • func โ€” an MDB_msg_func function
  • ctx โ€” 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 by mdb_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