mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-22 15:49: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 (!(env->me_pghead = mop = mdb_midl_alloc(i)))
|
||||
return ENOMEM;
|
||||
} else if (mop_len+i > mop[-1]) {
|
||||
if ((rc = mdb_midl_grow(&env->me_pghead, i)) != 0)
|
||||
} else {
|
||||
if ((rc = mdb_midl_need(&env->me_pghead, i)) != 0)
|
||||
return rc;
|
||||
mop = env->me_pghead;
|
||||
}
|
||||
|
|
@ -1538,12 +1538,13 @@ mdb_page_touch(MDB_cursor *mc)
|
|||
int rc;
|
||||
|
||||
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;
|
||||
pgno = np->mp_pgno;
|
||||
DPRINTF("touched db %u page %zu -> %zu", mc->mc_dbi,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 */
|
||||
if (mc->mc_top) {
|
||||
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) {
|
||||
unsigned j, x;
|
||||
pgno_t *mop = txn->mt_env->me_pghead;
|
||||
pgno_t *mop;
|
||||
MDB_ID2 *dl, ix, iy;
|
||||
/* Prepare to insert pg */
|
||||
j = mop[0] + ovpages;
|
||||
if (j > mop[-1]) {
|
||||
rc = mdb_midl_grow(&mop, ovpages);
|
||||
if (rc)
|
||||
return rc;
|
||||
txn->mt_env->me_pghead = mop;
|
||||
}
|
||||
rc = mdb_midl_need(&txn->mt_env->me_pghead, ovpages);
|
||||
if (rc)
|
||||
return rc;
|
||||
/* Remove from dirty list */
|
||||
dl = txn->mt_u.dirty_list;
|
||||
x = dl[0].mid--;
|
||||
|
|
@ -4231,16 +4227,17 @@ mdb_ovpage_free(MDB_cursor *mc, MDB_page *mp)
|
|||
}
|
||||
}
|
||||
/* Insert in me_pghead */
|
||||
mop = txn->mt_env->me_pghead;
|
||||
j = mop[0] + ovpages;
|
||||
for (i = mop[0]; i && mop[i] < pg; i--)
|
||||
mop[j--] = mop[i];
|
||||
while (j>i)
|
||||
mop[j--] = pg++;
|
||||
mop[0] += ovpages;
|
||||
} else {
|
||||
for (i=0; i<ovpages; i++) {
|
||||
mdb_midl_append(&txn->mt_free_pgs, pg);
|
||||
pg++;
|
||||
}
|
||||
rc = mdb_midl_append_range(&txn->mt_free_pgs, pg, ovpages);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
mc->mc_db->md_overflow_pages -= ovpages;
|
||||
return 0;
|
||||
|
|
@ -5229,7 +5226,8 @@ current:
|
|||
memcpy(METADATA(omp), data->mv_data, data->mv_size);
|
||||
goto done;
|
||||
} else {
|
||||
mdb_ovpage_free(mc, omp);
|
||||
if ((rc2 = mdb_ovpage_free(mc, omp)) != MDB_SUCCESS)
|
||||
return rc2;
|
||||
}
|
||||
} else if (NODEDSZ(leaf) == data->mv_size) {
|
||||
/* same size, just replace it. Note that we could
|
||||
|
|
@ -6308,7 +6306,10 @@ mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
|
|||
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]))
|
||||
csrc->mc_db->md_leaf_pages--;
|
||||
else
|
||||
|
|
@ -6409,7 +6410,9 @@ mdb_rebalance(MDB_cursor *mc)
|
|||
mc->mc_db->md_root = P_INVALID;
|
||||
mc->mc_db->md_depth = 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 */
|
||||
mc->mc_snum = 0;
|
||||
mc->mc_top = 0;
|
||||
|
|
@ -6434,7 +6437,9 @@ mdb_rebalance(MDB_cursor *mc)
|
|||
}
|
||||
} else if (IS_BRANCH(mp) && NUMKEYS(mp) == 1) {
|
||||
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));
|
||||
rc = mdb_page_get(mc->mc_txn,mc->mc_db->md_root,&mc->mc_pg[0],NULL);
|
||||
if (rc)
|
||||
|
|
@ -6539,10 +6544,9 @@ mdb_cursor_del0(MDB_cursor *mc, MDB_node *leaf)
|
|||
pgno_t 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;
|
||||
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);
|
||||
mc->mc_db->md_entries--;
|
||||
|
|
@ -7312,7 +7316,6 @@ mdb_drop0(MDB_cursor *mc, int subs)
|
|||
for (i=0; i<n; i++) {
|
||||
ni = NODEPTR(mp, i);
|
||||
if (ni->mn_flags & F_BIGDATA) {
|
||||
int j, ovpages;
|
||||
MDB_page *omp;
|
||||
pgno_t pg;
|
||||
memcpy(&pg, NODEDATA(ni), sizeof(pg));
|
||||
|
|
@ -7320,11 +7323,10 @@ mdb_drop0(MDB_cursor *mc, int subs)
|
|||
if (rc != 0)
|
||||
return rc;
|
||||
assert(IS_OVERFLOW(omp));
|
||||
ovpages = omp->mp_pages;
|
||||
for (j=0; j<ovpages; j++) {
|
||||
mdb_midl_append(&txn->mt_free_pgs, pg);
|
||||
pg++;
|
||||
}
|
||||
rc = mdb_midl_append_range(&txn->mt_free_pgs,
|
||||
pg, omp->mp_pages);
|
||||
if (rc)
|
||||
return rc;
|
||||
} else if (subs && (ni->mn_flags & F_SUBDATA)) {
|
||||
mdb_xcursor_init1(mc, ni);
|
||||
rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0);
|
||||
|
|
@ -7333,12 +7335,14 @@ mdb_drop0(MDB_cursor *mc, int subs)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if ((rc = mdb_midl_need(&txn->mt_free_pgs, n)) != 0)
|
||||
return rc;
|
||||
for (i=0; i<n; i++) {
|
||||
pgno_t pg;
|
||||
ni = NODEPTR(mp, i);
|
||||
pg = NODEPGNO(ni);
|
||||
/* free it */
|
||||
mdb_midl_append(&txn->mt_free_pgs, pg);
|
||||
mdb_midl_xappend(txn->mt_free_pgs, pg);
|
||||
}
|
||||
}
|
||||
if (!mc->mc_top)
|
||||
|
|
@ -7358,9 +7362,11 @@ mdb_drop0(MDB_cursor *mc, int subs)
|
|||
}
|
||||
}
|
||||
/* 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)
|
||||
|
|
|
|||
|
|
@ -120,8 +120,9 @@ void mdb_midl_free(MDB_IDL ids)
|
|||
int mdb_midl_shrink( MDB_IDL *idp )
|
||||
{
|
||||
MDB_IDL ids = *idp;
|
||||
if (*(--ids) > MDB_IDL_UM_MAX) {
|
||||
ids = realloc(ids, (MDB_IDL_UM_MAX+1) * sizeof(MDB_ID));
|
||||
if (*(--ids) > MDB_IDL_UM_MAX &&
|
||||
(ids = realloc(ids, (MDB_IDL_UM_MAX+1) * sizeof(MDB_ID))))
|
||||
{
|
||||
*ids++ = MDB_IDL_UM_MAX;
|
||||
*idp = ids;
|
||||
return 1;
|
||||
|
|
@ -129,7 +130,7 @@ int mdb_midl_shrink( MDB_IDL *idp )
|
|||
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;
|
||||
/* grow it */
|
||||
|
|
@ -141,6 +142,20 @@ int mdb_midl_grow( MDB_IDL *idp, int num )
|
|||
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 )
|
||||
{
|
||||
MDB_IDL ids = *idp;
|
||||
|
|
@ -169,6 +184,22 @@ int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app )
|
|||
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 */
|
||||
|
||||
#define SMALL 8
|
||||
|
|
|
|||
|
|
@ -68,6 +68,12 @@ typedef MDB_ID *MDB_IDL;
|
|||
#define MDB_IDL_FIRST( ids ) ( (ids)[1] )
|
||||
#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 */
|
||||
/** Insert an ID into an IDL.
|
||||
* @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);
|
||||
|
||||
/** Grow an IDL.
|
||||
* Add room for num additional elements.
|
||||
* @param[in,out] idp Address of the IDL to grow.
|
||||
* @param[in] num Number of elements to add.
|
||||
* @return 0 on success, -1 on failure.
|
||||
/** Make room for num additional elements in an IDL.
|
||||
* @param[in,out] idp Address of the IDL.
|
||||
* @param[in] num Number of elements to make room for.
|
||||
* @return 0 on success, ENOMEM 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.
|
||||
* @param[in,out] idp Address of the IDL to append to.
|
||||
* @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 );
|
||||
|
||||
/** Append an IDL onto an IDL.
|
||||
* @param[in,out] idp Address of the IDL to append to.
|
||||
* @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 );
|
||||
|
||||
/** 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.
|
||||
* @param[in,out] ids The IDL to sort.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue