mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-06 10:46:21 +08:00
Fix mdb_split, tweak split_indx if space is tight
This commit is contained in:
parent
01b9fc59fb
commit
027e1daa10
@ -2502,10 +2502,10 @@ mdb_add_node(MDB_txn *txn, MDB_dbi dbi, MDB_page *mp, indx_t indx,
|
||||
|
||||
assert(mp->mp_upper >= mp->mp_lower);
|
||||
|
||||
DPRINTF("add node [%s] to %s page %lu at index %i, key size %zu",
|
||||
key ? DKEY(key) : NULL,
|
||||
DPRINTF("add to %s page %lu index %i, data size %zu key size %zu [%s]",
|
||||
IS_LEAF(mp) ? "leaf" : "branch",
|
||||
mp->mp_pgno, indx, key ? key->mv_size : 0);
|
||||
mp->mp_pgno, indx, data ? data->mv_size : 0,
|
||||
key ? key->mv_size : 0, key ? DKEY(key) : NULL);
|
||||
|
||||
if (IS_LEAF2(mp)) {
|
||||
/* Move higher keys up one slot. */
|
||||
@ -3213,7 +3213,7 @@ mdb_split(MDB_txn *txn, MDB_dbi dbi, MDB_page **mpp, unsigned int *newindxp,
|
||||
int rc = MDB_SUCCESS, ins_new = 0;
|
||||
indx_t newindx;
|
||||
pgno_t pgno = 0;
|
||||
unsigned int i, j, split_indx;
|
||||
unsigned int i, j, split_indx, nkeys, pmax;
|
||||
MDB_node *node;
|
||||
MDB_val sepkey, rkey, rdata;
|
||||
MDB_page *copy;
|
||||
@ -3255,12 +3255,13 @@ mdb_split(MDB_txn *txn, MDB_dbi dbi, MDB_page **mpp, unsigned int *newindxp,
|
||||
rdp->h.md_pi = mdp->h.md_pi + 1;
|
||||
DPRINTF("new right sibling: page %lu", rdp->p.mp_pgno);
|
||||
|
||||
split_indx = NUMKEYS(&mdp->p) / 2 + 1;
|
||||
nkeys = NUMKEYS(&mdp->p);
|
||||
split_indx = nkeys / 2 + 1;
|
||||
|
||||
if (IS_LEAF2(&rdp->p)) {
|
||||
char *split, *ins;
|
||||
int x;
|
||||
unsigned int nkeys = NUMKEYS(&mdp->p), lsize, rsize, ksize;
|
||||
unsigned int lsize, rsize, ksize;
|
||||
/* Move half of the keys to the right sibling */
|
||||
copy = NULL;
|
||||
x = *newindxp - split_indx;
|
||||
@ -3307,6 +3308,46 @@ mdb_split(MDB_txn *txn, MDB_dbi dbi, MDB_page **mpp, unsigned int *newindxp,
|
||||
memset(&mdp->p.mp_ptrs, 0, txn->mt_env->me_psize - PAGEHDRSZ);
|
||||
mdp->p.mp_lower = PAGEHDRSZ;
|
||||
mdp->p.mp_upper = txn->mt_env->me_psize;
|
||||
/* For leaf pages, check the split point based on what
|
||||
* fits where, since otherwise add_node can fail.
|
||||
*/
|
||||
if (IS_LEAF(&mdp->p)) {
|
||||
unsigned int psize, nsize;
|
||||
/* Maximum free space in an empty page */
|
||||
pmax = txn->mt_env->me_psize - PAGEHDRSZ;
|
||||
nsize = mdb_leaf_size(txn->mt_env, newkey, newdata);
|
||||
if (newindx <= split_indx) {
|
||||
split1:
|
||||
psize = nsize;
|
||||
for (i=0; i<split_indx; i++) {
|
||||
node = NODEPTR(&mdp->p, i);
|
||||
psize += NODESIZE + NODEKSZ(node);
|
||||
if (F_ISSET(node->mn_flags, F_BIGDATA))
|
||||
psize += sizeof(pgno_t);
|
||||
else
|
||||
psize += NODEDSZ(node);
|
||||
if (psize > pmax) {
|
||||
split_indx--;
|
||||
goto split1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
split2:
|
||||
psize = nsize;
|
||||
for (i=split_indx; i<nkeys; i++) {
|
||||
node = NODEPTR(&mdp->p, i);
|
||||
psize += NODESIZE + NODEKSZ(node);
|
||||
if (F_ISSET(node->mn_flags, F_BIGDATA))
|
||||
psize += sizeof(pgno_t);
|
||||
else
|
||||
psize += NODEDSZ(node);
|
||||
if (psize > pmax) {
|
||||
split_indx++;
|
||||
goto split2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* First find the separating key between the split pages.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user