]> git.sur5r.net Git - openldap/blobdiff - libraries/liblmdb/mdb.c
ITS#8321 track temporary cursors
[openldap] / libraries / liblmdb / mdb.c
index 31cf1884719cdecdda6fb24e3cfc19feaa821054..7ac24610ff6e13013cd2ea34cab4cb0f78d6956e 100644 (file)
@@ -7645,6 +7645,22 @@ mdb_update_key(MDB_cursor *mc, MDB_val *key)
 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
@@ -7800,6 +7816,7 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)
         */
        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 {
@@ -7812,7 +7829,11 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)
                        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])) {
@@ -7828,6 +7849,7 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)
 
        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 {
@@ -7840,7 +7862,11 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)
                        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])) {
@@ -8198,24 +8224,13 @@ mdb_rebalance(MDB_cursor *mc)
                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;
@@ -8581,10 +8596,14 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
         */
        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;