@ -7620,16 +7620,12 @@ skip:
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
mdb_xcursor_init1 ( mc , leaf ) ;
mdb_xcursor_init1 ( mc , leaf ) ;
}
rc = mdb_cursor_first ( & mc - > mc_xcursor - > mx_cursor , data , NULL ) ;
if ( data ) {
if ( rc ! = MDB_SUCCESS )
return rc ;
} else if ( data ) {
if ( ( rc = mdb_node_read ( mc , leaf , data ) ) ! = MDB_SUCCESS )
if ( ( rc = mdb_node_read ( mc , leaf , data ) ) ! = MDB_SUCCESS )
return rc ;
return rc ;
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
rc = mdb_cursor_first ( & mc - > mc_xcursor - > mx_cursor , data , NULL ) ;
if ( rc ! = MDB_SUCCESS )
return rc ;
}
}
}
MDB_GET_KEY ( leaf , key ) ;
MDB_GET_KEY ( leaf , key ) ;
@ -7653,7 +7649,8 @@ mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
mp = mc - > mc_pg [ mc - > mc_top ] ;
mp = mc - > mc_pg [ mc - > mc_top ] ;
if ( mc - > mc_db - > md_flags & MDB_DUPSORT ) {
if ( ( mc - > mc_db - > md_flags & MDB_DUPSORT ) & &
mc - > mc_ki [ mc - > mc_top ] < NUMKEYS ( mp ) ) {
leaf = NODEPTR ( mp , mc - > mc_ki [ mc - > mc_top ] ) ;
leaf = NODEPTR ( mp , mc - > mc_ki [ mc - > mc_top ] ) ;
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
if ( op = = MDB_PREV | | op = = MDB_PREV_DUP ) {
if ( op = = MDB_PREV | | op = = MDB_PREV_DUP ) {
@ -7695,27 +7692,25 @@ mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
DPRINTF ( ( " ==> cursor points to page % " Yu " with %u keys, key index %u " ,
DPRINTF ( ( " ==> cursor points to page % " Yu " with %u keys, key index %u " ,
mdb_dbg_pgno ( mp ) , NUMKEYS ( mp ) , mc - > mc_ki [ mc - > mc_top ] ) ) ;
mdb_dbg_pgno ( mp ) , NUMKEYS ( mp ) , mc - > mc_ki [ mc - > mc_top ] ) ) ;
if ( ! IS_LEAF ( mp ) )
return MDB_CORRUPTED ;
if ( IS_LEAF2 ( mp ) ) {
if ( IS_LEAF2 ( mp ) ) {
key - > mv_size = mc - > mc_db - > md_pad ;
key - > mv_size = mc - > mc_db - > md_pad ;
key - > mv_data = LEAF2KEY ( mp , mc - > mc_ki [ mc - > mc_top ] , key - > mv_size ) ;
key - > mv_data = LEAF2KEY ( mp , mc - > mc_ki [ mc - > mc_top ] , key - > mv_size ) ;
return MDB_SUCCESS ;
return MDB_SUCCESS ;
}
}
mdb_cassert ( mc , IS_LEAF ( mp ) ) ;
leaf = NODEPTR ( mp , mc - > mc_ki [ mc - > mc_top ] ) ;
leaf = NODEPTR ( mp , mc - > mc_ki [ mc - > mc_top ] ) ;
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
mdb_xcursor_init1 ( mc , leaf ) ;
mdb_xcursor_init1 ( mc , leaf ) ;
}
rc = mdb_cursor_last ( & mc - > mc_xcursor - > mx_cursor , data , NULL ) ;
if ( data ) {
if ( rc ! = MDB_SUCCESS )
return rc ;
} else if ( data ) {
if ( ( rc = mdb_node_read ( mc , leaf , data ) ) ! = MDB_SUCCESS )
if ( ( rc = mdb_node_read ( mc , leaf , data ) ) ! = MDB_SUCCESS )
return rc ;
return rc ;
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
rc = mdb_cursor_last ( & mc - > mc_xcursor - > mx_cursor , data , NULL ) ;
if ( rc ! = MDB_SUCCESS )
return rc ;
}
}
}
MDB_GET_KEY ( leaf , key ) ;
MDB_GET_KEY ( leaf , key ) ;
@ -7873,24 +7868,22 @@ set1:
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
mdb_xcursor_init1 ( mc , leaf ) ;
mdb_xcursor_init1 ( mc , leaf ) ;
}
if ( op = = MDB_SET | | op = = MDB_SET_KEY | | op = = MDB_SET_RANGE ) {
if ( data ) {
rc = mdb_cursor_first ( & mc - > mc_xcursor - > mx_cursor , data , NULL ) ;
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
} else {
if ( op = = MDB_SET | | op = = MDB_SET_KEY | | op = = MDB_SET_RANGE ) {
int ex2 , * ex2p ;
rc = mdb_cursor_first ( & mc - > mc_xcursor - > mx_cursor , data , NULL ) ;
if ( op = = MDB_GET_BOTH ) {
ex2p = & ex2 ;
ex2 = 0 ;
} else {
} else {
int ex2 , * ex2p ;
ex2p = NULL ;
if ( op = = MDB_GET_BOTH ) {
ex2p = & ex2 ;
ex2 = 0 ;
} else {
ex2p = NULL ;
}
rc = mdb_cursor_set ( & mc - > mc_xcursor - > mx_cursor , data , NULL , MDB_SET_RANGE , ex2p ) ;
if ( rc ! = MDB_SUCCESS )
return rc ;
}
}
} else if ( op = = MDB_GET_BOTH | | op = = MDB_GET_BOTH_RANGE ) {
rc = mdb_cursor_set ( & mc - > mc_xcursor - > mx_cursor , data , NULL , MDB_SET_RANGE , ex2p ) ;
if ( rc ! = MDB_SUCCESS )
return rc ;
}
} else if ( data ) {
if ( op = = MDB_GET_BOTH | | op = = MDB_GET_BOTH_RANGE ) {
MDB_val olddata ;
MDB_val olddata ;
MDB_cmp_func * dcmp ;
MDB_cmp_func * dcmp ;
if ( ( rc = mdb_node_read ( mc , leaf , & olddata ) ) ! = MDB_SUCCESS )
if ( ( rc = mdb_node_read ( mc , leaf , & olddata ) ) ! = MDB_SUCCESS )
@ -7948,22 +7941,23 @@ mdb_cursor_first(MDB_cursor *mc, MDB_val *key, MDB_val *data)
mc - > mc_ki [ mc - > mc_top ] = 0 ;
mc - > mc_ki [ mc - > mc_top ] = 0 ;
if ( IS_LEAF2 ( mc - > mc_pg [ mc - > mc_top ] ) ) {
if ( IS_LEAF2 ( mc - > mc_pg [ mc - > mc_top ] ) ) {
key - > mv_size = mc - > mc_db - > md_pad ;
if ( key ) {
key - > mv_data = LEAF2KEY ( mc - > mc_pg [ mc - > mc_top ] , 0 , key - > mv_size ) ;
key - > mv_size = mc - > mc_db - > md_pad ;
key - > mv_data = LEAF2KEY ( mc - > mc_pg [ mc - > mc_top ] , 0 , key - > mv_size ) ;
}
return MDB_SUCCESS ;
return MDB_SUCCESS ;
}
}
if ( data ) {
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
mdb_xcursor_init1 ( mc , leaf ) ;
mdb_xcursor_init1 ( mc , leaf ) ;
rc = mdb_cursor_first ( & mc - > mc_xcursor - > mx_cursor , data , NULL ) ;
rc = mdb_cursor_first ( & mc - > mc_xcursor - > mx_cursor , data , NULL ) ;
if ( rc )
if ( rc )
return rc ;
return rc ;
} else if ( data ) {
} else {
if ( ( rc = mdb_node_read ( mc , leaf , data ) ) ! = MDB_SUCCESS )
if ( ( rc = mdb_node_read ( mc , leaf , data ) ) ! = MDB_SUCCESS )
return rc ;
return rc ;
}
}
}
MDB_GET_KEY ( leaf , key ) ;
MDB_GET_KEY ( leaf , key ) ;
return MDB_SUCCESS ;
return MDB_SUCCESS ;
}
}
@ -7992,21 +7986,21 @@ mdb_cursor_last(MDB_cursor *mc, MDB_val *key, MDB_val *data)
leaf = NODEPTR ( mc - > mc_pg [ mc - > mc_top ] , mc - > mc_ki [ mc - > mc_top ] ) ;
leaf = NODEPTR ( mc - > mc_pg [ mc - > mc_top ] , mc - > mc_ki [ mc - > mc_top ] ) ;
if ( IS_LEAF2 ( mc - > mc_pg [ mc - > mc_top ] ) ) {
if ( IS_LEAF2 ( mc - > mc_pg [ mc - > mc_top ] ) ) {
key - > mv_size = mc - > mc_db - > md_pad ;
if ( key ) {
key - > mv_data = LEAF2KEY ( mc - > mc_pg [ mc - > mc_top ] , mc - > mc_ki [ mc - > mc_top ] , key - > mv_size ) ;
key - > mv_size = mc - > mc_db - > md_pad ;
key - > mv_data = LEAF2KEY ( mc - > mc_pg [ mc - > mc_top ] , mc - > mc_ki [ mc - > mc_top ] , key - > mv_size ) ;
}
return MDB_SUCCESS ;
return MDB_SUCCESS ;
}
}
if ( data ) {
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
if ( F_ISSET ( leaf - > mn_flags , F_DUPDATA ) ) {
mdb_xcursor_init1 ( mc , leaf ) ;
mdb_xcursor_init1 ( mc , leaf ) ;
rc = mdb_cursor_last ( & mc - > mc_xcursor - > mx_cursor , data , NULL ) ;
rc = mdb_cursor_last ( & mc - > mc_xcursor - > mx_cursor , data , NULL ) ;
if ( rc )
if ( rc )
return rc ;
return rc ;
} else if ( data ) {
} else {
if ( ( rc = mdb_node_read ( mc , leaf , data ) ) ! = MDB_SUCCESS )
if ( ( rc = mdb_node_read ( mc , leaf , data ) ) ! = MDB_SUCCESS )
return rc ;
return rc ;
}
}
}
MDB_GET_KEY ( leaf , key ) ;
MDB_GET_KEY ( leaf , key ) ;
@ -8782,6 +8776,8 @@ mdb_cursor_del(MDB_cursor *mc, unsigned int flags)
return rc ;
return rc ;
mp = mc - > mc_pg [ mc - > mc_top ] ;
mp = mc - > mc_pg [ mc - > mc_top ] ;
if ( ! IS_LEAF ( mp ) )
return MDB_CORRUPTED ;
if ( IS_LEAF2 ( mp ) )
if ( IS_LEAF2 ( mp ) )
goto del_key ;
goto del_key ;
leaf = NODEPTR ( mp , mc - > mc_ki [ mc - > mc_top ] ) ;
leaf = NODEPTR ( mp , mc - > mc_ki [ mc - > mc_top ] ) ;
@ -10180,60 +10176,70 @@ mdb_cursor_del0(MDB_cursor *mc)
}
}
}
}
rc = mdb_rebalance ( mc ) ;
rc = mdb_rebalance ( mc ) ;
if ( rc )
goto fail ;
if ( rc = = MDB_SUCCESS ) {
/* DB is totally empty now, just bail out.
/* DB is totally empty now, just bail out.
* Other cursors adjustments were already done
* Other cursors adjustments were already done
* by mdb_rebalance and aren ' t needed here .
* by mdb_rebalance and aren ' t needed here .
*/
*/
if ( ! mc - > mc_snum ) {
if ( ! mc - > mc_snum )
mc - > mc_flags | = C_EOF ;
return rc ;
return rc ;
}
mp = mc - > mc_pg [ mc - > mc_top ] ;
ki = mc - > mc_ki [ mc - > mc_top ] ;
nkeys = NUMKEYS ( mp ) ;
mp = mc - > mc_pg [ mc - > mc_top ] ;
nkeys = NUMKEYS ( mp ) ;
/* Adjust other cursors pointing to mp */
/* Adjust other cursors pointing to mp */
for ( m2 = mc - > mc_txn - > mt_cursors [ dbi ] ; ! rc & & m2 ; m2 = m2 - > mc_next ) {
for ( m2 = mc - > mc_txn - > mt_cursors [ dbi ] ; ! rc & & m2 ; m2 = m2 - > mc_next ) {
m3 = ( mc - > mc_flags & C_SUB ) ? & m2 - > mc_xcursor - > mx_cursor : m2 ;
m3 = ( mc - > mc_flags & C_SUB ) ? & m2 - > mc_xcursor - > mx_cursor : m2 ;
if ( ! ( m2 - > mc_flags & m3 - > mc_flags & C_INITIALIZED ) )
if ( ! ( m2 - > mc_flags & m3 - > mc_flags & C_INITIALIZED ) )
continue ;
continue ;
if ( m3 - > mc_snum < mc - > mc_snum )
if ( m3 - > mc_snum < mc - > mc_snum )
continue ;
continue ;
if ( m3 - > mc_pg [ mc - > mc_top ] = = mp ) {
if ( m3 - > mc_pg [ mc - > mc_top ] = = mp ) {
/* if m3 points past last node in page, find next sibling */
/* if m3 points past last node in page, find next sibling */
if ( m3 - > mc_ki [ mc - > mc_top ] > = mc - > mc_ki [ mc - > mc_top ] ) {
if ( m3 - > mc_ki [ mc - > mc_top ] > = nkeys ) {
if ( m3 - > mc_ki [ mc - > mc_top ] > = nkeys ) {
rc = mdb_cursor_sibling ( m3 , 1 ) ;
rc = mdb_cursor_sibling ( m3 , 1 ) ;
if ( rc = = MDB_NOTFOUND ) {
if ( rc = = MDB_NOTFOUND ) {
m3 - > mc_flags | = C_EOF ;
m3 - > mc_flags | = C_EOF ;
rc = MDB_SUCCESS ;
rc = MDB_SUCCESS ;
continue ;
continue ;
}
}
if ( rc )
}
goto fail ;
if ( mc - > mc_db - > md_flags & MDB_DUPSORT ) {
}
MDB_node * node = NODEPTR ( m3 - > mc_pg [ m3 - > mc_top ] , m3 - > mc_ki [ m3 - > mc_top ] ) ;
if ( m3 - > mc_ki [ mc - > mc_top ] > = ki | |
/* If this node has dupdata, it may need to be reinited
/* moved to right sibling */ m3 - > mc_pg [ mc - > mc_top ] ! = mp ) {
* because its data has moved .
if ( m3 - > mc_xcursor & & ! ( m3 - > mc_flags & C_EOF ) ) {
* If the xcursor was not initd it must be reinited .
MDB_node * node = NODEPTR ( m3 - > mc_pg [ m3 - > mc_top ] , m3 - > mc_ki [ m3 - > mc_top ] ) ;
* Else if node points to a subDB , nothing is needed .
/* If this node has dupdata, it may need to be reinited
* Else ( xcursor was initd , not a subDB ) needs mc_pg [ 0 ] reset .
* because its data has moved .
*/
* If the xcursor was not initd it must be reinited .
if ( node - > mn_flags & F_DUPDATA ) {
* Else if node points to a subDB , nothing is needed .
if ( m3 - > mc_xcursor - > mx_cursor . mc_flags & C_INITIALIZED ) {
* Else ( xcursor was initd , not a subDB ) needs mc_pg [ 0 ] reset .
if ( ! ( node - > mn_flags & F_SUBDATA ) )
*/
m3 - > mc_xcursor - > mx_cursor . mc_pg [ 0 ] = NODEDATA ( node ) ;
if ( node - > mn_flags & F_DUPDATA ) {
} else {
if ( m3 - > mc_xcursor - > mx_cursor . mc_flags & C_INITIALIZED ) {
mdb_xcursor_init1 ( m3 , node ) ;
if ( ! ( node - > mn_flags & F_SUBDATA ) )
m3 - > mc_xcursor - > mx_cursor . mc_flags | = C_DEL ;
m3 - > mc_xcursor - > mx_cursor . mc_pg [ 0 ] = NODEDATA ( node ) ;
}
} else {
mdb_xcursor_init1 ( m3 , node ) ;
rc = mdb_cursor_first ( & m3 - > mc_xcursor - > mx_cursor , NULL , NULL ) ;
if ( rc )
goto fail ;
}
}
}
}
m3 - > mc_xcursor - > mx_cursor . mc_flags | = C_DEL ;
}
}
m3 - > mc_flags | = C_DEL ;
}
}
}
}
mc - > mc_flags | = C_DEL ;
}
}
fail :
if ( rc )
if ( rc )
mc - > mc_txn - > mt_flags | = MDB_TXN_ERROR ;
mc - > mc_txn - > mt_flags | = MDB_TXN_ERROR ;
return rc ;
return rc ;