]> git.sur5r.net Git - openldap/commitdiff
Save freelist using proper mdb_cursor_put().
authorHallvard Furuseth <hallvard@openldap.org>
Thu, 11 Jul 2013 20:09:46 +0000 (22:09 +0200)
committerHoward Chu <hyc@symas.com>
Fri, 12 Jul 2013 20:17:04 +0000 (13:17 -0700)
(Restructuring for upcoming mdb_page_spill work.)
mdb_freelist_save() can't just Get() the destination, since
mdb_page_spill() may have put the destination in the read-only map.

TODO: Can this new put() modify the freelist, which would break it? The
final iteration's put() can shorten the node, the rest uses MDB_CURRENT.

We could set P_KEEP on dirty freeDB leaves and ovpages, since they are
all about to be modified.  But the code in this commit must stay anyway,
if mdb should support dropping a 256G DB. I.e. too big for dirty_list.

libraries/liblmdb/mdb.c

index 57353fc0de51242cfae97628e46f0a64760996b9..50887d67899ec62945dd2b384c32d1ecd6dc8949 100644 (file)
@@ -2171,25 +2171,32 @@ mdb_freelist_save(MDB_txn *txn)
                total_room += head_room;
        }
 
-       /* Fill in the reserved, touched me_pghead records. Avoid write ops
-        * so they cannot rearrange anything, just read the destinations.
-        */
+       /* Fill in the reserved, touched me_pghead records */
        rc = MDB_SUCCESS;
        if (mop_len) {
                MDB_val key, data;
 
-               mop += mop_len + 1;
+               mop += mop_len;
                rc = mdb_cursor_first(&mc, &key, &data);
                for (; !rc; rc = mdb_cursor_next(&mc, &key, &data, MDB_NEXT)) {
-                       MDB_IDL dest = data.mv_data;
+                       unsigned flags = MDB_CURRENT;
+                       txnid_t id = *(txnid_t *)key.mv_data;
                        ssize_t len = (ssize_t)(data.mv_size / sizeof(MDB_ID)) - 1;
+                       MDB_ID save;
 
-                       assert(len >= 0 && *(txnid_t*)key.mv_data <= env->me_pglast);
-                       if (len > mop_len)
+                       assert(len >= 0 && id <= env->me_pglast);
+                       key.mv_data = &id;
+                       if (len > mop_len) {
                                len = mop_len;
-                       *dest++ = len;
-                       memcpy(dest, mop -= len, len * sizeof(MDB_ID));
-                       if (! (mop_len -= len))
+                               data.mv_size = (len + 1) * sizeof(MDB_ID);
+                               flags = 0;
+                       }
+                       data.mv_data = mop -= len;
+                       save = mop[0];
+                       mop[0] = len;
+                       rc = mdb_cursor_put(&mc, &key, &data, flags);
+                       mop[0] = save;
+                       if (rc || !(mop_len -= len))
                                break;
                }
        }