mdbx: backport - ITS#8311 fix page_split from update_key.

Check for top of stack. Usually the cursor only has height 1 when
calling page_split, but not always.

Change-Id: Iad221be30edac0f82b650f787e5dbe721cc978e0
This commit is contained in:
Howard Chu 2015-11-18 00:33:25 +00:00 committed by Leo Yuriev
parent 4bdeed9bd3
commit 02da85169e
2 changed files with 18 additions and 8 deletions

View File

@ -16,6 +16,7 @@ LMDB 0.9.17 Release Engineering
Fix ITS#7789 ensure mapsize >= pages in use Fix ITS#7789 ensure mapsize >= pages in use
Fix ITS#7971 mdb_txn_renew0() new reader slots Fix ITS#7971 mdb_txn_renew0() new reader slots
Fix ITS#7969 use __sync_synchronize on non-x86 Fix ITS#7969 use __sync_synchronize on non-x86
Fix ITS#8311 page_split from update_key
Added mdb_txn_id() (ITS#7994) Added mdb_txn_id() (ITS#7994)
Added robust mutex support Added robust mutex support
Miscellaneous cleanup/simplification Miscellaneous cleanup/simplification

25
mdb.c
View File

@ -6509,16 +6509,18 @@ fix_parent:
* update branch key if there is a parent page * update branch key if there is a parent page
*/ */
if (mc->mc_top && !mc->mc_ki[mc->mc_top]) { if (mc->mc_top && !mc->mc_ki[mc->mc_top]) {
unsigned short top = mc->mc_top; unsigned short dtop = 1;
mc->mc_top--; mc->mc_top--;
/* slot 0 is always an empty key, find real slot */ /* slot 0 is always an empty key, find real slot */
while (mc->mc_top && !mc->mc_ki[mc->mc_top]) while (mc->mc_top && !mc->mc_ki[mc->mc_top]) {
mc->mc_top--; mc->mc_top--;
dtop++;
}
if (mc->mc_ki[mc->mc_top]) if (mc->mc_ki[mc->mc_top])
rc2 = mdb_update_key(mc, key); rc2 = mdb_update_key(mc, key);
else else
rc2 = MDB_SUCCESS; rc2 = MDB_SUCCESS;
mc->mc_top = top; mc->mc_top += dtop;
if (rc2) if (rc2)
return rc2; return rc2;
} }
@ -8398,12 +8400,19 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
rp->mp_ksize = mp->mp_ksize; rp->mp_ksize = mp->mp_ksize;
mdb_debug("new right sibling: page %zu", rp->mp_pgno); mdb_debug("new right sibling: page %zu", rp->mp_pgno);
if (mc->mc_snum < 2) { /* Usually when splitting the root page, the cursor
* height is 1. But when called from mdb_update_key,
* the cursor height may be greater because it walks
* up the stack while finding the branch slot to update.
*/
if (mc->mc_top < 1) {
if ((rc = mdb_page_new(mc, P_BRANCH, 1, &pp))) if ((rc = mdb_page_new(mc, P_BRANCH, 1, &pp)))
goto done; goto done;
/* shift current top to make room for new parent */ /* shift current top to make room for new parent */
mc->mc_pg[1] = mc->mc_pg[0]; for (i=mc->mc_snum; i>0; i--) {
mc->mc_ki[1] = mc->mc_ki[0]; mc->mc_pg[i] = mc->mc_pg[i-1];
mc->mc_ki[i] = mc->mc_ki[i-1];
}
mc->mc_pg[0] = pp; mc->mc_pg[0] = pp;
mc->mc_ki[0] = 0; mc->mc_ki[0] = 0;
mc->mc_db->md_root = pp->mp_pgno; mc->mc_db->md_root = pp->mp_pgno;
@ -8419,8 +8428,8 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
mc->mc_db->md_depth--; mc->mc_db->md_depth--;
goto done; goto done;
} }
mc->mc_snum = 2; mc->mc_snum++;
mc->mc_top = 1; mc->mc_top++;
ptop = 0; ptop = 0;
} else { } else {
ptop = mc->mc_top-1; ptop = mc->mc_top-1;