]> git.sur5r.net Git - openldap/commitdiff
Return fresh overflow pages to current pghead
authorHoward Chu <hyc@symas.com>
Sun, 5 May 2013 08:28:12 +0000 (01:28 -0700)
committerHoward Chu <hyc@symas.com>
Thu, 6 Jun 2013 23:44:02 +0000 (16:44 -0700)
And remove them from the current dirty list.

libraries/liblmdb/mdb.c

index 0be43fecc2c494928cbe94f9c45426d5d2f25a29..9e01fb5e07eaa12d1e53e726d6ad9010a6c009a1 100644 (file)
@@ -1404,7 +1404,7 @@ again:
                                        txn->mt_env->me_pglast = last;
                                        goto again;
                                }
-                               mop = malloc(MDB_IDL_SIZEOF(idl));
+                               mop = mdb_midl_alloc(idl[0]);
                                if (!mop)
                                        return ENOMEM;
                                txn->mt_env->me_pglast = last;
@@ -1474,7 +1474,7 @@ none:
                                                if (oldest <= last)
                                                        break;
                                                idl = (MDB_ID *) data.mv_data;
-                                               mop2 = malloc(MDB_IDL_SIZEOF(idl) + MDB_IDL_SIZEOF(mop));
+                                               mop2 = mdb_midl_alloc(idl[0] + mop[0]);
                                                if (!mop2)
                                                        return ENOMEM;
                                                /* merge in sorted order */
@@ -1487,7 +1487,7 @@ none:
                                                                mop2[k--] = mop[j--];
                                                }
                                                txn->mt_env->me_pglast = last;
-                                               free(txn->mt_env->me_pgfree);
+                                               mdb_midl_free(txn->mt_env->me_pgfree);
                                                txn->mt_env->me_pghead = txn->mt_env->me_pgfree = mop2;
                                                mop = mop2;
                                                /* Keep trying to read until we have enough */
@@ -1521,7 +1521,7 @@ none:
                                mop[0]--;
                        }
                        if (MDB_IDL_IS_ZERO(mop)) {
-                               free(txn->mt_env->me_pgfree);
+                               mdb_midl_free(txn->mt_env->me_pgfree);
                                txn->mt_env->me_pghead = txn->mt_env->me_pgfree = NULL;
                        }
                }
@@ -1990,7 +1990,7 @@ mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)
                ntxn->mnt_pgstate = env->me_pgstate; /* save parent me_pghead & co */
                if (env->me_pghead) {
                        size = MDB_IDL_SIZEOF(env->me_pghead);
-                       env->me_pghead = malloc(size);
+                       env->me_pghead = mdb_midl_alloc(env->me_pghead[0]);
                        if (env->me_pghead)
                                memcpy(env->me_pghead, ntxn->mnt_pgstate.mf_pghead, size);
                        else
@@ -2068,7 +2068,7 @@ mdb_txn_reset0(MDB_txn *txn)
                if (!(env->me_flags & MDB_WRITEMAP)) {
                        mdb_dlist_free(txn);
                }
-               free(env->me_pgfree);
+               mdb_midl_free(env->me_pgfree);
 
                if (txn->mt_parent) {
                        txn->mt_parent->mt_child = NULL;
@@ -2403,7 +2403,7 @@ free2:
        if (freecnt != txn->mt_free_pgs[0])
                goto free2;
 
-       free(env->me_pgfree);
+       mdb_midl_free(env->me_pgfree);
        env->me_pghead = env->me_pgfree = NULL;
 
        if (!MDB_IDL_IS_ZERO(txn->mt_free_pgs)) {
@@ -4266,6 +4266,53 @@ mdb_page_search(MDB_cursor *mc, MDB_val *key, int flags)
        return mdb_page_search_root(mc, key, flags);
 }
 
+static int
+mdb_ovpage_free(MDB_cursor *mc, MDB_page *mp)
+{
+       pgno_t pg = mp->mp_pgno;
+       unsigned i, ovpages = mp->mp_pages;
+       int rc;
+
+       DPRINTF("free ov page %zu (%d)", pg, ovpages);
+       mc->mc_db->md_overflow_pages -= ovpages;
+       /* If the page is dirty we just acquired it, so we should
+        * give it back to our current free list, if any.
+        * Otherwise put it onto the list of pages we freed in this txn.
+        */
+       if ((mp->mp_flags & P_DIRTY) && mc->mc_txn->mt_env->me_pghead) {
+               unsigned j, x;
+               pgno_t *mop = mc->mc_txn->mt_env->me_pghead;
+               /* Remove from dirty list */
+               x = mdb_mid2l_search(mc->mc_txn->mt_u.dirty_list, pg);
+               for (; x < mc->mc_txn->mt_u.dirty_list[0].mid; x++)
+                       mc->mc_txn->mt_u.dirty_list[x] = mc->mc_txn->mt_u.dirty_list[x+1];
+               mc->mc_txn->mt_u.dirty_list[0].mid--;
+               /* Make room to insert pg */
+               j = mop[0] + ovpages;
+               if (j > mop[-1]) {
+                       rc = mdb_midl_grow(&mop, ovpages);
+                       if (rc)
+                               return rc;
+                       mc->mc_txn->mt_env->me_pghead = mc->mc_txn->mt_env->me_pgfree = mop;
+               }
+               for (i = mop[0]; i>0; i--) {
+                       if (mop[i] < pg)
+                               mop[j--] = mop[i];
+                       else
+                               break;
+               }
+               while (j>i)
+                       mop[j--] = pg++;
+               mop[0] += ovpages;
+       } else {
+               for (i=0; i<ovpages; i++) {
+                       mdb_midl_append(&mc->mc_txn->mt_free_pgs, pg);
+                       pg++;
+               }
+       }
+       return 0;
+}
+
 /** Return the data associated with a given node.
  * @param[in] txn The transaction for this operation.
  * @param[in] leaf The node being read.
@@ -5244,14 +5291,7 @@ current:
                                        memcpy(METADATA(omp), data->mv_data, data->mv_size);
                                goto done;
                        } else {
-                               /* no, free ovpages */
-                               int i;
-                               mc->mc_db->md_overflow_pages -= ovpages;
-                               for (i=0; i<ovpages; i++) {
-                                       DPRINTF("freed ov page %zu", pg);
-                                       mdb_midl_append(&mc->mc_txn->mt_free_pgs, pg);
-                                       pg++;
-                               }
+                               mdb_ovpage_free(mc, omp);
                        }
                } else if (NODEDSZ(leaf) == data->mv_size) {
                        /* same size, just replace it. Note that we could
@@ -6559,7 +6599,6 @@ mdb_cursor_del0(MDB_cursor *mc, MDB_node *leaf)
 
        /* add overflow pages to free list */
        if (!IS_LEAF2(mc->mc_pg[mc->mc_top]) && F_ISSET(leaf->mn_flags, F_BIGDATA)) {
-               int i, ovpages;
                MDB_page *omp;
                pgno_t pg;
 
@@ -6567,13 +6606,7 @@ mdb_cursor_del0(MDB_cursor *mc, MDB_node *leaf)
                if ((rc = mdb_page_get(mc->mc_txn, pg, &omp, NULL)) != 0)
                        return rc;
                assert(IS_OVERFLOW(omp));
-               ovpages = omp->mp_pages;
-               mc->mc_db->md_overflow_pages -= ovpages;
-               for (i=0; i<ovpages; i++) {
-                       DPRINTF("freed ov page %zu", pg);
-                       mdb_midl_append(&mc->mc_txn->mt_free_pgs, pg);
-                       pg++;
-               }
+               mdb_ovpage_free(mc, omp);
        }
        mdb_node_del(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], mc->mc_db->md_pad);
        mc->mc_db->md_entries--;