Commit 027e1daa authored by Howard Chu's avatar Howard Chu
Browse files

Fix mdb_split, tweak split_indx if space is tight

parent 01b9fc59
......@@ -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.
*/
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment