]> git.sur5r.net Git - openldap/blobdiff - libraries/liblmdb/mdb.c
ITS#8406 fix xcursors after cursor_del
[openldap] / libraries / liblmdb / mdb.c
index d2e81e4e9c541569279bddcee5d97c9a9ef24fb1..ec7ef8b4710737104267116c3c36f86ac87ad2ba 100644 (file)
@@ -1417,8 +1417,9 @@ mdb_strerror(int err)
         *      This works as long as no function between the call to mdb_strerror
         *      and the actual use of the message uses more than 4K of stack.
         */
-       char pad[4096];
-       char buf[1024], *ptr = buf;
+#define MSGSIZE        1024
+#define PADSIZE 4096
+       char buf[MSGSIZE+PADSIZE], *ptr = buf;
 #endif
        int i;
        if (!err)
@@ -1450,7 +1451,7 @@ mdb_strerror(int err)
        buf[0] = 0;
        FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
                FORMAT_MESSAGE_IGNORE_INSERTS,
-               NULL, err, 0, ptr, sizeof(buf), (va_list *)pad);
+               NULL, err, 0, ptr, MSGSIZE, (va_list *)buf+MSGSIZE);
        return ptr;
 #else
        return strerror(err);
@@ -5643,8 +5644,8 @@ mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
        if (mc->mc_flags & C_EOF) {
                return MDB_NOTFOUND;
        }
-
-       mdb_cassert(mc, mc->mc_flags & C_INITIALIZED);
+       if (!(mc->mc_flags & C_INITIALIZED))
+               return mdb_cursor_first(mc, key, data);
 
        mp = mc->mc_pg[mc->mc_top];
 
@@ -5723,7 +5724,12 @@ mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
        MDB_node        *leaf;
        int rc;
 
-       mdb_cassert(mc, mc->mc_flags & C_INITIALIZED);
+       if (!(mc->mc_flags & C_INITIALIZED)) {
+               rc = mdb_cursor_last(mc, key, data);
+               if (rc)
+                       return rc;
+               mc->mc_ki[mc->mc_top]++;
+       }
 
        mp = mc->mc_pg[mc->mc_top];
 
@@ -5973,8 +5979,8 @@ set1:
                                if (op == MDB_GET_BOTH || rc > 0)
                                        return MDB_NOTFOUND;
                                rc = 0;
-                               *data = olddata;
                        }
+                       *data = olddata;
 
                } else {
                        if (mc->mc_xcursor)
@@ -6169,10 +6175,7 @@ mdb_cursor_get(MDB_cursor *mc, MDB_val *key, MDB_val *data,
                        rc = MDB_INCOMPATIBLE;
                        break;
                }
-               if (!(mc->mc_flags & C_INITIALIZED))
-                       rc = mdb_cursor_first(mc, key, data);
-               else
-                       rc = mdb_cursor_next(mc, key, data, MDB_NEXT_DUP);
+               rc = mdb_cursor_next(mc, key, data, MDB_NEXT_DUP);
                if (rc == MDB_SUCCESS) {
                        if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) {
                                MDB_cursor *mx;
@@ -6190,21 +6193,11 @@ fetchm:
        case MDB_NEXT:
        case MDB_NEXT_DUP:
        case MDB_NEXT_NODUP:
-               if (!(mc->mc_flags & C_INITIALIZED))
-                       rc = mdb_cursor_first(mc, key, data);
-               else
-                       rc = mdb_cursor_next(mc, key, data, op);
+               rc = mdb_cursor_next(mc, key, data, op);
                break;
        case MDB_PREV:
        case MDB_PREV_DUP:
        case MDB_PREV_NODUP:
-               if (!(mc->mc_flags & C_INITIALIZED)) {
-                       rc = mdb_cursor_last(mc, key, data);
-                       if (rc)
-                               break;
-                       mc->mc_flags |= C_INITIALIZED;
-                       mc->mc_ki[mc->mc_top]++;
-               }
                rc = mdb_cursor_prev(mc, key, data, op);
                break;
        case MDB_FIRST:
@@ -8207,8 +8200,6 @@ mdb_cursor_del0(MDB_cursor *mc)
                        if (m3->mc_pg[mc->mc_top] == mp) {
                                if (m3->mc_ki[mc->mc_top] == ki) {
                                        m3->mc_flags |= C_DEL;
-                                       if (mc->mc_db->md_flags & MDB_DUPSORT)
-                                               m3->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED;
                                } else if (m3->mc_ki[mc->mc_top] > ki) {
                                        m3->mc_ki[mc->mc_top]--;
                                }
@@ -8242,11 +8233,21 @@ mdb_cursor_del0(MDB_cursor *mc)
                                continue;
                        if (m3->mc_pg[mc->mc_top] == mp) {
                                /* if m3 points past last node in page, find next sibling */
-                               if (m3->mc_ki[mc->mc_top] >= nkeys) {
-                                       rc = mdb_cursor_sibling(m3, 1);
-                                       if (rc == MDB_NOTFOUND) {
-                                               m3->mc_flags |= C_EOF;
-                                               rc = MDB_SUCCESS;
+                               if (m3->mc_ki[mc->mc_top] >= mc->mc_ki[mc->mc_top]) {
+                                       if (m3->mc_ki[mc->mc_top] >= nkeys) {
+                                               rc = mdb_cursor_sibling(m3, 1);
+                                               if (rc == MDB_NOTFOUND) {
+                                                       m3->mc_flags |= C_EOF;
+                                                       rc = MDB_SUCCESS;
+                                                       continue;
+                                               }
+                                       }
+                                       if (mc->mc_db->md_flags & MDB_DUPSORT) {
+                                               MDB_node *node = NODEPTR(m3->mc_pg[m3->mc_top], m3->mc_ki[m3->mc_top]);
+                                               if (node->mn_flags & F_DUPDATA) {
+                                                       mdb_xcursor_init1(m3, node);
+                                                       m3->mc_xcursor->mx_cursor.mc_flags |= C_DEL;
+                                               }
                                        }
                                }
                        }
@@ -9659,8 +9660,11 @@ mdb_drop0(MDB_cursor *mc, int subs)
 
                /* DUPSORT sub-DBs have no ovpages/DBs. Omit scanning leaves.
                 * This also avoids any P_LEAF2 pages, which have no nodes.
+                * Also if the DB doesn't have sub-DBs and has no overflow
+                * pages, omit scanning leaves.
                 */
-               if (mc->mc_flags & C_SUB)
+               if ((mc->mc_flags & C_SUB) ||
+                       (!subs && !mc->mc_db->md_overflow_pages))
                        mdb_cursor_pop(mc);
 
                mdb_cursor_copy(mc, &mx);
@@ -9682,6 +9686,9 @@ mdb_drop0(MDB_cursor *mc, int subs)
                                                        pg, omp->mp_pages);
                                                if (rc)
                                                        goto done;
+                                               mc->mc_db->md_overflow_pages -= omp->mp_pages;
+                                               if (!mc->mc_db->md_overflow_pages && !subs)
+                                                       break;
                                        } else if (subs && (ni->mn_flags & F_SUBDATA)) {
                                                mdb_xcursor_init1(mc, ni);
                                                rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0);
@@ -9689,6 +9696,8 @@ mdb_drop0(MDB_cursor *mc, int subs)
                                                        goto done;
                                        }
                                }
+                               if (!subs && !mc->mc_db->md_overflow_pages)
+                                       goto pop;
                        } else {
                                if ((rc = mdb_midl_need(&txn->mt_free_pgs, n)) != 0)
                                        goto done;
@@ -9710,6 +9719,7 @@ mdb_drop0(MDB_cursor *mc, int subs)
                                /* no more siblings, go back to beginning
                                 * of previous level.
                                 */
+pop:
                                mdb_cursor_pop(mc);
                                mc->mc_ki[0] = 0;
                                for (i=1; i<mc->mc_snum; i++) {