Another take on spill_pgs and deletes

vmware
Howard Chu 11 years ago
parent b917266ca1
commit 56c2a8d04a
  1. 47
      libraries/liblmdb/mdb.c

@ -847,7 +847,8 @@ struct MDB_txn {
*/ */
MDB_IDL mt_free_pgs; MDB_IDL mt_free_pgs;
/** The sorted list of dirty pages we temporarily wrote to disk /** The sorted list of dirty pages we temporarily wrote to disk
* because the dirty list was full. * because the dirty list was full. page numbers in here are
* shifted left by 1, deleted slots have the LSB set.
*/ */
MDB_IDL mt_spill_pgs; MDB_IDL mt_spill_pgs;
union { union {
@ -1476,12 +1477,12 @@ mdb_page_spill(MDB_cursor *m0, MDB_val *key, MDB_val *data)
if (!txn->mt_spill_pgs) if (!txn->mt_spill_pgs)
return ENOMEM; return ENOMEM;
} else { } else {
/* strip any dups */ /* purge deleted slots */
MDB_IDL sl = txn->mt_spill_pgs; MDB_IDL sl = txn->mt_spill_pgs;
unsigned int num = sl[0]; unsigned int num = sl[0];
j=1; j=0;
for (i=1; i<=num; i++) { for (i=1; i<=num; i++) {
if (sl[j] != sl[i]) if (!(sl[i] & 1))
sl[++j] = sl[i]; sl[++j] = sl[i];
} }
sl[0] = j; sl[0] = j;
@ -1504,6 +1505,7 @@ mdb_page_spill(MDB_cursor *m0, MDB_val *key, MDB_val *data)
/* Save the page IDs of all the pages we're flushing */ /* Save the page IDs of all the pages we're flushing */
/* flush from the tail forward, this saves a lot of shifting later on. */ /* flush from the tail forward, this saves a lot of shifting later on. */
for (i=dl[0].mid; i && need; i--) { for (i=dl[0].mid; i && need; i--) {
MDB_ID pn = dl[i].mid << 1;
dp = dl[i].mptr; dp = dl[i].mptr;
if (dp->mp_flags & P_KEEP) if (dp->mp_flags & P_KEEP)
continue; continue;
@ -1514,8 +1516,8 @@ mdb_page_spill(MDB_cursor *m0, MDB_val *key, MDB_val *data)
MDB_txn *tx2; MDB_txn *tx2;
for (tx2 = txn->mt_parent; tx2; tx2 = tx2->mt_parent) { for (tx2 = txn->mt_parent; tx2; tx2 = tx2->mt_parent) {
if (tx2->mt_spill_pgs) { if (tx2->mt_spill_pgs) {
j = mdb_midl_search(tx2->mt_spill_pgs, dl[i].mid); j = mdb_midl_search(tx2->mt_spill_pgs, pn);
if (j <= tx2->mt_spill_pgs[0] && tx2->mt_spill_pgs[j] == dl[i].mid) { if (j <= tx2->mt_spill_pgs[0] && tx2->mt_spill_pgs[j] == pn) {
dp->mp_flags |= P_KEEP; dp->mp_flags |= P_KEEP;
break; break;
} }
@ -1524,7 +1526,7 @@ mdb_page_spill(MDB_cursor *m0, MDB_val *key, MDB_val *data)
if (tx2) if (tx2)
continue; continue;
} }
if ((rc = mdb_midl_append(&txn->mt_spill_pgs, dl[i].mid))) if ((rc = mdb_midl_append(&txn->mt_spill_pgs, pn)))
goto done; goto done;
need--; need--;
} }
@ -1798,13 +1800,13 @@ mdb_page_unspill(MDB_txn *tx0, MDB_page *mp, MDB_page **ret)
MDB_env *env = tx0->mt_env; MDB_env *env = tx0->mt_env;
MDB_txn *txn; MDB_txn *txn;
unsigned x; unsigned x;
pgno_t pgno = mp->mp_pgno; pgno_t pgno = mp->mp_pgno, pn = pgno << 1;
for (txn = tx0; txn; txn=txn->mt_parent) { for (txn = tx0; txn; txn=txn->mt_parent) {
if (!txn->mt_spill_pgs) if (!txn->mt_spill_pgs)
continue; continue;
x = mdb_midl_search(txn->mt_spill_pgs, pgno); x = mdb_midl_search(txn->mt_spill_pgs, pn);
if (x <= txn->mt_spill_pgs[0] && txn->mt_spill_pgs[x] == pgno) { if (x <= txn->mt_spill_pgs[0] && txn->mt_spill_pgs[x] == pn) {
MDB_page *np; MDB_page *np;
int num; int num;
if (IS_OVERFLOW(mp)) if (IS_OVERFLOW(mp))
@ -1825,13 +1827,12 @@ mdb_page_unspill(MDB_txn *tx0, MDB_page *mp, MDB_page **ret)
if (txn == tx0) { if (txn == tx0) {
/* If in current txn, this page is no longer spilled. /* If in current txn, this page is no longer spilled.
* If it happens to be the last page, truncate the spill list. * If it happens to be the last page, truncate the spill list.
* Otherwise temporarily dup its neighbor over it. Dups will * Otherwise mark it as deleted by setting the LSB.
* be stripped out later by the next mdb_page_spill run.
*/ */
if (x == txn->mt_spill_pgs[0]) if (x == txn->mt_spill_pgs[0])
txn->mt_spill_pgs[0]--; txn->mt_spill_pgs[0]--;
else else
txn->mt_spill_pgs[x] = txn->mt_spill_pgs[x+1]; txn->mt_spill_pgs[x] |= 1;
} /* otherwise, if belonging to a parent txn, the } /* otherwise, if belonging to a parent txn, the
* page remains spilled until child commits * page remains spilled until child commits
*/ */
@ -2823,9 +2824,10 @@ mdb_txn_commit(MDB_txn *txn)
len = x; len = x;
/* zero out our dirty pages in parent spill list */ /* zero out our dirty pages in parent spill list */
for (i=1; i<=src[0].mid; i++) { for (i=1; i<=src[0].mid; i++) {
if (src[i].mid < parent->mt_spill_pgs[x]) MDB_ID pn = src[i].mid << 1;
if (pn < parent->mt_spill_pgs[x])
continue; continue;
if (src[i].mid > parent->mt_spill_pgs[x]) { if (pn > parent->mt_spill_pgs[x]) {
if (x <= 1) if (x <= 1)
break; break;
x--; x--;
@ -4533,8 +4535,9 @@ mdb_page_get(MDB_txn *txn, pgno_t pgno, MDB_page **ret, int *lvl)
* leave that unless page_touch happens again). * leave that unless page_touch happens again).
*/ */
if (tx2->mt_spill_pgs) { if (tx2->mt_spill_pgs) {
x = mdb_midl_search(tx2->mt_spill_pgs, pgno); MDB_ID pn = pgno << 1;
if (x <= tx2->mt_spill_pgs[0] && tx2->mt_spill_pgs[x] == pgno) { x = mdb_midl_search(tx2->mt_spill_pgs, pn);
if (x <= tx2->mt_spill_pgs[0] && tx2->mt_spill_pgs[x] == pn) {
p = (MDB_page *)(env->me_map + env->me_psize * pgno); p = (MDB_page *)(env->me_map + env->me_psize * pgno);
goto done; goto done;
} }
@ -4764,6 +4767,7 @@ mdb_ovpage_free(MDB_cursor *mc, MDB_page *mp)
unsigned x = 0, ovpages = mp->mp_pages; unsigned x = 0, ovpages = mp->mp_pages;
MDB_env *env = txn->mt_env; MDB_env *env = txn->mt_env;
MDB_IDL sl = txn->mt_spill_pgs; MDB_IDL sl = txn->mt_spill_pgs;
MDB_ID pn = pg << 1;
int rc; int rc;
DPRINTF(("free ov page %"Z"u (%d)", pg, ovpages)); DPRINTF(("free ov page %"Z"u (%d)", pg, ovpages));
@ -4778,7 +4782,7 @@ mdb_ovpage_free(MDB_cursor *mc, MDB_page *mp)
if (env->me_pghead && if (env->me_pghead &&
!txn->mt_parent && !txn->mt_parent &&
((mp->mp_flags & P_DIRTY) || ((mp->mp_flags & P_DIRTY) ||
(sl && (x = mdb_midl_search(sl, pg)) <= sl[0] && sl[x] == pg))) (sl && (x = mdb_midl_search(sl, pn)) <= sl[0] && sl[x] == pn)))
{ {
unsigned i, j; unsigned i, j;
pgno_t *mop; pgno_t *mop;
@ -4788,9 +4792,10 @@ mdb_ovpage_free(MDB_cursor *mc, MDB_page *mp)
return rc; return rc;
if (!(mp->mp_flags & P_DIRTY)) { if (!(mp->mp_flags & P_DIRTY)) {
/* This page is no longer spilled */ /* This page is no longer spilled */
for (; x < sl[0]; x++) if (x == sl[0])
sl[x] = sl[x+1]; sl[0]--;
sl[0]--; else
sl[x] |= 1;
goto release; goto release;
} }
/* Remove from dirty list */ /* Remove from dirty list */

Loading…
Cancel
Save