@ -168,6 +168,11 @@
* @ {
* @ {
*/
*/
/* Features under development */
# ifndef MDB_DEVEL
# define MDB_DEVEL 0
# endif
/** Wrapper around __func__, which is a C99 feature */
/** Wrapper around __func__, which is a C99 feature */
# if __STDC_VERSION__ >= 199901L
# if __STDC_VERSION__ >= 199901L
# define mdb_func_ __func__
# define mdb_func_ __func__
@ -372,7 +377,8 @@ static txnid_t mdb_debug_start;
/** @brief The maximum size of a database page.
/** @brief The maximum size of a database page.
*
*
* This is 32 k , since it must fit in # MDB_page . % mp_upper .
* It is 32 k or 64 k , since value - PAGEBASE must fit in
* # MDB_page . % mp_upper .
*
*
* LMDB will use database pages < OS pages if needed .
* LMDB will use database pages < OS pages if needed .
* That causes more I / O in write transactions : The OS must
* That causes more I / O in write transactions : The OS must
@ -385,7 +391,7 @@ static txnid_t mdb_debug_start;
* pressure from other processes is high . So until OSs have
* pressure from other processes is high . So until OSs have
* actual paging support for Huge pages , they ' re not viable .
* actual paging support for Huge pages , they ' re not viable .
*/
*/
# define MAX_PAGESIZE 0x8000
# define MAX_PAGESIZE (PAGEBASE ? 0x10000 : 0x8000)
/** The minimum number of keys required in a database page.
/** The minimum number of keys required in a database page.
* Setting this to a larger value will place a smaller bound on the
* Setting this to a larger value will place a smaller bound on the
@ -408,7 +414,7 @@ static txnid_t mdb_debug_start;
# define MDB_MAGIC 0xBEEFC0DE
# define MDB_MAGIC 0xBEEFC0DE
/** The version number for a database's datafile format. */
/** The version number for a database's datafile format. */
# define MDB_DATA_VERSION 1
# define MDB_DATA_VERSION ((MDB_DEVEL) ? 999 : 1)
/** The version number for a database's lockfile format. */
/** The version number for a database's lockfile format. */
# define MDB_LOCK_VERSION 1
# define MDB_LOCK_VERSION 1
@ -694,16 +700,10 @@ typedef struct MDB_page {
# define METADATA(p) ((void *)((char *)(p) + PAGEHDRSZ))
# define METADATA(p) ((void *)((char *)(p) + PAGEHDRSZ))
/** ITS#7713, change PAGEBASE to handle 65536 byte pages */
/** ITS#7713, change PAGEBASE to handle 65536 byte pages */
# ifdef MDB_DEVEL
# define PAGEBASE ((MDB_DEVEL) ? PAGEHDRSZ : 0)
# define MP_LOBASE 0
# define MP_HIBASE PAGEHDRSZ
# else
# define MP_LOBASE PAGEHDRSZ
# define MP_HIBASE 0
# endif
/** Number of nodes on a page */
/** Number of nodes on a page */
# define NUMKEYS(p) (((p)->mp_lower - MP_LOBASE ) >> 1)
# define NUMKEYS(p) (((p)->mp_lower - (PAGEHDRSZ-PAGEBASE)) >> 1)
/** The amount of space remaining in the page */
/** The amount of space remaining in the page */
# define SIZELEFT(p) (indx_t)((p)->mp_upper - (p)->mp_lower)
# define SIZELEFT(p) (indx_t)((p)->mp_upper - (p)->mp_lower)
@ -784,7 +784,7 @@ typedef struct MDB_node {
# define LEAFSIZE(k, d) (NODESIZE + (k)->mv_size + (d)->mv_size)
# define LEAFSIZE(k, d) (NODESIZE + (k)->mv_size + (d)->mv_size)
/** Address of node \b i in page \b p */
/** Address of node \b i in page \b p */
# define NODEPTR(p, i) ((MDB_node *)((char *)(p) + (p)->mp_ptrs[i] + MP_HI BASE))
# define NODEPTR(p, i) ((MDB_node *)((char *)(p) + (p)->mp_ptrs[i] + PAGE BASE))
/** Address of the key for the node */
/** Address of the key for the node */
# define NODEKEY(node) (void *)((node)->mn_data)
# define NODEKEY(node) (void *)((node)->mn_data)
@ -1394,7 +1394,7 @@ mdb_page_list(MDB_page *mp)
total = EVEN ( total ) ;
total = EVEN ( total ) ;
}
}
fprintf ( stderr , " Total: header %d + contents %d + unused %d \n " ,
fprintf ( stderr , " Total: header %d + contents %d + unused %d \n " ,
IS_LEAF2 ( mp ) ? PAGEHDRSZ : MP_HI BASE + mp - > mp_lower , total , SIZELEFT ( mp ) ) ;
IS_LEAF2 ( mp ) ? PAGEHDRSZ : PAGE BASE + mp - > mp_lower , total , SIZELEFT ( mp ) ) ;
}
}
void
void
@ -2046,10 +2046,10 @@ mdb_page_copy(MDB_page *dst, MDB_page *src, unsigned int psize)
* alignment so memcpy may copy words instead of bytes .
* alignment so memcpy may copy words instead of bytes .
*/
*/
if ( ( unused & = - Align ) & & ! IS_LEAF2 ( src ) ) {
if ( ( unused & = - Align ) & & ! IS_LEAF2 ( src ) ) {
upper & = - Align ;
upper = ( upper + PAGEBASE ) & - Align ;
memcpy ( dst , src , ( lower + MP_HI BASE + ( Align - 1 ) ) & - Align ) ;
memcpy ( dst , src , ( lower + PAGE BASE + ( Align - 1 ) ) & - Align ) ;
memcpy ( ( pgno_t * ) ( ( char * ) dst + upper + MP_HIBASE ) , ( pgno_t * ) ( ( char * ) src + upper + MP_HIBASE ) ,
memcpy ( ( pgno_t * ) ( ( char * ) dst + upper ) , ( pgno_t * ) ( ( char * ) src + upper ) ,
psize - upper - MP_HIBASE ) ;
psize - upper ) ;
} else {
} else {
memcpy ( dst , src , psize - unused ) ;
memcpy ( dst , src , psize - unused ) ;
}
}
@ -5945,11 +5945,14 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
if ( ( mc - > mc_db - > md_flags & MDB_DUPSORT ) & &
if ( ( mc - > mc_db - > md_flags & MDB_DUPSORT ) & &
LEAFSIZE ( key , data ) > env - > me_nodemax )
LEAFSIZE ( key , data ) > env - > me_nodemax )
{
{
/* Too big for a node, insert in sub-DB */
/* Too big for a node, insert in sub-DB. Set up an empty
* " old sub-page " for prep_subDB to expand to a full page .
*/
fp_flags = P_LEAF | P_DIRTY ;
fp_flags = P_LEAF | P_DIRTY ;
fp = env - > me_pbuf ;
fp = env - > me_pbuf ;
fp - > mp_pad = data - > mv_size ; /* used if MDB_DUPFIXED */
fp - > mp_pad = data - > mv_size ; /* used if MDB_DUPFIXED */
fp - > mp_lower = fp - > mp_upper = olddata . mv_size = MP_LOBASE ;
fp - > mp_lower = fp - > mp_upper = ( PAGEHDRSZ - PAGEBASE ) ;
olddata . mv_size = PAGEHDRSZ ;
goto prep_subDB ;
goto prep_subDB ;
}
}
} else {
} else {
@ -6004,7 +6007,7 @@ more:
/* Make sub-page header for the dup items, with dummy body */
/* Make sub-page header for the dup items, with dummy body */
fp - > mp_flags = P_LEAF | P_DIRTY | P_SUBP ;
fp - > mp_flags = P_LEAF | P_DIRTY | P_SUBP ;
fp - > mp_lower = MP_LOBASE ;
fp - > mp_lower = ( PAGEHDRSZ - PAGEBASE ) ;
xdata . mv_size = PAGEHDRSZ + dkey . mv_size + data - > mv_size ;
xdata . mv_size = PAGEHDRSZ + dkey . mv_size + data - > mv_size ;
if ( mc - > mc_db - > md_flags & MDB_DUPFIXED ) {
if ( mc - > mc_db - > md_flags & MDB_DUPFIXED ) {
fp - > mp_flags | = P_LEAF2 ;
fp - > mp_flags | = P_LEAF2 ;
@ -6014,7 +6017,7 @@ more:
xdata . mv_size + = 2 * ( sizeof ( indx_t ) + NODESIZE ) +
xdata . mv_size + = 2 * ( sizeof ( indx_t ) + NODESIZE ) +
( dkey . mv_size & 1 ) + ( data - > mv_size & 1 ) ;
( dkey . mv_size & 1 ) + ( data - > mv_size & 1 ) ;
}
}
fp - > mp_upper = xdata . mv_size - MP_HI BASE;
fp - > mp_upper = xdata . mv_size - PAGE BASE;
olddata . mv_size = xdata . mv_size ; /* pretend olddata is fp */
olddata . mv_size = xdata . mv_size ; /* pretend olddata is fp */
} else if ( leaf - > mn_flags & F_SUBDATA ) {
} else if ( leaf - > mn_flags & F_SUBDATA ) {
/* Data is on sub-DB, just store it */
/* Data is on sub-DB, just store it */
@ -6082,8 +6085,8 @@ prep_subDB:
if ( fp_flags & P_LEAF2 ) {
if ( fp_flags & P_LEAF2 ) {
memcpy ( METADATA ( mp ) , METADATA ( fp ) , NUMKEYS ( fp ) * fp - > mp_pad ) ;
memcpy ( METADATA ( mp ) , METADATA ( fp ) , NUMKEYS ( fp ) * fp - > mp_pad ) ;
} else {
} else {
memcpy ( ( char * ) mp + mp - > mp_upper + MP_HI BASE, ( char * ) fp + fp - > mp_upper + MP_HI BASE,
memcpy ( ( char * ) mp + mp - > mp_upper + PAGE BASE, ( char * ) fp + fp - > mp_upper + PAGE BASE,
olddata . mv_size - fp - > mp_upper ) ;
olddata . mv_size - fp - > mp_upper - PAGEBASE ) ;
for ( i = 0 ; i < NUMKEYS ( fp ) ; i + + )
for ( i = 0 ; i < NUMKEYS ( fp ) ; i + + )
mp - > mp_ptrs [ i ] = fp - > mp_ptrs [ i ] + offset ;
mp - > mp_ptrs [ i ] = fp - > mp_ptrs [ i ] + offset ;
}
}
@ -6404,8 +6407,8 @@ mdb_page_new(MDB_cursor *mc, uint32_t flags, int num, MDB_page **mp)
DPRINTF ( ( " allocated new mpage % " Z " u, page size %u " ,
DPRINTF ( ( " allocated new mpage % " Z " u, page size %u " ,
np - > mp_pgno , mc - > mc_txn - > mt_env - > me_psize ) ) ;
np - > mp_pgno , mc - > mc_txn - > mt_env - > me_psize ) ) ;
np - > mp_flags = flags | P_DIRTY ;
np - > mp_flags = flags | P_DIRTY ;
np - > mp_lower = MP_LOBASE ;
np - > mp_lower = ( PAGEHDRSZ - PAGEBASE ) ;
np - > mp_upper = mc - > mc_txn - > mt_env - > me_psize - MP_HI BASE;
np - > mp_upper = mc - > mc_txn - > mt_env - > me_psize - PAGE BASE;
if ( IS_BRANCH ( np ) )
if ( IS_BRANCH ( np ) )
mc - > mc_db - > md_branch_pages + + ;
mc - > mc_db - > md_branch_pages + + ;
@ -6658,7 +6661,7 @@ mdb_node_del(MDB_cursor *mc, int ksize)
}
}
}
}
base = ( char * ) mp + mp - > mp_upper + MP_HI BASE;
base = ( char * ) mp + mp - > mp_upper + PAGE BASE;
memmove ( base + sz , base , ptr - mp - > mp_upper ) ;
memmove ( base + sz , base , ptr - mp - > mp_upper ) ;
mp - > mp_lower - = sizeof ( indx_t ) ;
mp - > mp_lower - = sizeof ( indx_t ) ;
@ -6712,7 +6715,7 @@ mdb_node_shrink(MDB_page *mp, indx_t indx)
mp - > mp_ptrs [ i ] + = delta ;
mp - > mp_ptrs [ i ] + = delta ;
}
}
base = ( char * ) mp + mp - > mp_upper + MP_HI BASE;
base = ( char * ) mp + mp - > mp_upper + PAGE BASE;
memmove ( base + delta , base , ptr - mp - > mp_upper + NODESIZE + NODEKSZ ( node ) ) ;
memmove ( base + delta , base , ptr - mp - > mp_upper + NODESIZE + NODEKSZ ( node ) ) ;
mp - > mp_upper + = delta ;
mp - > mp_upper + = delta ;
}
}
@ -6984,7 +6987,7 @@ mdb_update_key(MDB_cursor *mc, MDB_val *key)
mp - > mp_ptrs [ i ] - = delta ;
mp - > mp_ptrs [ i ] - = delta ;
}
}
base = ( char * ) mp + mp - > mp_upper + MP_HI BASE;
base = ( char * ) mp + mp - > mp_upper + PAGE BASE;
len = ptr - mp - > mp_upper + NODESIZE ;
len = ptr - mp - > mp_upper + NODESIZE ;
memmove ( base - delta , base , len ) ;
memmove ( base - delta , base , len ) ;
mp - > mp_upper - = delta ;
mp - > mp_upper - = delta ;
@ -7779,8 +7782,8 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
}
}
copy - > mp_pgno = mp - > mp_pgno ;
copy - > mp_pgno = mp - > mp_pgno ;
copy - > mp_flags = mp - > mp_flags ;
copy - > mp_flags = mp - > mp_flags ;
copy - > mp_lower = MP_LOBASE ;
copy - > mp_lower = ( PAGEHDRSZ - PAGEBASE ) ;
copy - > mp_upper = env - > me_psize - MP_HI BASE;
copy - > mp_upper = env - > me_psize - PAGE BASE;
/* prepare to insert */
/* prepare to insert */
for ( i = 0 , j = 0 ; i < nkeys ; i + + ) {
for ( i = 0 , j = 0 ; i < nkeys ; i + + ) {
@ -7820,7 +7823,7 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
psize + = nsize ;
psize + = nsize ;
node = NULL ;
node = NULL ;
} else {
} else {
node = ( MDB_node * ) ( ( char * ) mp + copy - > mp_ptrs [ i ] + MP_HI BASE) ;
node = ( MDB_node * ) ( ( char * ) mp + copy - > mp_ptrs [ i ] + PAGE BASE) ;
psize + = NODESIZE + NODEKSZ ( node ) + sizeof ( indx_t ) ;
psize + = NODESIZE + NODEKSZ ( node ) + sizeof ( indx_t ) ;
if ( IS_LEAF ( mp ) ) {
if ( IS_LEAF ( mp ) ) {
if ( F_ISSET ( node - > mn_flags , F_BIGDATA ) )
if ( F_ISSET ( node - > mn_flags , F_BIGDATA ) )
@ -7840,7 +7843,7 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
sepkey . mv_size = newkey - > mv_size ;
sepkey . mv_size = newkey - > mv_size ;
sepkey . mv_data = newkey - > mv_data ;
sepkey . mv_data = newkey - > mv_data ;
} else {
} else {
node = ( MDB_node * ) ( ( char * ) mp + copy - > mp_ptrs [ split_indx ] + MP_HI BASE) ;
node = ( MDB_node * ) ( ( char * ) mp + copy - > mp_ptrs [ split_indx ] + PAGE BASE) ;
sepkey . mv_size = node - > mn_ksize ;
sepkey . mv_size = node - > mn_ksize ;
sepkey . mv_data = NODEKEY ( node ) ;
sepkey . mv_data = NODEKEY ( node ) ;
}
}
@ -7921,7 +7924,7 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
/* Update index for the new key. */
/* Update index for the new key. */
mc - > mc_ki [ mc - > mc_top ] = j ;
mc - > mc_ki [ mc - > mc_top ] = j ;
} else {
} else {
node = ( MDB_node * ) ( ( char * ) mp + copy - > mp_ptrs [ i ] + MP_HI BASE) ;
node = ( MDB_node * ) ( ( char * ) mp + copy - > mp_ptrs [ i ] + PAGE BASE) ;
rkey . mv_data = NODEKEY ( node ) ;
rkey . mv_data = NODEKEY ( node ) ;
rkey . mv_size = node - > mn_ksize ;
rkey . mv_size = node - > mn_ksize ;
if ( IS_LEAF ( mp ) ) {
if ( IS_LEAF ( mp ) ) {
@ -7957,7 +7960,7 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
mp - > mp_lower = copy - > mp_lower ;
mp - > mp_lower = copy - > mp_lower ;
mp - > mp_upper = copy - > mp_upper ;
mp - > mp_upper = copy - > mp_upper ;
memcpy ( NODEPTR ( mp , nkeys - 1 ) , NODEPTR ( copy , nkeys - 1 ) ,
memcpy ( NODEPTR ( mp , nkeys - 1 ) , NODEPTR ( copy , nkeys - 1 ) ,
env - > me_psize - copy - > mp_upper - MP_HI BASE) ;
env - > me_psize - copy - > mp_upper - PAGE BASE) ;
/* reset back to original page */
/* reset back to original page */
if ( newindx < split_indx ) {
if ( newindx < split_indx ) {