---
name: "mdb_internal"
section: "3"
platform: "linux"
package: "lmdb-doc"
version: "0.9.31-1"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/mdb_internal"
---

# mdb\_internal(3)

LMDB Internals

## NAME

internal - LMDB Internals

## SYNOPSIS

### Modules

**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

\#define **LOCK\_MUTEX**(rc,  env,  mutex)   ((rc) = **LOCK\_MUTEX0**(mutex))\
 \#define **mdb\_mutex\_failed**(env,  mutex,  rc)   (rc)\
 \#define **MDB\_DSYNC**   O\_SYNC\
 \#define **MDB\_FDATASYNC**   fdatasync\
 \#define **MDB\_MSYNC**(addr,  len,  flags)   msync(addr,len,flags)\
 \#define **MS\_SYNC**   1\
 \#define **MS\_ASYNC**   0\
 \#define **MAX\_PAGESIZE**   (**PAGEBASE** ? 0x10000 : 0x8000)\
 The maximum size of a database page.  #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)\
 The max size of a key we can write, or 0 for computed max.  #define **ENV\_MAXKEY**(env)   (**MDB\_MAXKEYSIZE**)\
 \#define **MAXDATASIZE**   0xffffffffUL\
 The maximum size of a data item.  #define **DKBUF**\
 \#define **DKEY**(x)   0\
 \#define **P\_INVALID**   (~(**pgno\_t**)0)\
 \#define **F\_ISSET**(w,  f)   (((w) & (f)) == (f))\
 \#define **EVEN**(n)   (((n) + 1U) & -2) /\* sign-extending -2 to match n+1U \*/\
 \#define **DEFAULT\_MAPSIZE**   1048576\
 \#define **MP\_PGNO**(p)   (((**MDB\_page2** \*)(void \*)(p))-\>mp2\_p)\
 \#define **MP\_PAD**(p)   (((**MDB\_page2** \*)(void \*)(p))-\>mp2\_pad)\
 \#define **MP\_FLAGS**(p)   (((**MDB\_page2** \*)(void \*)(p))-\>mp2\_flags)\
 \#define **MP\_LOWER**(p)   (((**MDB\_page2** \*)(void \*)(p))-\>mp2\_lower)\
 \#define **MP\_UPPER**(p)   (((**MDB\_page2** \*)(void \*)(p))-\>mp2\_upper)\
 \#define **MP\_PTRS**(p)   (((**MDB\_page2** \*)(void \*)(p))-\>mp2\_ptrs)\
 \#define **PAGEHDRSZ**   ((unsigned) offsetof(**MDB\_page**, mp\_ptrs))\
 \#define **METADATA**(p)   ((void \*)((char \*)(p) + **PAGEHDRSZ**))\
 \#define **PAGEBASE**   ((**MDB\_DEVEL**) ? **PAGEHDRSZ** : 0)\
 \#define **NUMKEYS**(p)   ((MP\_LOWER(p) - (**PAGEHDRSZ**-**PAGEBASE**)) \>\> 1)\
 \#define **SIZELEFT**(p)   (**indx\_t**)(MP\_UPPER(p) - MP\_LOWER(p))\
 \#define **PAGEFILL**(env,  p)\
 \#define **FILL\_THRESHOLD**   250\
 \#define **IS\_LEAF**(p)   **F\_ISSET**(MP\_FLAGS(p), **P\_LEAF**)\
 \#define **IS\_LEAF2**(p)   **F\_ISSET**(MP\_FLAGS(p), **P\_LEAF2**)\
 \#define **IS\_BRANCH**(p)   **F\_ISSET**(MP\_FLAGS(p), **P\_BRANCH**)\
 \#define **IS\_OVERFLOW**(p)   **F\_ISSET**(MP\_FLAGS(p), **P\_OVERFLOW**)\
 \#define **IS\_SUBP**(p)   **F\_ISSET**(MP\_FLAGS(p), **P\_SUBP**)\
 \#define **OVPAGES**(size,  psize)   ((**PAGEHDRSZ**-1 + (size)) / (psize) + 1)\
 \#define **NEXT\_LOOSE\_PAGE**(p)   (\*(**MDB\_page** \*\*)((p) + 2))\
 \#define **NODESIZE**   offsetof(**MDB\_node**, mn\_data)\
 \#define **PGNO\_TOPWORD**   ((**pgno\_t**)-1 \> 0xffffffffu ? 32 : 0)\
 \#define **INDXSIZE**(k)   (**NODESIZE** + ((k) == NULL ? 0 : (k)-\>mv\_size))\
 \#define **LEAFSIZE**(k,  d)   (**NODESIZE** + (k)-\>mv\_size + (d)-\>mv\_size)\
 \#define **NODEPTR**(p,  i)   ((**MDB\_node** \*)((char \*)(p) + MP\_PTRS(p)\[i\] + **PAGEBASE**))\
 \#define **NODEKEY**(node)   (void \*)((node)-\>mn\_data)\
 \#define **NODEDATA**(node)   (void \*)((char \*)(node)-\>mn\_data + (node)-\>mn\_ksize)\
 \#define **NODEPGNO**(node)\
 \#define **SETPGNO**(node,  pgno)\
 \#define **NODEDSZ**(node)   ((node)-\>mn\_lo \| ((unsigned)(node)-\>mn\_hi \<\< 16))\
 \#define **SETDSZ**(node,  size)\
 \#define **NODEKSZ**(node)   ((node)-\>mn\_ksize)\
 \#define **COPY\_PGNO**(dst,  src)\
 \#define **LEAF2KEY**(p,  i,  ks)   ((char \*)(p) + **PAGEHDRSZ** + ((i)\*(ks)))\
 \#define **MDB\_GET\_KEY**(node,  keyptr)\
 \#define **MDB\_GET\_KEY2**(node,  key)   { key.mv\_size = **NODEKSZ**(node); key.mv\_data = **NODEKEY**(node); }\
 \#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)   	((mc)-\>mc\_xcursor && ((mc)-\>mc\_xcursor-\>mx\_cursor.mc\_flags & **C\_INITIALIZED**))\
 \#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)   	((txn) && (dbi)\<(txn)-\>mt\_numdbs && ((txn)-\>mt\_dbflags\[dbi\] & (validity)))\
 \#define **TXN\_DBI\_CHANGED**(txn,  dbi)   	((txn)-\>mt\_dbiseqs\[dbi\] != (txn)-\>mt\_env-\>me\_dbiseqs\[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)   mdb\_env\_close1(env)\
 \#define **mdb\_cmp\_clong**   **mdb\_cmp\_cint**\
 \#define **mdb\_cassert**(mc,  expr)   mdb\_assert0((mc)-\>mc\_txn-\>mt\_env, expr, #expr)\
 \#define **mdb\_tassert**(txn,  expr)   mdb\_assert0((txn)-\>mt\_env, expr, #expr)\
 \#define **mdb\_eassert**(env,  expr)   mdb\_assert0(env, expr, #expr)\
 \#define **mdb\_assert0**(env,  expr,  expr\_txt)\
 \#define **MDB\_NAME**(str)   str\
 \#define **mdb\_name\_cpy**   strcpy\
 \#define **MDB\_SUFFLEN**   9\
 \#define **mdb\_fname\_destroy**(fname)   	do { if ((fname).mn\_alloced) free((fname).mn\_val); } while (0)\
 \#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\

### Typedefs

typedef **MDB\_ID** **pgno\_t**\
 typedef **MDB\_ID** **txnid\_t**\
 typedef uint16\_t **indx\_t**\
 typedef char **mdb\_nchar\_t**\

### Enumerations

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

static int **mdb\_page\_alloc** (**MDB\_cursor** \*mc, int num, **MDB\_page** \*\*mp)\
 static int **mdb\_page\_new** (**MDB\_cursor** \*mc, uint32\_t flags, int num, **MDB\_page** \*\*mp)\
 static int **mdb\_page\_touch** (**MDB\_cursor** \*mc)\
 static void **mdb\_txn\_end** (**MDB\_txn** \*txn, unsigned mode)\
 static int **mdb\_page\_get** (**MDB\_cursor** \*mc, **pgno\_t** pgno, **MDB\_page** \*\*mp, int \*lvl)\
 static int **mdb\_page\_search\_root** (**MDB\_cursor** \*mc, **MDB\_val** \*key, int modify)\
 static int **mdb\_page\_search** (**MDB\_cursor** \*mc, **MDB\_val** \*key, int flags)\
 static int **mdb\_page\_merge** (**MDB\_cursor** \*csrc, **MDB\_cursor** \*cdst)\
 static int **mdb\_page\_split** (**MDB\_cursor** \*mc, **MDB\_val** \*newkey, **MDB\_val** \*newdata, **pgno\_t** newpgno, unsigned int nflags)\
 static int **mdb\_env\_read\_header** (**MDB\_env** \*env, **MDB\_meta** \*meta)\
 static **MDB\_meta** \* **mdb\_env\_pick\_meta** (const **MDB\_env** \*env)\
 static int **mdb\_env\_write\_meta** (**MDB\_txn** \*txn)\
 static void **mdb\_env\_close0** (**MDB\_env** \*env, int excl)\
 static **MDB\_node** \* **mdb\_node\_search** (**MDB\_cursor** \*mc, **MDB\_val** \*key, int \*exactp)\
 static int **mdb\_node\_add** (**MDB\_cursor** \*mc, **indx\_t** indx, **MDB\_val** \*key, **MDB\_val** \*data, **pgno\_t** pgno, unsigned int flags)\
 static void **mdb\_node\_del** (**MDB\_cursor** \*mc, int ksize)\
 static void **mdb\_node\_shrink** (**MDB\_page** \*mp, **indx\_t** indx)\
 static int **mdb\_node\_move** (**MDB\_cursor** \*csrc, **MDB\_cursor** \*cdst, int fromleft)\
 static int **mdb\_node\_read** (**MDB\_cursor** \*mc, **MDB\_node** \*leaf, **MDB\_val** \*data)\
 static size\_t **mdb\_leaf\_size** (**MDB\_env** \*env, **MDB\_val** \*key, **MDB\_val** \*data)\
 static size\_t **mdb\_branch\_size** (**MDB\_env** \*env, **MDB\_val** \*key)\
 static int **mdb\_rebalance** (**MDB\_cursor** \*mc)\
 static int **mdb\_update\_key** (**MDB\_cursor** \*mc, **MDB\_val** \*key)\
 static void **mdb\_cursor\_pop** (**MDB\_cursor** \*mc)\
 static int **mdb\_cursor\_push** (**MDB\_cursor** \*mc, **MDB\_page** \*mp)\
 static int **mdb\_cursor\_del0** (**MDB\_cursor** \*mc)\
 static int **mdb\_del0** (**MDB\_txn** \*txn, **MDB\_dbi** dbi, **MDB\_val** \*key, **MDB\_val** \*data, unsigned flags)\
 static int **mdb\_cursor\_sibling** (**MDB\_cursor** \*mc, int move\_right)\
 static int **mdb\_cursor\_next** (**MDB\_cursor** \*mc, **MDB\_val** \*key, **MDB\_val** \*data, **MDB\_cursor\_op** op)\
 static int **mdb\_cursor\_prev** (**MDB\_cursor** \*mc, **MDB\_val** \*key, **MDB\_val** \*data, **MDB\_cursor\_op** op)\
 static int **mdb\_cursor\_set** (**MDB\_cursor** \*mc, **MDB\_val** \*key, **MDB\_val** \*data, **MDB\_cursor\_op** op, int \*exactp)\
 static int **mdb\_cursor\_first** (**MDB\_cursor** \*mc, **MDB\_val** \*key, **MDB\_val** \*data)\
 static int **mdb\_cursor\_last** (**MDB\_cursor** \*mc, **MDB\_val** \*key, **MDB\_val** \*data)\
 static void **mdb\_cursor\_init** (**MDB\_cursor** \*mc, **MDB\_txn** \*txn, **MDB\_dbi** dbi, **MDB\_xcursor** \*mx)\
 static void **mdb\_xcursor\_init0** (**MDB\_cursor** \*mc)\
 static void **mdb\_xcursor\_init1** (**MDB\_cursor** \*mc, **MDB\_node** \*node)\
 static void **mdb\_xcursor\_init2** (**MDB\_cursor** \*mc, **MDB\_xcursor** \*src\_mx, int force)\
 static int **mdb\_drop0** (**MDB\_cursor** \*mc, int subs)\
 static void **mdb\_default\_cmp** (**MDB\_txn** \*txn, **MDB\_dbi** dbi)\
 static int **mdb\_reader\_check0** (**MDB\_env** \*env, int rlocked, int \*dead)\
 char \*ESECT **mdb\_version** (int \*major, int \*minor, int \*patch)\
 Return the LMDB library version information.  char \* **mdb\_strerror** (int err)\
 Return a string describing a given error code.  static void ESECT **mdb\_assert\_fail** (**MDB\_env** \*env, const char \*expr\_txt, const char \*func, const char \*file, int line)\
 int **mdb\_cmp** (**MDB\_txn** \*txn, **MDB\_dbi** dbi, const **MDB\_val** \*a, const **MDB\_val** \*b)\
 Compare two data items according to a particular database.  int **mdb\_dcmp** (**MDB\_txn** \*txn, **MDB\_dbi** dbi, const **MDB\_val** \*a, const **MDB\_val** \*b)\
 Compare two data items according to a particular database.  static **MDB\_page** \* **mdb\_page\_malloc** (**MDB\_txn** \*txn, unsigned num)\
 static void **mdb\_page\_free** (**MDB\_env** \*env, **MDB\_page** \*mp)\
 static void **mdb\_dpage\_free** (**MDB\_env** \*env, **MDB\_page** \*dp)\
 static void **mdb\_dlist\_free** (**MDB\_txn** \*txn)\
 static int **mdb\_page\_loose** (**MDB\_cursor** \*mc, **MDB\_page** \*mp)\
 static int **mdb\_pages\_xkeep** (**MDB\_cursor** \*mc, unsigned pflags, int all)\
 static int **mdb\_page\_flush** (**MDB\_txn** \*txn, int keep)\
 static int **mdb\_page\_spill** (**MDB\_cursor** \*m0, **MDB\_val** \*key, **MDB\_val** \*data)\
 static **txnid\_t** **mdb\_find\_oldest** (**MDB\_txn** \*txn)\
 static void **mdb\_page\_dirty** (**MDB\_txn** \*txn, **MDB\_page** \*mp)\
 static void **mdb\_page\_copy** (**MDB\_page** \*dst, **MDB\_page** \*src, unsigned int psize)\
 static int **mdb\_page\_unspill** (**MDB\_txn** \*txn, **MDB\_page** \*mp, **MDB\_page** \*\*ret)\
 int **mdb\_env\_sync** (**MDB\_env** \*env, int force)\
 Flush the data buffers to disk.  static int **mdb\_cursor\_shadow** (**MDB\_txn** \*src, **MDB\_txn** \*dst)\
 static void **mdb\_cursors\_close** (**MDB\_txn** \*txn, unsigned merge)\
 static int **mdb\_reader\_pid** (**MDB\_env** \*env, enum Pidlock\_op op, MDB\_PID\_T pid)\
 static int **mdb\_txn\_renew0** (**MDB\_txn** \*txn)\
 int **mdb\_txn\_renew** (**MDB\_txn** \*txn)\
 Renew a read-only transaction.  int **mdb\_txn\_begin** (**MDB\_env** \*env, **MDB\_txn** \*parent, unsigned int flags, **MDB\_txn** \*\*ret)\
 Create a transaction for use with the environment.  **MDB\_env** \* **mdb\_txn\_env** (**MDB\_txn** \*txn)\
 Returns the transaction's **MDB\_env**.  size\_t **mdb\_txn\_id** (**MDB\_txn** \*txn)\
 Return the transaction's ID.  static void **mdb\_dbis\_update** (**MDB\_txn** \*txn, int keep)\
 void **mdb\_txn\_reset** (**MDB\_txn** \*txn)\
 Reset a read-only transaction.  void **mdb\_txn\_abort** (**MDB\_txn** \*txn)\
 Abandon all the operations of the transaction instead of saving them.  static int **mdb\_freelist\_save** (**MDB\_txn** \*txn)\
 int **mdb\_txn\_commit** (**MDB\_txn** \*txn)\
 Commit all the operations of a transaction into the database.  static void ESECT **mdb\_env\_init\_meta0** (**MDB\_env** \*env, **MDB\_meta** \*meta)\
 static int ESECT **mdb\_env\_init\_meta** (**MDB\_env** \*env, **MDB\_meta** \*meta)\
 int ESECT **mdb\_env\_create** (**MDB\_env** \*\*env)\
 Create an LMDB environment handle.  static int ESECT **mdb\_env\_map** (**MDB\_env** \*env, void \*addr)\
 int ESECT **mdb\_env\_set\_mapsize** (**MDB\_env** \*env, size\_t size)\
 Set the size of the memory map to use for this environment.  int ESECT **mdb\_env\_set\_maxdbs** (**MDB\_env** \*env, **MDB\_dbi** dbs)\
 Set the maximum number of named databases for the environment.  int ESECT **mdb\_env\_set\_maxreaders** (**MDB\_env** \*env, unsigned int readers)\
 Set the maximum number of threads/reader slots for the environment.  int ESECT **mdb\_env\_get\_maxreaders** (**MDB\_env** \*env, unsigned int \*readers)\
 Get the maximum number of threads/reader slots for the environment.  static int ESECT **mdb\_fsize** (**HANDLE** fd, size\_t \*size)\
 static int ESECT **mdb\_fname\_init** (const char \*path, unsigned envflags, **MDB\_name** \*fname)\
 static int ESECT **mdb\_fopen** (const **MDB\_env** \*env, **MDB\_name** \*fname, enum **mdb\_fopen\_type** which, **mdb\_mode\_t** mode, **HANDLE** \*res)\
 static int ESECT **mdb\_env\_open2** (**MDB\_env** \*env)\
 static void **mdb\_env\_reader\_dest** (void \*ptr)\
 static int ESECT **mdb\_env\_share\_locks** (**MDB\_env** \*env, int \*excl)\
 static int ESECT **mdb\_env\_excl\_lock** (**MDB\_env** \*env, int \*excl)\
 static int ESECT **mdb\_env\_setup\_locks** (**MDB\_env** \*env, **MDB\_name** \*fname, int mode, int \*excl)\
 int ESECT **mdb\_env\_open** (**MDB\_env** \*env, const char \*path, unsigned int flags, **mdb\_mode\_t** mode)\
 Open an environment handle.  void ESECT **mdb\_env\_close** (**MDB\_env** \*env)\
 Close the environment and release the memory map.  static int **mdb\_cmp\_long** (const **MDB\_val** \*a, const **MDB\_val** \*b)\
 static int **mdb\_cmp\_int** (const **MDB\_val** \*a, const **MDB\_val** \*b)\
 static int **mdb\_cmp\_cint** (const **MDB\_val** \*a, const **MDB\_val** \*b)\
 static int **mdb\_cmp\_memn** (const **MDB\_val** \*a, const **MDB\_val** \*b)\
 static int **mdb\_cmp\_memnr** (const **MDB\_val** \*a, const **MDB\_val** \*b)\
 static int **mdb\_page\_search\_lowest** (**MDB\_cursor** \*mc)\
 static int **mdb\_ovpage\_free** (**MDB\_cursor** \*mc, **MDB\_page** \*mp)\
 int **mdb\_get** (**MDB\_txn** \*txn, **MDB\_dbi** dbi, **MDB\_val** \*key, **MDB\_val** \*data)\
 Get items from a database.  int **mdb\_cursor\_get** (**MDB\_cursor** \*mc, **MDB\_val** \*key, **MDB\_val** \*data, **MDB\_cursor\_op** op)\
 Retrieve by cursor.  static int **mdb\_cursor\_touch** (**MDB\_cursor** \*mc)\
 int **mdb\_cursor\_put** (**MDB\_cursor** \*mc, **MDB\_val** \*key, **MDB\_val** \*data, unsigned int flags)\
 Store by cursor.  int **mdb\_cursor\_del** (**MDB\_cursor** \*mc, unsigned int flags)\
 Delete current key/data pair.  int **mdb\_cursor\_open** (**MDB\_txn** \*txn, **MDB\_dbi** dbi, **MDB\_cursor** \*\*ret)\
 Create a cursor handle.  int **mdb\_cursor\_renew** (**MDB\_txn** \*txn, **MDB\_cursor** \*mc)\
 Renew a cursor handle.  int **mdb\_cursor\_count** (**MDB\_cursor** \*mc, size\_t \*countp)\
 Return count of duplicates for current key.  void **mdb\_cursor\_close** (**MDB\_cursor** \*mc)\
 Close a cursor handle.  **MDB\_txn** \* **mdb\_cursor\_txn** (**MDB\_cursor** \*mc)\
 Return the cursor's transaction handle.  **MDB\_dbi** **mdb\_cursor\_dbi** (**MDB\_cursor** \*mc)\
 Return the cursor's database handle.  static void **mdb\_cursor\_copy** (const **MDB\_cursor** \*csrc, **MDB\_cursor** \*cdst)\
 int **mdb\_del** (**MDB\_txn** \*txn, **MDB\_dbi** dbi, **MDB\_val** \*key, **MDB\_val** \*data)\
 Delete items from a database.  int **mdb\_put** (**MDB\_txn** \*txn, **MDB\_dbi** dbi, **MDB\_val** \*key, **MDB\_val** \*data, unsigned int flags)\
 Store items into a database.  static THREAD\_RET ESECT CALL\_CONV **mdb\_env\_copythr** (void \*arg)\
 static int ESECT **mdb\_env\_cthr\_toggle** (**mdb\_copy** \*my, int adjust)\
 static int ESECT **mdb\_env\_cwalk** (**mdb\_copy** \*my, **pgno\_t** \*pg, int flags)\
 static int ESECT **mdb\_env\_copyfd1** (**MDB\_env** \*env, **HANDLE** fd)\
 static int ESECT **mdb\_env\_copyfd0** (**MDB\_env** \*env, **HANDLE** fd)\
 int ESECT **mdb\_env\_copyfd2** (**MDB\_env** \*env, **HANDLE** fd, unsigned int flags)\
 int ESECT **mdb\_env\_copyfd** (**MDB\_env** \*env, **HANDLE** fd)\
 int ESECT **mdb\_env\_copy2** (**MDB\_env** \*env, const char \*path, unsigned int flags)\
 Copy an LMDB environment to the specified path, with options.  int ESECT **mdb\_env\_copy** (**MDB\_env** \*env, const char \*path)\
 Copy an LMDB environment to the specified path.  int ESECT **mdb\_env\_set\_flags** (**MDB\_env** \*env, unsigned int flag, int onoff)\
 Set environment flags.  int ESECT **mdb\_env\_get\_flags** (**MDB\_env** \*env, unsigned int \*arg)\
 Get environment flags.  int ESECT **mdb\_env\_set\_userctx** (**MDB\_env** \*env, void \*ctx)\
 Set application information associated with the **MDB\_env**.  void \*ESECT **mdb\_env\_get\_userctx** (**MDB\_env** \*env)\
 Get the application information associated with the **MDB\_env**.  int ESECT **mdb\_env\_set\_assert** (**MDB\_env** \*env, **MDB\_assert\_func** \*func)\
 int ESECT **mdb\_env\_get\_path** (**MDB\_env** \*env, const char \*\*arg)\
 Return the path that was used in **mdb\_env\_open()**.  int ESECT **mdb\_env\_get\_fd** (**MDB\_env** \*env, **mdb\_filehandle\_t** \*arg)\
 Return the filedescriptor for the given environment.  static int ESECT **mdb\_stat0** (**MDB\_env** \*env, **MDB\_db** \*db, **MDB\_stat** \*arg)\
 int ESECT **mdb\_env\_stat** (**MDB\_env** \*env, **MDB\_stat** \*arg)\
 Return statistics about the LMDB environment.  int ESECT **mdb\_env\_info** (**MDB\_env** \*env, **MDB\_envinfo** \*arg)\
 Return information about the LMDB environment.  int **mdb\_dbi\_open** (**MDB\_txn** \*txn, const char \*name, unsigned int flags, **MDB\_dbi** \*dbi)\
 Open a database in the environment.  int ESECT **mdb\_stat** (**MDB\_txn** \*txn, **MDB\_dbi** dbi, **MDB\_stat** \*arg)\
 Retrieve statistics for a database.  void **mdb\_dbi\_close** (**MDB\_env** \*env, **MDB\_dbi** dbi)\
 Close a database handle. Normally unnecessary. Use with care:  int **mdb\_dbi\_flags** (**MDB\_txn** \*txn, **MDB\_dbi** dbi, unsigned int \*flags)\
 Retrieve the DB flags for a database handle.  int **mdb\_drop** (**MDB\_txn** \*txn, **MDB\_dbi** dbi, int del)\
 Empty or delete+close a database.  int **mdb\_set\_compare** (**MDB\_txn** \*txn, **MDB\_dbi** dbi, **MDB\_cmp\_func** \*cmp)\
 Set a custom key comparison function for a database.  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.  int **mdb\_set\_relfunc** (**MDB\_txn** \*txn, **MDB\_dbi** dbi, **MDB\_rel\_func** \*rel)\
 Set a relocation function for a **MDB\_FIXEDMAP** database.  int **mdb\_set\_relctx** (**MDB\_txn** \*txn, **MDB\_dbi** dbi, void \*ctx)\
 Set a context pointer for a **MDB\_FIXEDMAP** database's relocation function.  int ESECT **mdb\_env\_get\_maxkeysize** (**MDB\_env** \*env)\
 Get the maximum size of keys and **MDB\_DUPSORT** data 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.  static int ESECT **mdb\_pid\_insert** (MDB\_PID\_T \*ids, MDB\_PID\_T pid)\
 int ESECT **mdb\_reader\_check** (**MDB\_env** \*env, int \*dead)\
 Check for stale entries in the reader lock table.

### Variables

static char \*const **mdb\_errstr** \[\]\
 static const **mdb\_nchar\_t** \*const **mdb\_suffixes** \[2\]\[2\]\

## Detailed Description

## Data Structure Documentation

## struct MDB\_page

Common header for all page types. The page type depends on **mp\_flags**.

**P\_BRANCH** and **P\_LEAF** pages have unsorted '**MDB\_node**'s 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

### struct MDB\_page\* MDB\_page::p\_next

for in-memory list of freed pages

### uint16\_t MDB\_page::mp\_pad

key size if this is a LEAF2 page

### uint16\_t MDB\_page::mp\_flags

**Page Flags**

### indx\_t MDB\_page::pb\_lower

lower bound of free space

### indx\_t MDB\_page::pb\_upper

upper bound of free space

### uint32\_t MDB\_page::pb\_pages

number of overflow pages

### indx\_t MDB\_page::mp\_ptrs\[0\]

dynamic size

## 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\_node**'s.

**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

### unsigned short MDB\_node::mn\_hi

part of data size or pgno

### unsigned short MDB\_node::mn\_flags

**Node Flags**

### unsigned short MDB\_node::mn\_ksize

key size

### char MDB\_node::mn\_data\[1\]

key and data are appended here

## struct MDB\_db

Information about a single database in the environment.

**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

### uint16\_t MDB\_db::md\_flags

**Database Flags**

### uint16\_t MDB\_db::md\_depth

depth of this tree

### pgno\_t MDB\_db::md\_branch\_pages

number of internal pages

### pgno\_t MDB\_db::md\_leaf\_pages

number of leaf pages

### pgno\_t MDB\_db::md\_overflow\_pages

number of overflow pages

### size\_t MDB\_db::md\_entries

number of data items

### pgno\_t MDB\_db::md\_root

the root page of this tree

## 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).

**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**.

### uint32\_t MDB\_meta::mm\_version

Version number of this file. Must be set to **MDB\_DATA\_VERSION**.

### void\* MDB\_meta::mm\_address

address for fixed mapping

### size\_t MDB\_meta::mm\_mapsize

size of mmap region

### MDB\_db MDB\_meta::mm\_dbs\[CORE\_DBS\]

first is free space, 2nd is main db

### 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.

### volatile txnid\_t MDB\_meta::mm\_txnid

txnid that committed this page

## 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.

**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.

**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

### MDB\_cmp\_func\* MDB\_dbx::md\_cmp

function for comparing keys

### MDB\_cmp\_func\* MDB\_dbx::md\_dcmp

function for comparing data items

### MDB\_rel\_func\* MDB\_dbx::md\_rel

user relocate function

### void\* MDB\_dbx::md\_relctx

user-provided context for md\_rel

## 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.

**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

### MDB\_txn\* MDB\_txn::mt\_child

Nested txn under this txn, set together with flag **MDB\_TXN\_HAS\_CHILD**

### pgno\_t MDB\_txn::mt\_next\_pgno

next unallocated page

### 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.

### MDB\_env\* MDB\_txn::mt\_env

the DB environment

### MDB\_IDL MDB\_txn::mt\_free\_pgs

The list of pages that became unused during this transaction.

### 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)**.

### int MDB\_txn::mt\_loose\_count

Number of loose pages (**mt\_loose\_pgs**)

### 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.

### MDB\_ID2L MDB\_txn::dirty\_list

For write txns: Modified pages. Sorted when not MDB\_WRITEMAP.

### MDB\_reader\* MDB\_txn::reader

For read txns: This thread/txn's reader table slot, or NULL.

### MDB\_dbx\* MDB\_txn::mt\_dbxs

Array of records for each DB known in the environment.

### MDB\_db\* MDB\_txn::mt\_dbs

Array of **MDB\_db** records for each known DB

### unsigned int\* MDB\_txn::mt\_dbiseqs

Array of sequence numbers for each DB handle

### MDB\_cursor\*\* MDB\_txn::mt\_cursors

In write txns, array of cursors for each DB

### unsigned char\* MDB\_txn::mt\_dbflags

Array of flags for each 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.

### unsigned int MDB\_txn::mt\_flags

**Transaction Flags**

### 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.

## struct MDB\_cursor

Opaque structure for navigating through a database.

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

### MDB\_cursor\* MDB\_cursor::mc\_backup

Backup of the original cursor if this cursor is a shadow

### 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

### 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**

### 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.

**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**

**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

### 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

### 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

**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**\[\]

**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.

**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\]\
 int **mc\_wlen** \[2\]\
 int **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.

## Macro Definition Documentation

### #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 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.

### #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.

### #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.

### #define ENV\_MAXKEY(env) (MDB\_MAXKEYSIZE)

The maximum size of a key we can write to the environment.

### #define MAXDATASIZE 0xffffffffUL

The maximum size of a data item. We only store a 32 bit value for node sizes.

### #define P\_INVALID (~(pgno\_t)0)

An invalid page number. Mainly used to denote an empty tree.

### #define F\_ISSET(w, f) (((w) & (f)) == (f))

Test if the flags **f** are set in a flag word **w**.

### #define EVEN(n) (((n) + 1U) & -2) /\* sign-extending -2 to match n+1U \*/

Round **n** up to an even number.

### #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()**.

### #define PAGEHDRSZ ((unsigned) offsetof(MDB\_page, mp\_ptrs))

Size of the page header, excluding dynamic data at the end

### #define METADATA(p) ((void \*)((char \*)(p) + PAGEHDRSZ))

Address of first usable data byte in a page, after the header

### #define PAGEBASE ((MDB\_DEVEL) ? PAGEHDRSZ : 0)

ITS#7713, change PAGEBASE to handle 65536 byte pages

### #define NUMKEYS(p) ((MP\_LOWER(p) - (PAGEHDRSZ-PAGEBASE)) \>\> 1)

Number of nodes on a page

### #define SIZELEFT(p) (indx\_t)(MP\_UPPER(p) - MP\_LOWER(p))

The amount of space remaining in the page

### #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.

### #define FILL\_THRESHOLD 250

The minimum page fill factor, in tenths of a percent. Pages emptier than this are candidates for merging.

### #define IS\_LEAF(p) F\_ISSET(MP\_FLAGS(p), P\_LEAF)

Test if a page is a leaf page

### #define IS\_LEAF2(p) F\_ISSET(MP\_FLAGS(p), P\_LEAF2)

Test if a page is a LEAF2 page

### #define IS\_BRANCH(p) F\_ISSET(MP\_FLAGS(p), P\_BRANCH)

Test if a page is a branch page

### #define IS\_OVERFLOW(p) F\_ISSET(MP\_FLAGS(p), P\_OVERFLOW)

Test if a page is an overflow page

### #define IS\_SUBP(p) F\_ISSET(MP\_FLAGS(p), P\_SUBP)

Test if a page is a sub page

### #define OVPAGES(size, psize) ((PAGEHDRSZ-1 + (size)) / (psize) + 1)

The number of overflow pages needed to store the given size.

### #define NEXT\_LOOSE\_PAGE(p) (\*(MDB\_page \*\*)((p) + 2))

Link in **MDB\_txn**.mt\_loose\_pgs list. Kept outside the page header, which is needed when reusing the page.

### #define NODESIZE offsetof(MDB\_node, mn\_data)

Size of the node header, excluding dynamic data at the end

### #define PGNO\_TOPWORD ((pgno\_t)-1 \> 0xffffffffu ? 32 : 0)

Bit position of top word in page number, for shifting mn\_flags

### #define INDXSIZE(k) (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.

### #define LEAFSIZE(k, d) (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.

### #define NODEPTR(p, i) ((MDB\_node \*)((char \*)(p) + MP\_PTRS(p)\[i\] + PAGEBASE))

Address of node **i** in page **p**

### #define NODEKEY(node) (void \*)((node)-\>mn\_data)

Address of the key for the node

### #define NODEDATA(node) (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

### #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

### #define NODEDSZ(node) ((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

### #define NODEKSZ(node) ((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

### #define LEAF2KEY(p, i, ks) ((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.

### #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.

### #define MDB\_GET\_KEY2(node, key) { key.mv\_size = NODEKSZ(node); key.mv\_data = NODEKEY(node); }

Set the **node's** key into **key**.

### #define MDB\_VALID 0x8000

DB handle is valid, for me\_dbflags

### #define VALID\_FLAGS

**Value:**

```
    (MDB_REVERSEKEY|MDB_DUPSORT|MDB_INTEGERKEY|MDB_DUPFIXED|    MDB_INTEGERDUP|MDB_REVERSEDUP|MDB_CREATE)
```

**mdb\_dbi\_open()** flags

### #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

### #define NUM\_METAS 2

Number of meta pages - also hardcoded elsewhere

### #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.

### #define XCURSOR\_INITED(mc) ((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**\].

### #define MDB\_COMMIT\_PAGES 64

max number of pages to commit in one writev() call

### #define MAX\_WRITE (0x40000000U \>\> (sizeof(ssize\_t) == 4))

max bytes to write in one call

### #define TXN\_DBI\_EXIST(txn, dbi, validity) ((txn) && (dbi)\<(txn)-\>mt\_numdbs && ((txn)-\>mt\_dbflags\[dbi\] & (validity)))

Check **txn** and **dbi** arguments to a function

### #define TXN\_DBI\_CHANGED(txn, dbi) ((txn)-\>mt\_dbiseqs\[dbi\] != (txn)-\>mt\_env-\>me\_dbiseqs\[dbi\])

Check for misused **dbi** handles

### #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

### #define MDB\_END\_SLOT MDB\_NOTLS

release any reader slot if **MDB\_NOTLS**

### #define MDB\_SPLIT\_REPLACE MDB\_APPENDDUP

newkey is not new

### #define mdb\_cmp\_clong mdb\_cmp\_cint

Compare two items pointing at size\_t's of unknown alignment.

### #define mdb\_cassert(mc, expr) mdb\_assert0((mc)-\>mc\_txn-\>mt\_env, expr, #expr)

[assert(3)](/assert/3.md) variant in cursor context

### #define mdb\_tassert(txn, expr) mdb\_assert0((txn)-\>mt\_env, expr, #expr)

[assert(3)](/assert/3.md) variant in transaction context

### #define mdb\_eassert(env, expr) mdb\_assert0(env, expr, #expr)

[assert(3)](/assert/3.md) variant in environment context

### #define mdb\_assert0(env, expr, expr\_txt)

**Value:**

```
        ((expr) ? (void)0 :         mdb_assert_fail(env, expr_txt, mdb_func_, __FILE__, __LINE__))
```

### #define MDB\_NAME(str) str

**mdb\_nchar\_t**\[\] string literal

### #define mdb\_name\_cpy strcpy

Copy name (**mdb\_nchar\_t** string)

### #define MDB\_SUFFLEN 9

Max string length in **mdb\_suffixes**\[\]

### #define mdb\_fname\_destroy(fname) do { if ((fname).mn\_alloced) free((fname).mn\_val); } while (0)

Destroy **fname** from **mdb\_fname\_init()**

### #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.

### #define CHANGELESS

**Value:**

```
   (MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY|     MDB_WRITEMAP|MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD)
```

### #define MDB\_NOSPILL 0x8000

Do not spill pages to disk if txn is getting full, may fail instead

### #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**

### #define MDB\_EOF 0x10

**mdb\_env\_copyfd1()** is done reading

## Typedef Documentation

### typedef MDB\_ID pgno\_t

A page number in the database. Note that 64 bit page numbers are overkill, since pages themselves already represent 12-13 bits of addressable memory, and the OS will always limit applications to a maximum of 63 bits of address space.

**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.

### typedef MDB\_ID txnid\_t

A transaction ID. See struct **MDB\_txn.mt\_txnid** for details.

### typedef uint16\_t indx\_t

Used for offsets within a single page. Since memory pages are typically 4 or 8KB in size, 12-13 bits, this is plenty.

### typedef char mdb\_nchar\_t

Character type for file names: char on Unix, wchar\_t on Windows

## Enumeration Type Documentation

### 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

### static int mdb\_page\_alloc (MDB\_cursor \* mc, int num, MDB\_page \*\* mp)` [static]`

*Allocate page numbers and memory for writing. Maintain me\_pglast, me\_pghead and mt\_next\_pgno. Set* **MDB\_TXN\_ERROR** *on failure.*

*If there are free pages available from older transactions, they are re-used first. Otherwise allocate a new page at mt\_next\_pgno. Do not modify the freedB, just merge freeDB records into me\_pghead\[\] and move me\_pglast to say which records were consumed. Only this function can create me\_pghead and move me\_pglast/mt\_next\_pgno.*

**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.*

### static int mdb\_page\_new (MDB\_cursor \* mc, uint32\_t flags, int num, MDB\_page \*\* mp)` [static]`

*Allocate and initialize new pages for a database. Set* **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.*

### static int mdb\_page\_touch (MDB\_cursor \* mc)` [static]`

*Touch a page: make it dirty and re-insert into tree with updated pgno. Set* **MDB\_TXN\_ERROR** *on failure.*

**Parameters**

*mc cursor pointing to the page to be touched*

**Returns**

*0 on success, non-zero on failure.*

### static void mdb\_txn\_end (MDB\_txn \* txn, unsigned mode)` [static]`

*End a transaction, except successful commit of a nested transaction. May be called twice for readonly txns: First reset it, then abort.*

**Parameters**

*txn the transaction handle to end* \
 *mode why and how to end the transaction*

### static 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. Set* **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.*

### static 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.*

### static 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.*

### static 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.*

**Parameters**

*csrc Cursor pointing to the source page.* \
 *cdst Cursor pointing to the destination page.*

**Returns**

*0 on success, non-zero on failure.*

### static 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. Set* **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.*

### static 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.*

### static MDB\_meta \* mdb\_env\_pick\_meta (const MDB\_env \* env)` [static]`

*Check both meta pages to see which one is newer.*

**Parameters**

*env the environment handle*

**Returns**

*newest* **MDB\_meta***.*

### static 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.*

### static void ESECT mdb\_env\_close0 (MDB\_env \* env, int excl)` [static]`

*Destroy resources from* **mdb\_env\_open()***, clear our readers & DBIs*

### static 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.*

### static 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. Set* **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.*

### static 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.*

### static void mdb\_node\_shrink (MDB\_page \* mp, indx\_t indx)` [static]`

*Compact the main page after deleting a node on a subpage.*

**Parameters**

*mp The main page to operate on.* \
 *indx The index of the subpage on the main page.*

### static int mdb\_node\_move (MDB\_cursor \* csrc, MDB\_cursor \* cdst, int fromleft)` [static]`

*Move a node from csrc to cdst.*

### static 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.*

### static size\_t mdb\_leaf\_size (MDB\_env \* env, MDB\_val \* key, MDB\_val \* data)` [static]`

*Calculate the size of a leaf node. The size depends on the environment's page size; if a data item is too large it will be put onto an overflow page and the node size will only include the key and not the data. Sizes are always rounded up to an even number of bytes, to guarantee 2-byte alignment of the* **MDB\_node** *headers.*

**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.*

### static size\_t mdb\_branch\_size (MDB\_env \* env, MDB\_val \* key)` [static]`

*Calculate the size of a branch node. The size should depend on the environment's page size but since we currently don't support spilling large keys onto overflow pages, it's simply the size of the* **MDB\_node** *header plus the size of the key. Sizes are always rounded up to an even number of bytes, to guarantee 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.*

### static int mdb\_rebalance (MDB\_cursor \* mc)` [static]`

*Rebalance the tree after a delete operation.*

**Parameters**

*mc Cursor pointing to the page where rebalancing should begin.*

**Returns**

*0 on success, non-zero on failure.*

### static int mdb\_update\_key (MDB\_cursor \* mc, MDB\_val \* key)` [static]`

*Replace the key for a branch node with a new key. Set* **MDB\_TXN\_ERROR** *on failure.*

**Parameters**

*mc Cursor pointing to the node to operate on.* \
 *key The new key to use.*

**Returns**

*0 on success, non-zero on failure.*

### static void mdb\_cursor\_pop (MDB\_cursor \* mc)` [static]`

*Pop a page off the top of the cursor's stack.*

### static int mdb\_cursor\_push (MDB\_cursor \* mc, MDB\_page \* mp)` [static]`

*Push a page onto the top of the cursor's stack. Set* **MDB\_TXN\_ERROR** *on failure.*

### static int mdb\_cursor\_del0 (MDB\_cursor \* mc)` [static]`

*Complete a delete operation started by* **mdb\_cursor\_del()***.*

### static int mdb\_cursor\_sibling (MDB\_cursor \* mc, int move\_right)` [static]`

*Find a sibling for a page. Replaces the page at the top of the cursor's stack with the specified sibling, if one exists.*

**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.*

### static int mdb\_cursor\_next (MDB\_cursor \* mc, MDB\_val \* key, MDB\_val \* data, MDB\_cursor\_op op)` [static]`

*Move the cursor to the next data item.*

### static int mdb\_cursor\_prev (MDB\_cursor \* mc, MDB\_val \* key, MDB\_val \* data, MDB\_cursor\_op op)` [static]`

*Move the cursor to the previous data item.*

### static int mdb\_cursor\_set (MDB\_cursor \* mc, MDB\_val \* key, MDB\_val \* data, MDB\_cursor\_op op, int \* exactp)` [static]`

*Set the cursor on a specific data item.*

### static int mdb\_cursor\_first (MDB\_cursor \* mc, MDB\_val \* key, MDB\_val \* data)` [static]`

*Move the cursor to the first item in the database.*

### static int mdb\_cursor\_last (MDB\_cursor \* mc, MDB\_val \* key, MDB\_val \* data)` [static]`

*Move the cursor to the last item in the database.*

### static void mdb\_cursor\_init (MDB\_cursor \* mc, MDB\_txn \* txn, MDB\_dbi dbi, MDB\_xcursor \* mx)` [static]`

*Initialize a cursor for a given transaction and database.*

### static void mdb\_xcursor\_init0 (MDB\_cursor \* mc)` [static]`

*Initial setup of a sorted-dups cursor. Sorted duplicates are implemented as a sub-database for the given key. The duplicate data items are actually keys of the sub-database. Operations on the duplicate data items are performed using a sub-cursor 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.*

### static void mdb\_xcursor\_init1 (MDB\_cursor \* mc, MDB\_node \* node)` [static]`

*Final setup of a sorted-dups cursor. 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.*

### static void mdb\_xcursor\_init2 (MDB\_cursor \* mc, MDB\_xcursor \* src\_mx, int new\_dupdata)` [static]`

*Fixup a sorted-dups cursor due to underlying update. Sets up some fields that depend on the data from the main cursor. Almost the same as init1, but 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.*

### static int mdb\_drop0 (MDB\_cursor \* mc, int subs)` [static]`

*Add 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.*

### static void mdb\_default\_cmp (MDB\_txn \* txn, MDB\_dbi dbi)` [static]`

*Set the default comparison functions for a database. Called immediately after a database is opened to set the defaults. The user can then override them with* **mdb\_set\_compare()** *or* **mdb\_set\_dupsort()***.*

**Parameters**

*txn A transaction handle returned by* **mdb\_txn\_begin()** \
 *dbi A database handle returned by* **mdb\_dbi\_open()**

### static int ESECT mdb\_reader\_check0 (MDB\_env \* env, int rlocked, int \* dead)` [static]`

*As* **mdb\_reader\_check()***.* **rlocked** *is set if caller locked* **me\_rmutex***.*

### char \*ESECT mdb\_version (int \* major, int \* minor, int \* patch)

*Return the LMDB library version information. Return the library version info.*

### char \* mdb\_strerror (int err)

*Return a string describing a given error code. This function is a superset of the ANSI C X3.159-1989 (ANSI C) [strerror(3)](/strerror/3.md) function. If the error code is greater than or equal to 0, then the string returned by the system function [strerror(3)](/strerror/3.md) 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)

*Compare 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)

*Compare two data items according to a particular database. This returns a comparison as if the two items were data items of the specified database. The database must have the* **MDB\_DUPSORT** *flag.*

**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*

### static MDB\_page \* mdb\_page\_malloc (MDB\_txn \* txn, unsigned num)` [static]`

*Allocate memory for a page. Re-use old malloc'd pages first for singletons, otherwise just malloc. Set* **MDB\_TXN\_ERROR** *on failure.*

### static void mdb\_page\_free (MDB\_env \* env, MDB\_page \* mp)` [static]`

*Free a single page. Saves single pages to a list, for future reuse. (This is not used for multi-page overflow pages.)*

### static void mdb\_dpage\_free (MDB\_env \* env, MDB\_page \* dp)` [static]`

*Free a dirty page*

### static void mdb\_dlist\_free (MDB\_txn \* txn)` [static]`

*Return all dirty pages to dpage list*

### static int mdb\_page\_loose (MDB\_cursor \* mc, MDB\_page \* mp)` [static]`

*Loosen or free a single page. Saves single pages to a list for future reuse in this same txn. It has been pulled from the freeDB and already resides on the dirty list, but has been deleted. Use these pages first before pulling again from the freeDB.*

*If the page wasn't dirtied in this txn, just add it to this txn's free list.*

### static int mdb\_pages\_xkeep (MDB\_cursor \* mc, unsigned pflags, int all)` [static]`

*Set or clear 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.*

### static int mdb\_page\_flush (MDB\_txn \* txn, int keep)` [static]`

*Flush (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.*

### static int mdb\_page\_spill (MDB\_cursor \* m0, MDB\_val \* key, MDB\_val \* data)` [static]`

*Spill 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 not using nested txns, it is 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. 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.*

**Parameters**

*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.*

### static txnid\_t mdb\_find\_oldest (MDB\_txn \* txn)` [static]`

*Find oldest txnid still referenced. Expects txn-\>mt\_txnid \> 0.*

### static void mdb\_page\_dirty (MDB\_txn \* txn, MDB\_page \* mp)` [static]`

*Add a page to the txn's dirty list*

### static void mdb\_page\_copy (MDB\_page \* dst, MDB\_page \* src, unsigned int psize)` [static]`

*Copy the used portions of a non-overflow page.*

**Parameters**

*dst page to copy into* \
 *src page to copy from* \
 *psize size of a page*

### static int mdb\_page\_unspill (MDB\_txn \* txn, MDB\_page \* mp, MDB\_page \*\* ret)` [static]`

*Pull a page off the txn's spill list, if present. If a page being referenced was spilled to disk in this txn, bring it back and make it dirty/writable again.*

**Parameters**

*txn the transaction handle.* \
 *mp the page being referenced. It must not be dirty.* \
 *ret the writable page, if any. ret is unchanged if mp wasn't spilled.*

### int mdb\_env\_sync (MDB\_env \* env, int force)

*Flush the data buffers to disk. Data is always written to disk when* **mdb\_txn\_commit()** *is called, but the operating system may keep it buffered. LMDB always flushes the OS buffers upon commit as well, 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 will 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.*

### static int mdb\_cursor\_shadow (MDB\_txn \* src, MDB\_txn \* dst)` [static]`

*Back up parent txn's cursors, then grab the originals for tracking*

### static void mdb\_cursors\_close (MDB\_txn \* txn, unsigned merge)` [static]`

*Close this write txn's cursors, give parent txn's cursors back to 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.*

### static int mdb\_reader\_pid (MDB\_env \* env, enum Pidlock\_op op, MDB\_PID\_T pid)` [static]`

*Set or check a pid lock. Set returns 0 on success. Check returns 0 if the process is certainly dead, nonzero if it may be alive (the lock exists or an error happened so we do not know).*

*On Windows Pidset is a no-op, we merely check for the existence of the process with the given pid. On POSIX we use a single byte lock on the lockfile, set at an offset equal to the pid.*

### static int mdb\_txn\_renew0 (MDB\_txn \* txn)` [static]`

*Common code for* **mdb\_txn\_begin()** *and* **mdb\_txn\_renew()***.*

**Parameters**

*txn the transaction handle to initialize*

**Returns**

*0 on success, non-zero on failure.*

### int mdb\_txn\_renew (MDB\_txn \* txn)

*Renew a read-only transaction. This acquires 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.*

**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)

*Create a transaction for use with the environment. The transaction handle may be discarded using* **mdb\_txn\_abort()** *or* **mdb\_txn\_commit()***.*

**Note**

*A transaction and its cursors must only be used by a single thread, and a thread may only have a single transaction at a time. If* **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***.*

**Parameters**

*txn A transaction handle returned by* **mdb\_txn\_begin()**

### size\_t mdb\_txn\_id (MDB\_txn \* txn)

*Return 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.*

**Parameters**

*txn A transaction handle returned by* **mdb\_txn\_begin()**

**Returns**

*A transaction ID, valid if input is an active transaction.*

### static void mdb\_dbis\_update (MDB\_txn \* txn, int keep)` [static]`

*Export or close DBI handles opened in this txn.*

### void mdb\_txn\_reset (MDB\_txn \* txn)

*Reset a read-only transaction. Abort the transaction like* **mdb\_txn\_abort()***, but keep the transaction handle.* **mdb\_txn\_renew()** *may reuse the handle. This saves allocation overhead if the process will start a new read-only transaction soon, and also 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 keep old versions of database pages allocated. Thus they prevent the old pages from being reused when writers commit new data, and so under heavy load the database size may grow much more rapidly than otherwise.*

**Parameters**

*txn A transaction handle returned by* **mdb\_txn\_begin()**

### void mdb\_txn\_abort (MDB\_txn \* txn)

*Abandon all the operations of the transaction instead of saving them. The transaction handle is freed. It and its cursors must not be used again after this call, except with* **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()**

### static int mdb\_freelist\_save (MDB\_txn \* txn)` [static]`

*Save the freelist as of this transaction to the freeDB. This changes the freelist. Keep trying until it stabilizes.*

### int mdb\_txn\_commit (MDB\_txn \* txn)

*Commit all the operations of a transaction into the database. The transaction handle is freed. It and its cursors must not be used again after this call, except with* **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.*

### static void ESECT mdb\_env\_init\_meta0 (MDB\_env \* env, MDB\_meta \* meta)` [static]`

*Fill in most of the zeroed* **MDB\_meta** *for an empty database environment*

### static int ESECT mdb\_env\_init\_meta (MDB\_env \* env, MDB\_meta \* meta)` [static]`

*Write the environment parameters of a freshly created DB environment.*

**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)

*Create an LMDB environment handle. This function allocates memory for a* **MDB\_env** *structure. To release the 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 opening the handle, e.g.* **mdb\_env\_set\_mapsize()***,* **mdb\_env\_set\_maxreaders()***,* **mdb\_env\_set\_maxdbs()***, depending on 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)

*Set the size of the memory map to use for this environment. The size should be a multiple of the OS page size. The default is 10485760 bytes. The size of the memory map is also the maximum size of the database. The value should be chosen as large as possible, to accommodate future growth of the database. This function should be called after* **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.*

*The new size takes effect immediately for the current process but will not be persisted to any others until a write transaction has been committed by the current process. Also, only mapsize increases are persisted into the environment.*

*If the mapsize is increased by another process, and data has grown beyond the range of the current mapsize,* **mdb\_txn\_begin()** *will return* **MDB\_MAP\_RESIZED***. This function may be called with a size of zero to adopt the new size.*

*Any attempt to set a size smaller than the space already consumed by the environment will be silently changed to the current size of the used space.*

**Parameters**

*env An environment handle returned by* **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.*

### int ESECT mdb\_env\_set\_maxdbs (MDB\_env \* env, MDB\_dbi dbs)

*Set the maximum number of named databases for the environment. This function is only needed if multiple databases will be used in the environment. Simpler applications that use the environment as a single unnamed database can ignore this option. This function may only be called after* **mdb\_env\_create()** *and before* **mdb\_env\_open()***.*

*Currently a moderate number of slots are cheap but a huge number gets expensive: 7-120 words per transaction, and every* **mdb\_dbi\_open()** *does a linear search of the opened slots.*

**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.*

### int ESECT mdb\_env\_set\_maxreaders (MDB\_env \* env, unsigned int readers)

*Set the maximum number of threads/reader slots for the environment. This defines the number of slots in the lock table that is used to track readers in the the environment. The default is 126. Starting a read-only transaction normally ties a lock table slot to the current thread until the environment closes or the thread exits. 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. This function 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.*

### int ESECT mdb\_env\_get\_maxreaders (MDB\_env \* env, unsigned int \* readers)

*Get the maximum number of threads/reader slots for the environment.*

**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.*

### static int ESECT mdb\_fname\_init (const char \* path, unsigned envflags, MDB\_name \* fname)` [static]`

*Set up filename + scratch area for filename suffix, for opening files. It should be freed with* **mdb\_fname\_destroy()***. On Windows, paths are converted from char \*UTF-8 to wchar\_t \*UTF-16.*

**Parameters**

*path Pathname for* **mdb\_env\_open()***.* \
 *envflags Whether a subdir and/or lockfile will be used.* \
 *fname Resulting filename, with room for a suffix if necessary.*

### static int ESECT mdb\_fopen (const MDB\_env \* env, MDB\_name \* fname, enum mdb\_fopen\_type which, mdb\_mode\_t mode, HANDLE \* res)` [static]`

*Open an LMDB file.*

**Parameters**

*env The LMDB environment.* \
 *fname Path from from* **mdb\_fname\_init()***. A suffix is appended if necessary to create the filename, without changing mn\_len.* \
 *which Determines file type, access mode, etc.* \
 *mode The Unix permissions for the file, if we create it.* \
 *res Resulting file handle.*

**Returns**

*0 on success, non-zero on failure.*

### static int ESECT mdb\_env\_open2 (MDB\_env \* env)` [static]`

*Further setup required for opening an LMDB environment*

### static void mdb\_env\_reader\_dest (void \* ptr)` [static]`

*Release a reader thread's slot in the reader lock table. This function is called automatically when a thread exits.*

**Parameters**

*ptr This points to the slot in the reader lock table.*

### static int ESECT mdb\_env\_share\_locks (MDB\_env \* env, int \* excl)` [static]`

*Downgrade the exclusive lock on the region back to shared*

### static int ESECT mdb\_env\_excl\_lock (MDB\_env \* env, int \* excl)` [static]`

*Try to get exclusive lock, otherwise shared. Maintain \*excl = -1: no/unknown lock, 0: shared, 1: exclusive.*

### static int ESECT mdb\_env\_setup\_locks (MDB\_env \* env, MDB\_name \* fname, int mode, int \* excl)` [static]`

*Open and/or initialize the lock region for the environment.*

**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 -1, out 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)

*Open an environment handle. If this function fails,* **mdb\_env\_close()** *must be called to discard the* **MDB\_env** *handle.*

**Parameters**

*env An environment handle returned by* **mdb\_env\_create()** \
 *path The directory in which the database files reside. This directory must already exist and be writable.* \
 *flags Special options for this environment. This parameter must be set to 0 or by bitwise OR'ing together one or more of the values described here. Flags set by* **mdb\_env\_set\_flags()** *are also used.*

- •

  **MDB\_FIXEDMAP** *use a fixed address for the mmap region. This flag must be specified when creating the environment, and is stored persistently in the environment. If successful, the memory map will always reside at the same virtual address and pointers used to reference data items in the database will be constant across multiple invocations. This option may not always work, depending on how the operating system has allocated memory to shared libraries and other uses. The feature is highly experimental.*

- •

  **MDB\_NOSUBDIR** *By default, LMDB creates its environment in a directory whose pathname is given in* **path***, and creates its data and lock files under that directory. With this option,* **path** *is used as-is for the database main data file. The database lock file is the* **path** *with '-lock' appended.*

- •

  **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 loses protection from application bugs like wild pointer writes and other bad updates into the database. This may be slightly faster for DBs that fit entirely in RAM, but is slower for DBs larger than RAM. Incompatible with nested transactions. Do not mix processes with and without MDB\_WRITEMAP on the same environment. This can defeat durability (***mdb\_env\_sync** *etc).*

- •

  **MDB\_NOMETASYNC** *Flush system buffers to disk only once per transaction, omit the metadata flush. Defer that until the system flushes files to disk, or next non-MDB\_RDONLY commit or* **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 D (durability) database property. This flag may 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 are not yet flushed to disk. 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 may be changed at any time using* **mdb\_env\_set\_flags()***.*

- •

  **MDB\_MAPASYNC** *When using* **MDB\_WRITEMAP***, use asynchronous flushes to disk. 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 next commit. This flag may 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. 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 may 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)

*Close the environment and release the memory map. Only a single thread may call this function. All transactions, databases, and cursors must already be closed before calling this function. Attempts to use any such handles after calling this function will cause a SIGSEGV. The environment handle will be freed and must not be used again after this call.*

**Parameters**

*env An environment handle returned by* **mdb\_env\_create()**

### static int mdb\_cmp\_long (const MDB\_val \* a, const MDB\_val \* b)` [static]`

*Compare two items pointing at aligned size\_t's*

### static int mdb\_cmp\_int (const MDB\_val \* a, const MDB\_val \* b)` [static]`

*Compare two items pointing at aligned unsigned int's.*

*This is also set as* **MDB\_INTEGERDUP***\|***MDB\_DUPFIXED***'s* **MDB\_dbx***.md\_dcmp, but* **mdb\_cmp\_clong()** *is called instead if the data type is size\_t.*

### static int mdb\_cmp\_cint (const MDB\_val \* a, const MDB\_val \* b)` [static]`

*Compare two items pointing at unsigned ints of unknown alignment. Nodes and keys are guaranteed to be 2-byte aligned.*

### static int mdb\_cmp\_memn (const MDB\_val \* a, const MDB\_val \* b)` [static]`

*Compare two items lexically*

### static int mdb\_cmp\_memnr (const MDB\_val \* a, const MDB\_val \* b)` [static]`

*Compare two items in reverse byte order*

### static int mdb\_page\_search\_lowest (MDB\_cursor \* mc)` [static]`

*Search for the lowest key under the current branch page. This just bypasses a NUMKEYS check in the current page before calling* **mdb\_page\_search\_root()***, because the callers are all in situations where the current page is known to be underfilled.*

### int mdb\_get (MDB\_txn \* txn, MDB\_dbi dbi, MDB\_val \* key, MDB\_val \* data)

*Get items from a database. This function retrieves key/data pairs from the database. The address and length of the data associated with the specified* **key** *are returned in the structure to which* **data** *refers. If the database supports duplicate keys (***MDB\_DUPSORT***) then the first data item for the key will be returned. Retrieval of other items requires the use of* **mdb\_cursor\_get()***.*

**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. For values returned in a read-only transaction any modification attempts will cause a SIGSEGV.*

*Values returned from the database are valid only until a subsequent update operation, or the end of the transaction.*

**Parameters**

*txn A transaction handle returned by* **mdb\_txn\_begin()** \
 *dbi A database handle returned by* **mdb\_dbi\_open()** \
 *key The key to search for in the database* \
 *data The data corresponding to the key*

**Returns**

*A non-zero error value on failure and 0 on success. Some possible errors are:*

- •

  **MDB\_NOTFOUND** *- the key was not in the database.*

- •

  *EINVAL - an invalid parameter was specified.*

### int mdb\_cursor\_get (MDB\_cursor \* cursor, MDB\_val \* key, MDB\_val \* data, MDB\_cursor\_op op)

*Retrieve by cursor. This function retrieves key/data pairs from the database. The address and length of the key are returned in the object to which* **key** *refers (except for the case of the* **MDB\_SET** *option, in which the* **key** *object is unchanged), and the address and length of the data are returned in the object to which* **data** *refers. See* **mdb\_get()** *for restrictions on using the output values.*

**Parameters**

*cursor A cursor handle returned by* **mdb\_cursor\_open()** \
 *key The key for a retrieved item* \
 *data The data of a retrieved item* \
 *op A cursor operation* **MDB\_cursor\_op**

**Returns**

*A non-zero error value on failure and 0 on success. Some possible errors are:*

- •

  **MDB\_NOTFOUND** *- no matching key found.*

- •

  *EINVAL - an invalid parameter was specified.*

### static int mdb\_cursor\_touch (MDB\_cursor \* mc)` [static]`

*Touch all the pages in the cursor stack. Set mc\_top. Makes sure all the pages are writable, before attempting a write operation.*

**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. This function stores key/data pairs into the database. The cursor is positioned at the new item, or on failure usually near it.*

**Note**

*Earlier documentation incorrectly said errors would leave the state of the cursor unchanged.*

**Parameters**

*cursor A cursor handle returned by* **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 must match it. If using sorted duplicates (***MDB\_DUPSORT***) the data item must still sort into the same place. This is intended to be used 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.*

- •

  **MDB\_NODUPDATA** *- enter the new key/data pair only 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 will return* **MDB\_KEYEXIST** *if the key/data pair already appears in the database.*

- •

  **MDB\_NOOVERWRITE** *- enter the new key/data pair only if the key does not already appear in the database. The function will return* **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 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.*

- •

  **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**

*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.*

### int mdb\_cursor\_del (MDB\_cursor \* cursor, unsigned int flags)

*Delete current key/data pair. This function deletes the key/data pair to which the cursor refers. This does not invalidate the cursor, so operations such as MDB\_NEXT can still be used on it. Both MDB\_NEXT and MDB\_GET\_CURRENT will return the same record after this operation.*

**Parameters**

*cursor A cursor handle returned by* **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**

*A non-zero error value on failure and 0 on success. Some possible errors are:*

- •

  *EACCES - an attempt was made to write in a read-only transaction.*

- •

  *EINVAL - an invalid parameter was specified.*

### int mdb\_cursor\_open (MDB\_txn \* txn, MDB\_dbi dbi, MDB\_cursor \*\* cursor)

*Create a cursor handle. A cursor is associated with a specific transaction and database. A cursor cannot be used when its database handle is closed. Nor when its transaction has ended, except with* **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 finally closing it.*

**Note**

*Earlier documentation said that cursors in every transaction were closed when the transaction committed or aborted.*

**Parameters**

*txn A transaction handle returned by* **mdb\_txn\_begin()** \
 *dbi A database handle returned by* **mdb\_dbi\_open()** \
 *cursor Address where the new* **MDB\_cursor** *handle will be stored*

**Returns**

*A non-zero error value on failure and 0 on success. Some possible errors are:*

- •

  *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 a specific transaction and database. Cursors that are only used in read-only transactions may be re-used, to avoid unnecessary malloc/free overhead. The cursor may be associated with a new read-only transaction, and referencing the same database handle as it was created with. This may be done whether the previous transaction is live or dead.*

**Parameters**

*txn A transaction handle returned by* **mdb\_txn\_begin()** \
 *cursor A cursor handle returned by* **mdb\_cursor\_open()**

**Returns**

*A non-zero error value on failure and 0 on success. Some possible errors are:*

- •

  *EINVAL - an invalid parameter was specified.*

### int mdb\_cursor\_count (MDB\_cursor \* cursor, size\_t \* countp)

*Return count of duplicates for current key. This call is only valid on databases that support sorted duplicate data items* **MDB\_DUPSORT***.*

**Parameters**

*cursor A cursor handle returned by* **mdb\_cursor\_open()** \
 *countp Address where the count will be stored*

**Returns**

*A non-zero error value on failure and 0 on success. Some possible errors are:*

- •

  *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 will be freed and must not be used again after this call. Its transaction must still be live if it is a write-transaction.*

**Parameters**

*cursor A cursor handle returned by* **mdb\_cursor\_open()**

### MDB\_txn \* mdb\_cursor\_txn (MDB\_cursor \* cursor)

*Return the cursor's transaction handle.*

**Parameters**

*cursor A cursor handle returned by* **mdb\_cursor\_open()**

### MDB\_dbi mdb\_cursor\_dbi (MDB\_cursor \* cursor)

*Return the cursor's database handle.*

**Parameters**

*cursor A cursor handle returned by* **mdb\_cursor\_open()**

### static void mdb\_cursor\_copy (const MDB\_cursor \* csrc, MDB\_cursor \* cdst)` [static]`

*Copy the contents of a cursor.*

**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 function removes key/data pairs from the database. If the database does not support sorted duplicate data items (***MDB\_DUPSORT***) the data parameter is ignored. If the database supports sorted duplicates and the data parameter is NULL, all of the duplicate data items for the key will be deleted. Otherwise, if the data parameter is non-NULL only the matching data item will be deleted. This function will return* **MDB\_NOTFOUND** *if the specified key/data pair is not in the database.*

**Parameters**

*txn A transaction handle returned by* **mdb\_txn\_begin()** \
 *dbi A database handle returned by* **mdb\_dbi\_open()** \
 *key The key to delete from the database* \
 *data The data to delete*

**Returns**

*A non-zero error value on failure and 0 on success. Some possible errors are:*

- •

  *EACCES - an attempt was made to write in a read-only transaction.*

- •

  *EINVAL - an invalid parameter was specified.*

### int mdb\_put (MDB\_txn \* txn, MDB\_dbi dbi, MDB\_val \* key, MDB\_val \* data, unsigned int flags)

*Store items into a database. This function 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***).*

**Parameters**

*txn A transaction handle returned by* **mdb\_txn\_begin()** \
 *dbi A database handle returned by* **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 to 0 or by bitwise OR'ing together one or more of the values described here.*

- •

  **MDB\_NODUPDATA** *- enter the new key/data pair only 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 will return* **MDB\_KEYEXIST** *if the key/data pair already appears in the database.*

- •

  **MDB\_NOOVERWRITE** *- enter the new key/data pair only if the key does not already appear in the database. The function will return* **MDB\_KEYEXIST** *if the key already appears in the database, even if the database supports duplicates (***MDB\_DUPSORT***). The* **data** *parameter will be set to point to the existing item.*

- •

  **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. LMDB does nothing else with this memory, 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** *- append the given key/data pair to the end of the database. This option allows fast bulk loading when 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.*

### static THREAD\_RET ESECT CALL\_CONV mdb\_env\_copythr (void \* arg)` [static]`

*Dedicated writer thread for compacting copy.*

### static int ESECT mdb\_env\_cthr\_toggle (mdb\_copy \* my, int adjust)` [static]`

*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).*

### static int ESECT mdb\_env\_cwalk (mdb\_copy \* my, pgno\_t \* pg, int flags)` [static]`

*Depth-first tree traversal for compacting copy.*

**Parameters**

*my control structure.* \
 *pg database root.* \
 *flags includes* **F\_DUPDATA** *if it is a sorted-duplicate sub-DB.*

### static int ESECT mdb\_env\_copyfd1 (MDB\_env \* env, HANDLE fd)` [static]`

*Copy environment with compaction.*

### static int ESECT mdb\_env\_copyfd0 (MDB\_env \* env, HANDLE fd)` [static]`

*Copy environment as-is.*

### 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)

*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)

*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.*

**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)

*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)

*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)

*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)

*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.*

**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)

*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)

*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.*

### static int ESECT mdb\_stat0 (MDB\_env \* env, MDB\_db \* db, MDB\_stat \* arg)` [static]`

*Common code for* **mdb\_stat()** *and* **mdb\_env\_stat()***.*

**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)

*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)

*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)

*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.*

*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 returned by* **mdb\_txn\_begin()** \
 *name The name of the database to open. If only a single database is needed in the environment, this value may be NULL.* \
 *flags Special options for this database. This parameter must be set to 0 or by bitwise OR'ing together one or more of the values described here.*

- •

  **MDB\_REVERSEKEY** *Keys are strings to be compared in reverse order, from the end of the strings to the beginning. By default, Keys are treated as strings and compared from beginning to end.*

- •

  **MDB\_DUPSORT** *Duplicate keys may be used in the database. (Or, from another perspective, keys may have multiple data items, stored in sorted order.) By default keys must be unique and may have only a single data item.*

- •

  **MDB\_INTEGERKEY** *Keys are binary integers in native byte order, either unsigned int or size\_t, and will be sorted as such. The keys must all be of the same size.*

- •

  **MDB\_DUPFIXED** *This flag may only be used in combination with* **MDB\_DUPSORT***. This option tells the library that the data items for this database are all the same size, which allows further optimizations in storage and retrieval. When all data items are the same size, the* **MDB\_GET\_MULTIPLE***,* **MDB\_NEXT\_MULTIPLE** *and* **MDB\_PREV\_MULTIPLE** *cursor operations may be used to retrieve multiple items at once.*

- •

  **MDB\_INTEGERDUP** *This option specifies that duplicate data items are binary integers, similar to* **MDB\_INTEGERKEY** *keys.*

- •

  **MDB\_REVERSEDUP** *This option specifies that duplicate data items should be compared as strings in reverse order.*

- •

  **MDB\_CREATE** *Create the named database if it doesn't exist. This option is not allowed in a read-only transaction or a read-only environment.*

*dbi Address where the new* **MDB\_dbi** *handle will be stored*

**Returns**

*A non-zero error value on failure and 0 on success. Some possible errors are:*

- •

  **MDB\_NOTFOUND** *- the specified database doesn't exist in the environment and* **MDB\_CREATE** *was not specified.*

- •

  **MDB\_DBS\_FULL** *- too many databases have been opened. See* **mdb\_env\_set\_maxdbs()***.*

### int ESECT mdb\_stat (MDB\_txn \* txn, MDB\_dbi dbi, MDB\_stat \* stat)

*Retrieve statistics for a database.*

**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. 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 going to reference the database handle or one of its cursors any further. Do not close a handle if an existing transaction has modified its database. Doing so can cause misbehavior from database corruption to errors like MDB\_BAD\_VALSIZE (since the DB name is gone).*

*Closing a database handle is not necessary, but lets* **mdb\_dbi\_open()** *reuse the handle value. Usually it's better to 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.*

**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. See* **mdb\_dbi\_close()** *for restrictions about closing the DB handle.*

**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. The comparison function is called whenever it is necessary to compare a key specified by the application with a key currently stored in the database. If no comparison function is specified, and no special key flags were specified with* **mdb\_dbi\_open()***, the keys are compared lexically, with shorter keys collating before longer keys.*

**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 A* **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 a* **MDB\_DUPSORT** *database. This comparison function is called whenever it is necessary to compare a data item specified by the application with a data item currently stored in the database. This function 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 are compared lexically, with shorter items collating before longer items.*

**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 A* **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 a* **MDB\_FIXEDMAP** *database.*

**Todo**

*The relocation function is called whenever it is necessary to move the data of an item to a different position in the database (e.g. through tree balancing operations, shifts as a result of adds or deletes, etc.). It is intended to allow address/position-dependent data items to be stored in a database in an environment opened with the* **MDB\_FIXEDMAP** *option. Currently the relocation feature is unimplemented and setting this function has no effect.*

**Parameters**

*txn A transaction handle returned by* **mdb\_txn\_begin()** \
 *dbi A database handle returned by* **mdb\_dbi\_open()** \
 *rel A* **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 a* **MDB\_FIXEDMAP** *database's relocation function. See* **mdb\_set\_relfunc** *and* **MDB\_rel\_func** *for more details.*

**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 will 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 we can write. Depends on the compile-time constant* **MDB\_MAXKEYSIZE***. Default 511. See* **MDB\_val***.*

**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.*

**Parameters**

*env An environment handle returned by* **mdb\_env\_create()** \
 *func A* **MDB\_msg\_func** *function* \
 *ctx Anything the message function needs*

**Returns**

*\< 0 on failure, \>= 0 on success.*

### static int ESECT mdb\_pid\_insert (MDB\_PID\_T \* ids, MDB\_PID\_T pid)` [static]`

*Insert pid into list if not already present. return -1 if already present.*

### int ESECT mdb\_reader\_check (MDB\_env \* env, int \* dead)

*Check for stale entries in the reader lock table.*

**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

### char\* const mdb\_errstr\[\]` [static]`

**Initial value:**

```
= {
    "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",
}
```

*Table of descriptions for LMDB* **Return Codes**

### const mdb\_nchar\_t\* const mdb\_suffixes\[2\]\[2\]` [static]`

**Initial value:**

```
= {
    { MDB_NAME("/data.mdb"), MDB_NAME("")      },
    { MDB_NAME("/lock.mdb"), MDB_NAME("-lock") }
}
```

*Filename suffixes \[datafile,lockfile\]\[without,with MDB\_NOSUBDIR\]*

## Author

*Generated automatically by Doxygen for LMDB from the source code.*
