]> git.sur5r.net Git - openldap/commitdiff
Clean up mdb_page_touch(), mdb_page_copy().
authorHallvard Furuseth <hallvard@openldap.org>
Thu, 13 Jun 2013 06:58:24 +0000 (08:58 +0200)
committerHallvard Furuseth <hallvard@openldap.org>
Thu, 13 Jun 2013 06:58:24 +0000 (08:58 +0200)
When copying, round up/down to aligned sizes. Skip the unused portion,
this was not done when touching a page dirty in the parent txn.
No other change in behavior.

Simplify mdb_page_touch(), including: Drop test m3==mc, the condition
is caught below. Don't "modify" the parent's pgno into the same pgno,
when a nested txn copies a parent's page into its freelist.

libraries/liblmdb/mdb.c

index e1093f6467a85755d61462e9bea883e38b67a35d..97926d9e145b5930f4fdbcc25ef887cb927fe73e 100644 (file)
@@ -1563,7 +1563,7 @@ none:
        return MDB_SUCCESS;
 }
 
-/** Copy a page: avoid copying unused portions of the page.
+/** Copy the used portions of a non-overflow page.
  * @param[in] dst page to copy into
  * @param[in] src page to copy from
  * @param[in] psize size of a page
@@ -1571,17 +1571,19 @@ none:
 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;
+       enum { Align = sizeof(pgno_t) };
+       indx_t upper = src->mp_upper, lower = src->mp_lower, unused = upper-lower;
 
-       if (IS_LEAF2(src)) {
-               memcpy(dst->mp_ptrs, src->mp_ptrs, psize - PAGEHDRSZ - SIZELEFT(src));
+       /* If page isn't full, just copy the used portion. Adjust
+        * alignment so memcpy may copy words instead of bytes.
+        */
+       if ((unused &= -Align) && !IS_LEAF2(src)) {
+               upper &= -Align;
+               memcpy(dst, src, (lower + (Align-1)) & -Align);
+               memcpy((pgno_t *)((char *)dst+upper), (pgno_t *)((char *)src+upper),
+                       psize - upper);
        } 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);
+               memcpy(dst, src, psize - unused);
        }
 }
 
@@ -1592,76 +1594,36 @@ mdb_page_copy(MDB_page *dst, MDB_page *src, unsigned int psize)
 static int
 mdb_page_touch(MDB_cursor *mc)
 {
-       MDB_page *mp = mc->mc_pg[mc->mc_top];
+       MDB_page *mp = mc->mc_pg[mc->mc_top], *np;
+       MDB_cursor *m2, *m3;
+       MDB_dbi dbi;
        pgno_t  pgno;
        int rc;
 
        if (!F_ISSET(mp->mp_flags, P_DIRTY)) {
-               MDB_page *np;
                if ((rc = mdb_page_alloc(mc, 1, &np)))
                        return rc;
-               DPRINTF("touched db %u page %zu -> %zu", mc->mc_dbi, mp->mp_pgno, np->mp_pgno);
-               assert(mp->mp_pgno != np->mp_pgno);
+               pgno = np->mp_pgno;
+               DPRINTF("touched db %u page %zu -> %zu", mc->mc_dbi,mp->mp_pgno,pgno);
+               assert(mp->mp_pgno != pgno);
                mdb_midl_append(&mc->mc_txn->mt_free_pgs, mp->mp_pgno);
-               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;
-
-finish:
-               /* Adjust other cursors pointing to mp */
-               if (mc->mc_flags & C_SUB) {
-                       MDB_cursor *m2, *m3;
-                       MDB_dbi dbi = mc->mc_dbi-1;
-
-                       for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
-                               m3 = &m2->mc_xcursor->mx_cursor;
-                               if (m3 == mc) continue;
-                               if (m3->mc_snum < mc->mc_snum) continue;
-                               if (m3->mc_pg[mc->mc_top] == mc->mc_pg[mc->mc_top]) {
-                                       m3->mc_pg[mc->mc_top] = mp;
-                               }
-                       }
+               /* Update the parent page, if any, to point to the new page */
+               if (mc->mc_top) {
+                       MDB_page *parent = mc->mc_pg[mc->mc_top-1];
+                       MDB_node *node = NODEPTR(parent, mc->mc_ki[mc->mc_top-1]);
+                       SETPGNO(node, pgno);
                } else {
-                       MDB_cursor *m2;
-
-                       for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2=m2->mc_next) {
-                               if (m2 == mc || m2->mc_snum < mc->mc_snum) continue;
-                               if (m2->mc_pg[mc->mc_top] == mc->mc_pg[mc->mc_top]) {
-                                       m2->mc_pg[mc->mc_top] = mp;
-                                       if ((mc->mc_db->md_flags & MDB_DUPSORT) &&
-                                               m2->mc_ki[mc->mc_top] == mc->mc_ki[mc->mc_top]) {
-                                               MDB_node *leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
-                                               if (!(leaf->mn_flags & F_SUBDATA)) {
-                                                       m2->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf);
-                                               }
-                                       }
-                               }
-                       }
+                       mc->mc_db->md_root = pgno;
                }
-               mc->mc_pg[mc->mc_top] = mp;
-               /** If this page has a parent, update the parent to point to
-                * this new page.
-                */
-               if (mc->mc_top)
-                       SETPGNO(NODEPTR(mc->mc_pg[mc->mc_top-1], mc->mc_ki[mc->mc_top-1]), mp->mp_pgno);
-               else
-                       mc->mc_db->md_root = mp->mp_pgno;
        } else if (mc->mc_txn->mt_parent && !(mp->mp_flags & P_SUBP)) {
-               MDB_page *np;
                MDB_ID2 mid, *dl = mc->mc_txn->mt_u.dirty_list;
+               pgno = mp->mp_pgno;
                /* If txn has a parent, make sure the page is in our
                 * dirty list.
                 */
                if (dl[0].mid) {
-                       unsigned x = mdb_mid2l_search(dl, mp->mp_pgno);
-                       if (x <= dl[0].mid && dl[x].mid == mp->mp_pgno) {
+                       unsigned x = mdb_mid2l_search(dl, pgno);
+                       if (x <= dl[0].mid && dl[x].mid == pgno) {
                                np = dl[x].mptr;
                                if (mp != np)
                                        mc->mc_pg[mc->mc_top] = np;
@@ -1673,12 +1635,42 @@ finish:
                np = mdb_page_malloc(mc, 1);
                if (!np)
                        return ENOMEM;
-               memcpy(np, mp, mc->mc_txn->mt_env->me_psize);
-               mid.mid = np->mp_pgno;
+               mid.mid = pgno;
                mid.mptr = np;
                mdb_mid2l_insert(dl, &mid);
-               mp = np;
-               goto finish;
+       } else {
+               return 0;
+       }
+
+       mdb_page_copy(np, mp, mc->mc_txn->mt_env->me_psize);
+       np->mp_pgno = pgno;
+       np->mp_flags |= P_DIRTY;
+
+       /* Adjust cursors pointing to mp */
+       mc->mc_pg[mc->mc_top] = np;
+       dbi = mc->mc_dbi;
+       if (mc->mc_flags & C_SUB) {
+               dbi--;
+               for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
+                       m3 = &m2->mc_xcursor->mx_cursor;
+                       if (m3->mc_snum < mc->mc_snum) continue;
+                       if (m3->mc_pg[mc->mc_top] == mp)
+                               m3->mc_pg[mc->mc_top] = np;
+               }
+       } else {
+               for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
+                       if (m2->mc_snum < mc->mc_snum) continue;
+                       if (m2->mc_pg[mc->mc_top] == mp) {
+                               m2->mc_pg[mc->mc_top] = np;
+                               if ((mc->mc_db->md_flags & MDB_DUPSORT) &&
+                                       m2->mc_ki[mc->mc_top] == mc->mc_ki[mc->mc_top])
+                               {
+                                       MDB_node *leaf = NODEPTR(np, mc->mc_ki[mc->mc_top]);
+                                       if (!(leaf->mn_flags & F_SUBDATA))
+                                               m2->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf);
+                               }
+                       }
+               }
        }
        return 0;
 }