From e26fc734177ccc4da91d6bf79035a9dda354784a Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 7 Dec 2012 13:19:36 -0800 Subject: [PATCH 1/3] ITS#7467 add verbose freelist info --- libraries/liblmdb/mdb_stat.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/libraries/liblmdb/mdb_stat.c b/libraries/liblmdb/mdb_stat.c index e9981f6016..13a24f9cbd 100644 --- a/libraries/liblmdb/mdb_stat.c +++ b/libraries/liblmdb/mdb_stat.c @@ -31,7 +31,7 @@ static void prstat(MDB_stat *ms) static void usage(char *prog) { - fprintf(stderr, "usage: %s dbpath [-e] [-f] [-n] [-a|-s subdb]\n", prog); + fprintf(stderr, "usage: %s dbpath [-e] [-f[f]] [-n] [-a|-s subdb]\n", prog); exit(EXIT_FAILURE); } @@ -122,7 +122,7 @@ int main(int argc, char *argv[]) if (freinfo) { MDB_cursor *cursor; - MDB_val data; + MDB_val key, data; size_t pages = 0, *iptr; printf("Freelist Status\n"); @@ -137,12 +137,20 @@ int main(int argc, char *argv[]) printf("mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } - while ((rc = mdb_cursor_get(cursor, NULL, &data, MDB_NEXT)) == 0) { + prstat(&mst); + while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { iptr = data.mv_data; pages += *iptr; + if (freinfo > 1) { + size_t i, j; + j = *iptr++; + printf(" Transaction %zu, %zu pages\n", + *(size_t *)key.mv_data, j); + for (i=0; i Date: Mon, 10 Dec 2012 12:16:50 -0800 Subject: [PATCH 2/3] ITS#7455 simplify Don't try to reclaim overflow pages while operating on the freelist (for now). The circular dependencies are much like the single-page case, but worse. Maybe look into this in the future, but it's not absolutely necessary now. --- libraries/liblmdb/mdb.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 81470d9fe7..7f6af70721 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -1347,6 +1347,11 @@ none: mdb_cursor_init(&m2, txn, FREE_DBI, NULL); do { + /* bail out if we're operating on the freelist. + * TODO: get all of this working. Many circular dependencies... + */ + if (mc->mc_dbi == FREE_DBI) + break; if (readit) { MDB_val key, data; MDB_oldpages *mop2; From 0ce6bb4be0034120c850917bc4f59b4d4efc1432 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Mon, 10 Dec 2012 12:21:36 -0800 Subject: [PATCH 3/3] Add error checks to txn_commit These ops could fail if the map is full. --- libraries/liblmdb/mdb.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 7f6af70721..f147588b48 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -2126,7 +2126,12 @@ mdb_txn_commit(MDB_txn *txn) /* should only be one record now */ if (env->me_pghead) { /* make sure first page of freeDB is touched and on freelist */ - mdb_page_search(&mc, NULL, MDB_PS_MODIFY); + rc = mdb_page_search(&mc, NULL, MDB_PS_MODIFY); + if (rc) { +fail: + mdb_txn_abort(txn); + return rc; + } } /* Delete IDLs we used from the free list */ @@ -2141,10 +2146,8 @@ mdb_txn_commit(MDB_txn *txn) mdb_cursor_set(&mc, &key, NULL, MDB_SET, &exact); rc = mdb_cursor_del(&mc, 0); - if (rc) { - mdb_txn_abort(txn); - return rc; - } + if (rc) + goto fail; } env->me_pgfirst = 0; env->me_pglast = 0; @@ -2159,7 +2162,9 @@ free2: /* make sure last page of freeDB is touched and on freelist */ key.mv_size = MAXKEYSIZE+1; key.mv_data = NULL; - mdb_page_search(&mc, &key, MDB_PS_MODIFY); + rc = mdb_page_search(&mc, &key, MDB_PS_MODIFY); + if (rc) + goto fail; #if MDB_DEBUG > 1 { @@ -2186,10 +2191,8 @@ free2: data.mv_size = MDB_IDL_SIZEOF(txn->mt_free_pgs); mdb_midl_sort(txn->mt_free_pgs); rc = mdb_cursor_put(&mc, &key, &data, 0); - if (rc) { - mdb_txn_abort(txn); - return rc; - } + if (rc) + goto fail; } while (freecnt != txn->mt_free_pgs[0]); } /* should only be one record now */ @@ -2210,18 +2213,24 @@ again: /* These steps may grow the freelist again * due to freed overflow pages... */ - mdb_cursor_put(&mc, &key, &data, 0); + rc = mdb_cursor_put(&mc, &key, &data, 0); + if (rc) + goto fail; if (mop == env->me_pghead && env->me_pghead->mo_txnid == id) { /* could have been used again here */ if (mop->mo_pages[0] != orig) { data.mv_size = MDB_IDL_SIZEOF(mop->mo_pages); data.mv_data = mop->mo_pages; id = mop->mo_txnid; - mdb_cursor_put(&mc, &key, &data, 0); + rc = mdb_cursor_put(&mc, &key, &data, 0); + if (rc) + goto fail; } } else { /* was completely used up */ - mdb_cursor_del(&mc, 0); + rc = mdb_cursor_del(&mc, 0); + if (rc) + goto fail; if (env->me_pghead) goto again; }