]> git.sur5r.net Git - openldap/commitdiff
Write optimization: avoid copying unused portions of pages.
authorHoward Chu <hyc@symas.com>
Tue, 31 Jul 2012 23:03:48 +0000 (16:03 -0700)
committerHoward Chu <hyc@symas.com>
Tue, 31 Jul 2012 23:03:48 +0000 (16:03 -0700)
libraries/libmdb/mdb.c

index 4563e23e8be2eaf09f2f00e8cb26e272d2df3b71..2db10eab34a8d4c1f4b6ac7d01b98ccc88bb2233 100644 (file)
@@ -1328,6 +1328,27 @@ none:
        return np;
 }
 
+/** Copy a page: avoid copying unused portions of the page.
+ * @param[in] dst page to copy into
+ * @param[in] src page to copy from
+ */
+static void
+mdb_page_copy(MDB_page *dst, MDB_page *src, unsigned int psize)
+{
+       dst->mp_flags = src->mp_flags | P_DIRTY;
+       dst->mp_pages = src->mp_pages;
+
+       if (IS_LEAF2(src)) {
+               memcpy(dst->mp_ptrs, src->mp_ptrs, psize - PAGEHDRSZ - SIZELEFT(src));
+       } else {
+               unsigned int i, nkeys = NUMKEYS(src);
+               for (i=0; i<nkeys; i++)
+                       dst->mp_ptrs[i] = src->mp_ptrs[i];
+               memcpy((char *)dst+src->mp_upper, (char *)src+src->mp_upper,
+                       psize - src->mp_upper);
+       }
+}
+
 /** Touch a page: make it dirty and re-insert into tree with updated pgno.
  * @param[in] mc cursor pointing to the page to be touched
  * @return 0 on success, non-zero on failure.
@@ -1345,11 +1366,16 @@ mdb_page_touch(MDB_cursor *mc)
                DPRINTF("touched db %u page %zu -> %zu", mc->mc_dbi, mp->mp_pgno, np->mp_pgno);
                assert(mp->mp_pgno != np->mp_pgno);
                mdb_midl_append(&mc->mc_txn->mt_free_pgs, mp->mp_pgno);
-               pgno = np->mp_pgno;
-               memcpy(np, mp, mc->mc_txn->mt_env->me_psize);
+               if (SIZELEFT(mp)) {
+                       /* If page isn't full, just copy the used portion */
+                       mdb_page_copy(np, mp, mc->mc_txn->mt_env->me_psize);
+               } else {
+                       pgno = np->mp_pgno;
+                       memcpy(np, mp, mc->mc_txn->mt_env->me_psize);
+                       np->mp_pgno = pgno;
+                       np->mp_flags |= P_DIRTY;
+               }
                mp = np;
-               mp->mp_pgno = pgno;
-               mp->mp_flags |= P_DIRTY;
 
 finish:
                /* Adjust other cursors pointing to mp */