mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-22 23:59:34 -05:00
Tweak MIDLs, catch errors.
Grow midls earlier in order to catch errors earlier. Use mdb_midl_need() instead of mdb_midl_grow(), then mdb_midl_xappend() needs no error checks. Factor out mdb_midl_append_range().
This commit is contained in:
parent
6b200e3beb
commit
51ff20a4d6
3 changed files with 94 additions and 44 deletions
|
|
@ -1438,8 +1438,8 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
|
||||||
if (!mop) {
|
if (!mop) {
|
||||||
if (!(env->me_pghead = mop = mdb_midl_alloc(i)))
|
if (!(env->me_pghead = mop = mdb_midl_alloc(i)))
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
} else if (mop_len+i > mop[-1]) {
|
} else {
|
||||||
if ((rc = mdb_midl_grow(&env->me_pghead, i)) != 0)
|
if ((rc = mdb_midl_need(&env->me_pghead, i)) != 0)
|
||||||
return rc;
|
return rc;
|
||||||
mop = env->me_pghead;
|
mop = env->me_pghead;
|
||||||
}
|
}
|
||||||
|
|
@ -1538,12 +1538,13 @@ mdb_page_touch(MDB_cursor *mc)
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!F_ISSET(mp->mp_flags, P_DIRTY)) {
|
if (!F_ISSET(mp->mp_flags, P_DIRTY)) {
|
||||||
if ((rc = mdb_page_alloc(mc, 1, &np)))
|
if ((rc = mdb_midl_need(&txn->mt_free_pgs, 1)) ||
|
||||||
|
(rc = mdb_page_alloc(mc, 1, &np)))
|
||||||
return rc;
|
return rc;
|
||||||
pgno = np->mp_pgno;
|
pgno = np->mp_pgno;
|
||||||
DPRINTF("touched db %u page %zu -> %zu", mc->mc_dbi,mp->mp_pgno,pgno);
|
DPRINTF("touched db %u page %zu -> %zu", mc->mc_dbi,mp->mp_pgno,pgno);
|
||||||
assert(mp->mp_pgno != pgno);
|
assert(mp->mp_pgno != pgno);
|
||||||
mdb_midl_append(&txn->mt_free_pgs, mp->mp_pgno);
|
mdb_midl_xappend(txn->mt_free_pgs, mp->mp_pgno);
|
||||||
/* Update the parent page, if any, to point to the new page */
|
/* Update the parent page, if any, to point to the new page */
|
||||||
if (mc->mc_top) {
|
if (mc->mc_top) {
|
||||||
MDB_page *parent = mc->mc_pg[mc->mc_top-1];
|
MDB_page *parent = mc->mc_pg[mc->mc_top-1];
|
||||||
|
|
@ -4207,16 +4208,11 @@ mdb_ovpage_free(MDB_cursor *mc, MDB_page *mp)
|
||||||
*/
|
*/
|
||||||
if ((mp->mp_flags & P_DIRTY) && !txn->mt_parent && txn->mt_env->me_pghead) {
|
if ((mp->mp_flags & P_DIRTY) && !txn->mt_parent && txn->mt_env->me_pghead) {
|
||||||
unsigned j, x;
|
unsigned j, x;
|
||||||
pgno_t *mop = txn->mt_env->me_pghead;
|
pgno_t *mop;
|
||||||
MDB_ID2 *dl, ix, iy;
|
MDB_ID2 *dl, ix, iy;
|
||||||
/* Prepare to insert pg */
|
rc = mdb_midl_need(&txn->mt_env->me_pghead, ovpages);
|
||||||
j = mop[0] + ovpages;
|
|
||||||
if (j > mop[-1]) {
|
|
||||||
rc = mdb_midl_grow(&mop, ovpages);
|
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
txn->mt_env->me_pghead = mop;
|
|
||||||
}
|
|
||||||
/* Remove from dirty list */
|
/* Remove from dirty list */
|
||||||
dl = txn->mt_u.dirty_list;
|
dl = txn->mt_u.dirty_list;
|
||||||
x = dl[0].mid--;
|
x = dl[0].mid--;
|
||||||
|
|
@ -4231,16 +4227,17 @@ mdb_ovpage_free(MDB_cursor *mc, MDB_page *mp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Insert in me_pghead */
|
/* Insert in me_pghead */
|
||||||
|
mop = txn->mt_env->me_pghead;
|
||||||
|
j = mop[0] + ovpages;
|
||||||
for (i = mop[0]; i && mop[i] < pg; i--)
|
for (i = mop[0]; i && mop[i] < pg; i--)
|
||||||
mop[j--] = mop[i];
|
mop[j--] = mop[i];
|
||||||
while (j>i)
|
while (j>i)
|
||||||
mop[j--] = pg++;
|
mop[j--] = pg++;
|
||||||
mop[0] += ovpages;
|
mop[0] += ovpages;
|
||||||
} else {
|
} else {
|
||||||
for (i=0; i<ovpages; i++) {
|
rc = mdb_midl_append_range(&txn->mt_free_pgs, pg, ovpages);
|
||||||
mdb_midl_append(&txn->mt_free_pgs, pg);
|
if (rc)
|
||||||
pg++;
|
return rc;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mc->mc_db->md_overflow_pages -= ovpages;
|
mc->mc_db->md_overflow_pages -= ovpages;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -5229,7 +5226,8 @@ current:
|
||||||
memcpy(METADATA(omp), data->mv_data, data->mv_size);
|
memcpy(METADATA(omp), data->mv_data, data->mv_size);
|
||||||
goto done;
|
goto done;
|
||||||
} else {
|
} else {
|
||||||
mdb_ovpage_free(mc, omp);
|
if ((rc2 = mdb_ovpage_free(mc, omp)) != MDB_SUCCESS)
|
||||||
|
return rc2;
|
||||||
}
|
}
|
||||||
} else if (NODEDSZ(leaf) == data->mv_size) {
|
} else if (NODEDSZ(leaf) == data->mv_size) {
|
||||||
/* same size, just replace it. Note that we could
|
/* same size, just replace it. Note that we could
|
||||||
|
|
@ -6308,7 +6306,10 @@ mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
mdb_midl_append(&csrc->mc_txn->mt_free_pgs, csrc->mc_pg[csrc->mc_top]->mp_pgno);
|
rc = mdb_midl_append(&csrc->mc_txn->mt_free_pgs,
|
||||||
|
csrc->mc_pg[csrc->mc_top]->mp_pgno);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
if (IS_LEAF(csrc->mc_pg[csrc->mc_top]))
|
if (IS_LEAF(csrc->mc_pg[csrc->mc_top]))
|
||||||
csrc->mc_db->md_leaf_pages--;
|
csrc->mc_db->md_leaf_pages--;
|
||||||
else
|
else
|
||||||
|
|
@ -6409,7 +6410,9 @@ mdb_rebalance(MDB_cursor *mc)
|
||||||
mc->mc_db->md_root = P_INVALID;
|
mc->mc_db->md_root = P_INVALID;
|
||||||
mc->mc_db->md_depth = 0;
|
mc->mc_db->md_depth = 0;
|
||||||
mc->mc_db->md_leaf_pages = 0;
|
mc->mc_db->md_leaf_pages = 0;
|
||||||
mdb_midl_append(&mc->mc_txn->mt_free_pgs, mp->mp_pgno);
|
rc = mdb_midl_append(&mc->mc_txn->mt_free_pgs, mp->mp_pgno);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
/* Adjust cursors pointing to mp */
|
/* Adjust cursors pointing to mp */
|
||||||
mc->mc_snum = 0;
|
mc->mc_snum = 0;
|
||||||
mc->mc_top = 0;
|
mc->mc_top = 0;
|
||||||
|
|
@ -6434,7 +6437,9 @@ mdb_rebalance(MDB_cursor *mc)
|
||||||
}
|
}
|
||||||
} else if (IS_BRANCH(mp) && NUMKEYS(mp) == 1) {
|
} else if (IS_BRANCH(mp) && NUMKEYS(mp) == 1) {
|
||||||
DPUTS("collapsing root page!");
|
DPUTS("collapsing root page!");
|
||||||
mdb_midl_append(&mc->mc_txn->mt_free_pgs, mp->mp_pgno);
|
rc = mdb_midl_append(&mc->mc_txn->mt_free_pgs, mp->mp_pgno);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
mc->mc_db->md_root = NODEPGNO(NODEPTR(mp, 0));
|
mc->mc_db->md_root = NODEPGNO(NODEPTR(mp, 0));
|
||||||
rc = mdb_page_get(mc->mc_txn,mc->mc_db->md_root,&mc->mc_pg[0],NULL);
|
rc = mdb_page_get(mc->mc_txn,mc->mc_db->md_root,&mc->mc_pg[0],NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
|
@ -6539,10 +6544,9 @@ mdb_cursor_del0(MDB_cursor *mc, MDB_node *leaf)
|
||||||
pgno_t pg;
|
pgno_t pg;
|
||||||
|
|
||||||
memcpy(&pg, NODEDATA(leaf), sizeof(pg));
|
memcpy(&pg, NODEDATA(leaf), sizeof(pg));
|
||||||
if ((rc = mdb_page_get(mc->mc_txn, pg, &omp, NULL)) != 0)
|
if ((rc = mdb_page_get(mc->mc_txn, pg, &omp, NULL)) ||
|
||||||
|
(rc = mdb_ovpage_free(mc, omp)))
|
||||||
return rc;
|
return rc;
|
||||||
assert(IS_OVERFLOW(omp));
|
|
||||||
mdb_ovpage_free(mc, omp);
|
|
||||||
}
|
}
|
||||||
mdb_node_del(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], mc->mc_db->md_pad);
|
mdb_node_del(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], mc->mc_db->md_pad);
|
||||||
mc->mc_db->md_entries--;
|
mc->mc_db->md_entries--;
|
||||||
|
|
@ -7312,7 +7316,6 @@ mdb_drop0(MDB_cursor *mc, int subs)
|
||||||
for (i=0; i<n; i++) {
|
for (i=0; i<n; i++) {
|
||||||
ni = NODEPTR(mp, i);
|
ni = NODEPTR(mp, i);
|
||||||
if (ni->mn_flags & F_BIGDATA) {
|
if (ni->mn_flags & F_BIGDATA) {
|
||||||
int j, ovpages;
|
|
||||||
MDB_page *omp;
|
MDB_page *omp;
|
||||||
pgno_t pg;
|
pgno_t pg;
|
||||||
memcpy(&pg, NODEDATA(ni), sizeof(pg));
|
memcpy(&pg, NODEDATA(ni), sizeof(pg));
|
||||||
|
|
@ -7320,11 +7323,10 @@ mdb_drop0(MDB_cursor *mc, int subs)
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return rc;
|
return rc;
|
||||||
assert(IS_OVERFLOW(omp));
|
assert(IS_OVERFLOW(omp));
|
||||||
ovpages = omp->mp_pages;
|
rc = mdb_midl_append_range(&txn->mt_free_pgs,
|
||||||
for (j=0; j<ovpages; j++) {
|
pg, omp->mp_pages);
|
||||||
mdb_midl_append(&txn->mt_free_pgs, pg);
|
if (rc)
|
||||||
pg++;
|
return rc;
|
||||||
}
|
|
||||||
} else if (subs && (ni->mn_flags & F_SUBDATA)) {
|
} else if (subs && (ni->mn_flags & F_SUBDATA)) {
|
||||||
mdb_xcursor_init1(mc, ni);
|
mdb_xcursor_init1(mc, ni);
|
||||||
rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0);
|
rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0);
|
||||||
|
|
@ -7333,12 +7335,14 @@ mdb_drop0(MDB_cursor *mc, int subs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if ((rc = mdb_midl_need(&txn->mt_free_pgs, n)) != 0)
|
||||||
|
return rc;
|
||||||
for (i=0; i<n; i++) {
|
for (i=0; i<n; i++) {
|
||||||
pgno_t pg;
|
pgno_t pg;
|
||||||
ni = NODEPTR(mp, i);
|
ni = NODEPTR(mp, i);
|
||||||
pg = NODEPGNO(ni);
|
pg = NODEPGNO(ni);
|
||||||
/* free it */
|
/* free it */
|
||||||
mdb_midl_append(&txn->mt_free_pgs, pg);
|
mdb_midl_xappend(txn->mt_free_pgs, pg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!mc->mc_top)
|
if (!mc->mc_top)
|
||||||
|
|
@ -7358,9 +7362,11 @@ mdb_drop0(MDB_cursor *mc, int subs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* free it */
|
/* free it */
|
||||||
mdb_midl_append(&txn->mt_free_pgs, mc->mc_db->md_root);
|
rc = mdb_midl_append(&txn->mt_free_pgs, mc->mc_db->md_root);
|
||||||
|
} else if (rc == MDB_NOTFOUND) {
|
||||||
|
rc = MDB_SUCCESS;
|
||||||
}
|
}
|
||||||
return 0;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
|
int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
|
||||||
|
|
|
||||||
|
|
@ -120,8 +120,9 @@ void mdb_midl_free(MDB_IDL ids)
|
||||||
int mdb_midl_shrink( MDB_IDL *idp )
|
int mdb_midl_shrink( MDB_IDL *idp )
|
||||||
{
|
{
|
||||||
MDB_IDL ids = *idp;
|
MDB_IDL ids = *idp;
|
||||||
if (*(--ids) > MDB_IDL_UM_MAX) {
|
if (*(--ids) > MDB_IDL_UM_MAX &&
|
||||||
ids = realloc(ids, (MDB_IDL_UM_MAX+1) * sizeof(MDB_ID));
|
(ids = realloc(ids, (MDB_IDL_UM_MAX+1) * sizeof(MDB_ID))))
|
||||||
|
{
|
||||||
*ids++ = MDB_IDL_UM_MAX;
|
*ids++ = MDB_IDL_UM_MAX;
|
||||||
*idp = ids;
|
*idp = ids;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -129,7 +130,7 @@ int mdb_midl_shrink( MDB_IDL *idp )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdb_midl_grow( MDB_IDL *idp, int num )
|
static int mdb_midl_grow( MDB_IDL *idp, int num )
|
||||||
{
|
{
|
||||||
MDB_IDL idn = *idp-1;
|
MDB_IDL idn = *idp-1;
|
||||||
/* grow it */
|
/* grow it */
|
||||||
|
|
@ -141,6 +142,20 @@ int mdb_midl_grow( MDB_IDL *idp, int num )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mdb_midl_need( MDB_IDL *idp, unsigned num )
|
||||||
|
{
|
||||||
|
MDB_IDL ids = *idp;
|
||||||
|
num += ids[0];
|
||||||
|
if (num > ids[-1]) {
|
||||||
|
num = (num + num/4 + (256 + 2)) & -256;
|
||||||
|
if (!(ids = realloc(ids-1, num * sizeof(MDB_ID))))
|
||||||
|
return ENOMEM;
|
||||||
|
*ids++ += num -= 2;
|
||||||
|
*idp = ids;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int mdb_midl_append( MDB_IDL *idp, MDB_ID id )
|
int mdb_midl_append( MDB_IDL *idp, MDB_ID id )
|
||||||
{
|
{
|
||||||
MDB_IDL ids = *idp;
|
MDB_IDL ids = *idp;
|
||||||
|
|
@ -169,6 +184,22 @@ int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n )
|
||||||
|
{
|
||||||
|
MDB_ID *ids = *idp, len = ids[0];
|
||||||
|
/* Too big? */
|
||||||
|
if (len + n > ids[-1]) {
|
||||||
|
if (mdb_midl_grow(idp, n | MDB_IDL_UM_MAX))
|
||||||
|
return ENOMEM;
|
||||||
|
ids = *idp;
|
||||||
|
}
|
||||||
|
ids[0] = len + n;
|
||||||
|
ids += len;
|
||||||
|
while (n)
|
||||||
|
ids[n--] = id++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Quicksort + Insertion sort for small arrays */
|
/* Quicksort + Insertion sort for small arrays */
|
||||||
|
|
||||||
#define SMALL 8
|
#define SMALL 8
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,12 @@ typedef MDB_ID *MDB_IDL;
|
||||||
#define MDB_IDL_FIRST( ids ) ( (ids)[1] )
|
#define MDB_IDL_FIRST( ids ) ( (ids)[1] )
|
||||||
#define MDB_IDL_LAST( ids ) ( (ids)[(ids)[0]] )
|
#define MDB_IDL_LAST( ids ) ( (ids)[(ids)[0]] )
|
||||||
|
|
||||||
|
/** Append ID to IDL. The IDL must be big enough. */
|
||||||
|
#define mdb_midl_xappend(idl, id) do { \
|
||||||
|
MDB_ID *xidl = (idl), xlen = ++(xidl[0]); \
|
||||||
|
xidl[xlen] = (id); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#if 0 /* superseded by append/sort */
|
#if 0 /* superseded by append/sort */
|
||||||
/** Insert an ID into an IDL.
|
/** Insert an ID into an IDL.
|
||||||
* @param[in,out] ids The IDL to insert into.
|
* @param[in,out] ids The IDL to insert into.
|
||||||
|
|
@ -95,28 +101,35 @@ void mdb_midl_free(MDB_IDL ids);
|
||||||
*/
|
*/
|
||||||
int mdb_midl_shrink(MDB_IDL *idp);
|
int mdb_midl_shrink(MDB_IDL *idp);
|
||||||
|
|
||||||
/** Grow an IDL.
|
/** Make room for num additional elements in an IDL.
|
||||||
* Add room for num additional elements.
|
* @param[in,out] idp Address of the IDL.
|
||||||
* @param[in,out] idp Address of the IDL to grow.
|
* @param[in] num Number of elements to make room for.
|
||||||
* @param[in] num Number of elements to add.
|
* @return 0 on success, ENOMEM on failure.
|
||||||
* @return 0 on success, -1 on failure.
|
|
||||||
*/
|
*/
|
||||||
int mdb_midl_grow(MDB_IDL *idp, int num);
|
int mdb_midl_need(MDB_IDL *idp, unsigned num);
|
||||||
|
|
||||||
/** Append an ID onto an IDL.
|
/** Append an ID onto an IDL.
|
||||||
* @param[in,out] idp Address of the IDL to append to.
|
* @param[in,out] idp Address of the IDL to append to.
|
||||||
* @param[in] id The ID to append.
|
* @param[in] id The ID to append.
|
||||||
* @return 0 on success, -1 if the IDL is too large.
|
* @return 0 on success, ENOMEM if the IDL is too large.
|
||||||
*/
|
*/
|
||||||
int mdb_midl_append( MDB_IDL *idp, MDB_ID id );
|
int mdb_midl_append( MDB_IDL *idp, MDB_ID id );
|
||||||
|
|
||||||
/** Append an IDL onto an IDL.
|
/** Append an IDL onto an IDL.
|
||||||
* @param[in,out] idp Address of the IDL to append to.
|
* @param[in,out] idp Address of the IDL to append to.
|
||||||
* @param[in] app The IDL to append.
|
* @param[in] app The IDL to append.
|
||||||
* @return 0 on success, -1 if the IDL is too large.
|
* @return 0 on success, ENOMEM if the IDL is too large.
|
||||||
*/
|
*/
|
||||||
int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app );
|
int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app );
|
||||||
|
|
||||||
|
/** Append an ID range onto an IDL.
|
||||||
|
* @param[in,out] idp Address of the IDL to append to.
|
||||||
|
* @param[in] id The lowest ID to append.
|
||||||
|
* @param[in] n Number of IDs to append.
|
||||||
|
* @return 0 on success, ENOMEM if the IDL is too large.
|
||||||
|
*/
|
||||||
|
int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n );
|
||||||
|
|
||||||
/** Sort an IDL.
|
/** Sort an IDL.
|
||||||
* @param[in,out] ids The IDL to sort.
|
* @param[in,out] ids The IDL to sort.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue