ITS#7455 Save freelist in single-page chunks

vmware
Hallvard Furuseth 12 years ago committed by Howard Chu
parent 1b8bfc5756
commit 52ecd38e18
  1. 30
      libraries/liblmdb/mdb.c

@ -2022,7 +2022,7 @@ mdb_txn_commit(MDB_txn *txn)
off_t size;
MDB_page *dp;
MDB_env *env;
pgno_t next, freecnt;
pgno_t next, freecnt, maxfree_1pg;
txnid_t oldpg_txnid, id;
MDB_cursor mc;
@ -2138,7 +2138,8 @@ mdb_txn_commit(MDB_txn *txn)
/* Save the freelist as of this transaction to the freeDB. This
* can change the freelist, so keep trying until it stabilizes.
*
* env->me_pglast and the length of txn->mt_free_pgs cannot decrease.
* env->me_pglast and the length of txn->mt_free_pgs cannot decrease,
* except the code below can decrease env->me_pglast to split pghead.
* Page numbers cannot disappear from txn->mt_free_pgs. New pages
* can only appear in env->me_pghead when env->me_pglast increases.
* Until then, the me_pghead pointer won't move but can become NULL.
@ -2147,6 +2148,12 @@ mdb_txn_commit(MDB_txn *txn)
mdb_cursor_init(&mc, txn, FREE_DBI, NULL);
oldpg_txnid = id = 0;
freecnt = 0;
/* Preferred max #items per freelist entry, to avoid overflow pages.
* Leave room for headers, key (txnid), pagecount (pageno_t), and
* FIXME: a bit more in case there is some delimiter I don't know about.
*/
maxfree_1pg = (env->me_psize - (PAGEHDRSZ + NODESIZE + 3*sizeof(MDB_ID)))
/ sizeof(pgno_t);
/* should only be one record now */
if (env->me_pghead || env->me_pglast) {
@ -2225,6 +2232,7 @@ free2:
/* Put back page numbers we took from freeDB but did not use */
if (env->me_pghead) {
for (;;) {
MDB_val key, data;
pgno_t orig, *mop;
@ -2238,7 +2246,9 @@ free2:
i = 2;
do {
orig = mop[0];
data.mv_size = MDB_IDL_SIZEOF(mop);
if (orig > maxfree_1pg && id > 4)
orig = maxfree_1pg; /* Do not use an overflow page */
data.mv_size = (orig + 1) * sizeof(pgno_t);
rc = mdb_cursor_put(&mc, &key, &data, MDB_RESERVE);
if (rc)
goto fail;
@ -2246,9 +2256,19 @@ free2:
/* mop could have been used again here */
if (id != env->me_pglast || env->me_pghead == NULL)
goto again; /* was completely used up */
assert(mop == env->me_pghead && mop[0] <= orig);
} while (mop[0] != orig && --i);
assert(mop == env->me_pghead);
} while (mop[0] < orig && --i);
memcpy(data.mv_data, mop, data.mv_size);
if (mop[0] <= orig)
break;
*(pgno_t *)data.mv_data = orig;
mop[0] -= orig;
memmove(&mop[1], &mop[1 + orig],
mop[0] * sizeof(pgno_t));
/* Save more oldpages at the previous txnid. */
assert(env->me_pglast == id && id == oldpg_txnid);
env->me_pglast = --oldpg_txnid;
}
}
/* Check for growth of freelist again */

Loading…
Cancel
Save