From 7e9a6134fde1e65648aa18c935c1af7554fd5b97 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Tue, 17 Jul 2012 04:02:48 -0700 Subject: [PATCH] Make sure cursor's DB is init'd if STALE. --- libraries/libmdb/mdb.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/libraries/libmdb/mdb.c b/libraries/libmdb/mdb.c index 4de36c6..4588e75 100644 --- a/libraries/libmdb/mdb.c +++ b/libraries/libmdb/mdb.c @@ -932,8 +932,10 @@ static int mdb_page_touch(MDB_cursor *mc); static int mdb_page_get(MDB_txn *txn, pgno_t pgno, MDB_page **mp); static int mdb_page_search_root(MDB_cursor *mc, MDB_val *key, int modify); +#define MDB_PS_MODIFY 1 +#define MDB_PS_ROOTONLY 2 static int mdb_page_search(MDB_cursor *mc, - MDB_val *key, int modify); + MDB_val *key, int flags); static int mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst); static int mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno, unsigned int nflags); @@ -1554,7 +1556,8 @@ mdb_txn_renew0(MDB_txn *txn) memcpy(txn->mt_dbs, env->me_metas[txn->mt_toggle]->mm_dbs, 2 * sizeof(MDB_db)); for (i=2; imt_numdbs; i++) txn->mt_dbs[i].md_flags = env->me_dbflags[i]; - memset(txn->mt_dbflags, DB_STALE, env->me_numdbs); + txn->mt_dbflags[0] = txn->mt_dbflags[1] = 0; + memset(txn->mt_dbflags+2, DB_STALE, env->me_numdbs-2); return MDB_SUCCESS; } @@ -1858,7 +1861,7 @@ 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, 1); + mdb_page_search(&mc, NULL, MDB_PS_MODIFY); } /* Delete IDLs we used from the free list */ @@ -1887,7 +1890,7 @@ 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, 1); + mdb_page_search(&mc, &key, MDB_PS_MODIFY); mdb_midl_sort(txn->mt_free_pgs); #if MDB_DEBUG > 1 @@ -3371,7 +3374,8 @@ mdb_page_get(MDB_txn *txn, pgno_t pgno, MDB_page **ret) * @param[in,out] mc the cursor for this operation. * @param[in] key the key to search for. If NULL, search for the lowest * page. (This is used by #mdb_cursor_first().) - * @param[in] modify If true, visited pages are updated with new page numbers. + * @param[in] flags If MDB_PS_MODIFY set, visited pages are updated with new page numbers. + * If MDB_PS_ROOTONLY set, just fetch root node, no further lookups. * @return 0 on success, non-zero on failure. */ static int @@ -3453,7 +3457,7 @@ mdb_page_search_root(MDB_cursor *mc, MDB_val *key, int modify) * @return 0 on success, non-zero on failure. */ static int -mdb_page_search(MDB_cursor *mc, MDB_val *key, int modify) +mdb_page_search(MDB_cursor *mc, MDB_val *key, int flags) { int rc; pgno_t root; @@ -3468,11 +3472,11 @@ mdb_page_search(MDB_cursor *mc, MDB_val *key, int modify) /* Make sure we're using an up-to-date root */ if (mc->mc_dbi > MAIN_DBI) { if ((*mc->mc_dbflag & DB_STALE) || - (modify && !(*mc->mc_dbflag & DB_DIRTY))) { + ((flags & MDB_PS_MODIFY) && !(*mc->mc_dbflag & DB_DIRTY))) { MDB_cursor mc2; unsigned char dbflag = 0; mdb_cursor_init(&mc2, mc->mc_txn, MAIN_DBI, NULL); - rc = mdb_page_search(&mc2, &mc->mc_dbx->md_name, modify); + rc = mdb_page_search(&mc2, &mc->mc_dbx->md_name, flags & MDB_PS_MODIFY); if (rc) return rc; if (*mc->mc_dbflag & DB_STALE) { @@ -3485,7 +3489,7 @@ mdb_page_search(MDB_cursor *mc, MDB_val *key, int modify) mdb_node_read(mc->mc_txn, leaf, &data); memcpy(mc->mc_db, data.mv_data, sizeof(MDB_db)); } - if (modify) + if (flags & MDB_PS_MODIFY) dbflag = DB_DIRTY; *mc->mc_dbflag = dbflag; } @@ -3508,12 +3512,15 @@ mdb_page_search(MDB_cursor *mc, MDB_val *key, int modify) DPRINTF("db %u root page %zu has flags 0x%X", mc->mc_dbi, root, mc->mc_pg[0]->mp_flags); - if (modify) { + if (flags & MDB_PS_MODIFY) { if ((rc = mdb_page_touch(mc))) return rc; } - return mdb_page_search_root(mc, key, modify); + if (flags & MDB_PS_ROOTONLY) + return MDB_SUCCESS; + + return mdb_page_search_root(mc, key, flags); } /** Return the data associated with a given node. @@ -4149,7 +4156,7 @@ mdb_cursor_touch(MDB_cursor *mc) if (mc->mc_dbi > MAIN_DBI && !(*mc->mc_dbflag & DB_DIRTY)) { MDB_cursor mc2; mdb_cursor_init(&mc2, mc->mc_txn, MAIN_DBI, NULL); - rc = mdb_page_search(&mc2, &mc->mc_dbx->md_name, 1); + rc = mdb_page_search(&mc2, &mc->mc_dbx->md_name, MDB_PS_MODIFY); if (rc) return rc; *mc->mc_dbflag = DB_DIRTY; @@ -4995,6 +5002,9 @@ mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx) } else { mc->mc_xcursor = NULL; } + if (*mc->mc_dbflag & DB_STALE) { + mdb_page_search(mc, NULL, MDB_PS_ROOTONLY); + } } int