static void
mdb_cursor_copy(const MDB_cursor *csrc, MDB_cursor *cdst);
+/** Track a temporary cursor */
+#define CURSOR_TMP_TRACK(mc, mn, dummy, tracked) \
+ if (mc->mc_flags & C_SUB) { \
+ dummy.mc_flags = C_INITIALIZED; \
+ dummy.mc_xcursor = (MDB_xcursor *)&mn; \
+ tracked = &dummy; \
+ } else { \
+ tracked = &mn; \
+ } \
+ tracked->mc_next = mc->mc_txn->mt_cursors[mc->mc_dbi]; \
+ mc->mc_txn->mt_cursors[mc->mc_dbi] = tracked
+
+/** Stop tracking a temporary cursor */
+#define CURSOR_TMP_UNTRACK(mc, tracked) \
+ mc->mc_txn->mt_cursors[mc->mc_dbi] = tracked->mc_next
+
/** Move a node from csrc to cdst.
*/
static int
*/
if (csrc->mc_ki[csrc->mc_top] == 0) {
if (csrc->mc_ki[csrc->mc_top-1] != 0) {
+ MDB_cursor dummy, *tracked;
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size);
} else {
mdb_cursor_copy(csrc, &mn);
mn.mc_snum--;
mn.mc_top--;
- if ((rc = mdb_update_key(&mn, &key)) != MDB_SUCCESS)
+ /* We want mdb_rebalance to find mn when doing fixups */
+ CURSOR_TMP_TRACK(csrc, mn, dummy, tracked);
+ rc = mdb_update_key(&mn, &key);
+ CURSOR_TMP_UNTRACK(csrc, tracked);
+ if (rc)
return rc;
}
if (IS_BRANCH(csrc->mc_pg[csrc->mc_top])) {
if (cdst->mc_ki[cdst->mc_top] == 0) {
if (cdst->mc_ki[cdst->mc_top-1] != 0) {
+ MDB_cursor dummy, *tracked;
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
key.mv_data = LEAF2KEY(cdst->mc_pg[cdst->mc_top], 0, key.mv_size);
} else {
mdb_cursor_copy(cdst, &mn);
mn.mc_snum--;
mn.mc_top--;
- if ((rc = mdb_update_key(&mn, &key)) != MDB_SUCCESS)
+ /* We want mdb_rebalance to find mn when doing fixups */
+ CURSOR_TMP_TRACK(cdst, mn, dummy, tracked);
+ rc = mdb_update_key(&mn, &key);
+ CURSOR_TMP_UNTRACK(cdst, tracked);
+ if (rc)
return rc;
}
if (IS_BRANCH(cdst->mc_pg[cdst->mc_top])) {
if (!fromleft) {
rc = mdb_page_merge(&mn, mc);
} else {
- MDB_cursor dummy;
+ MDB_cursor dummy, *tracked;
oldki += NUMKEYS(mn.mc_pg[mn.mc_top]);
mn.mc_ki[mn.mc_top] += mc->mc_ki[mn.mc_top] + 1;
/* We want mdb_rebalance to find mn when doing fixups */
- if (mc->mc_flags & C_SUB) {
- dummy.mc_flags = C_INITIALIZED;
- dummy.mc_next = mc->mc_txn->mt_cursors[mc->mc_dbi];
- mc->mc_txn->mt_cursors[mc->mc_dbi] = &dummy;
- dummy.mc_xcursor = (MDB_xcursor *)&mn;
- } else {
- mn.mc_next = mc->mc_txn->mt_cursors[mc->mc_dbi];
- mc->mc_txn->mt_cursors[mc->mc_dbi] = &mn;
- }
+ CURSOR_TMP_TRACK(mc, mn, dummy, tracked);
rc = mdb_page_merge(mc, &mn);
- if (mc->mc_flags & C_SUB)
- mc->mc_txn->mt_cursors[mc->mc_dbi] = dummy.mc_next;
- else
- mc->mc_txn->mt_cursors[mc->mc_dbi] = mn.mc_next;
+ CURSOR_TMP_UNTRACK(mc, tracked);
mdb_cursor_copy(&mn, mc);
}
mc->mc_flags &= ~C_EOF;
*/
if (SIZELEFT(mn.mc_pg[ptop]) < mdb_branch_size(env, &sepkey)) {
int snum = mc->mc_snum;
+ MDB_cursor dummy, *tracked;
mn.mc_snum--;
mn.mc_top--;
did_split = 1;
+ /* We want other splits to find mn when doing fixups */
+ CURSOR_TMP_TRACK(mc, mn, dummy, tracked);
rc = mdb_page_split(&mn, &sepkey, NULL, rp->mp_pgno, 0);
+ CURSOR_TMP_UNTRACK(mc, tracked);
if (rc)
goto done;