diff options
author | Howard Chu <hyc@symas.com> | 2017-08-12 12:21:25 +0100 |
---|---|---|
committer | Howard Chu <hyc@symas.com> | 2017-08-12 12:21:25 +0100 |
commit | 9c6eb75c656363176a55c63c81803feb3cfa614d (patch) | |
tree | b46956d659a9047b4d0730081fff4ca3cd6c3ca8 /external/db_drivers/liblmdb/mdb.c | |
parent | Merge pull request #2263 (diff) | |
download | monero-9c6eb75c656363176a55c63c81803feb3cfa614d.tar.xz |
ITS#8704 add MDB_PREVSNAPSHOT flag to mdb_env_open
used to open the previous snapshot, in case the latest one
is corrupted
Diffstat (limited to 'external/db_drivers/liblmdb/mdb.c')
-rw-r--r-- | external/db_drivers/liblmdb/mdb.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/external/db_drivers/liblmdb/mdb.c b/external/db_drivers/liblmdb/mdb.c index 3552bd2a9..377512ebe 100644 --- a/external/db_drivers/liblmdb/mdb.c +++ b/external/db_drivers/liblmdb/mdb.c @@ -1468,7 +1468,7 @@ 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); -static int mdb_env_read_header(MDB_env *env, MDB_meta *meta); +static int mdb_env_read_header(MDB_env *env, int prev, MDB_meta *meta); static MDB_meta *mdb_env_pick_meta(const MDB_env *env); static int mdb_env_write_meta(MDB_txn *txn); #ifdef MDB_USE_POSIX_MUTEX /* Drop unused excl arg */ @@ -3632,6 +3632,8 @@ done: return MDB_SUCCESS; } +static int ESECT mdb_env_share_locks(MDB_env *env, int *excl); + int mdb_txn_commit(MDB_txn *txn) { @@ -3854,6 +3856,15 @@ mdb_txn_commit(MDB_txn *txn) if ((rc = mdb_env_write_meta(txn))) goto fail; end_mode = MDB_END_COMMITTED|MDB_END_UPDATE; + if (env->me_flags & MDB_PREVSNAPSHOT) { + if (!(env->me_flags & MDB_NOLOCK)) { + int excl; + rc = mdb_env_share_locks(env, &excl); + if (rc) + goto fail; + } + env->me_flags ^= MDB_PREVSNAPSHOT; + } done: mdb_txn_end(txn, end_mode); @@ -3867,11 +3878,12 @@ fail: /** Read the environment parameters of a DB environment before * mapping it into memory. * @param[in] env the environment handle + * @param[in] prev whether to read the backup meta page * @param[out] meta address of where to store the meta information * @return 0 on success, non-zero on failure. */ static int ESECT -mdb_env_read_header(MDB_env *env, MDB_meta *meta) +mdb_env_read_header(MDB_env *env, int prev, MDB_meta *meta) { MDB_metabuf pbuf; MDB_page *p; @@ -3922,7 +3934,7 @@ mdb_env_read_header(MDB_env *env, MDB_meta *meta) return MDB_VERSION_MISMATCH; } - if (off == 0 || m->mm_txnid > meta->mm_txnid) + if (off == 0 || (prev ? m->mm_txnid < meta->mm_txnid : m->mm_txnid > meta->mm_txnid)) *meta = *m; } return 0; @@ -4131,7 +4143,8 @@ static MDB_meta * mdb_env_pick_meta(const MDB_env *env) { MDB_meta *const *metas = env->me_metas; - return metas[ metas[0]->mm_txnid < metas[1]->mm_txnid ]; + return metas[ (metas[0]->mm_txnid < metas[1]->mm_txnid) ^ + ((env->me_flags & MDB_PREVSNAPSHOT) != 0) ]; } int ESECT @@ -4366,7 +4379,7 @@ mdb_fsize(HANDLE fd, mdb_size_t *size) /** Further setup required for opening an LMDB environment */ static int ESECT -mdb_env_open2(MDB_env *env) +mdb_env_open2(MDB_env *env, int prev) { unsigned int flags = env->me_flags; int i, newenv = 0, rc; @@ -4429,7 +4442,7 @@ mdb_env_open2(MDB_env *env) } #endif - if ((i = mdb_env_read_header(env, &meta)) != 0) { + if ((i = mdb_env_read_header(env, prev, &meta)) != 0) { if (i != ENOENT) return i; DPUTS("new mdbenv"); @@ -4505,6 +4518,9 @@ mdb_env_open2(MDB_env *env) #endif env->me_maxpg = env->me_mapsize / env->me_psize; + if (env->me_txns) + env->me_txns->mti_txnid = meta.mm_txnid; + #if MDB_DEBUG { MDB_meta *meta = mdb_env_pick_meta(env); @@ -4600,9 +4616,6 @@ static int ESECT mdb_env_share_locks(MDB_env *env, int *excl) { int rc = 0; - MDB_meta *meta = mdb_env_pick_meta(env); - - env->me_txns->mti_txnid = meta->mm_txnid; #ifdef _WIN32 { @@ -5056,7 +5069,7 @@ fail: */ #define CHANGEABLE (MDB_NOSYNC|MDB_NOMETASYNC|MDB_MAPASYNC|MDB_NOMEMINIT) #define CHANGELESS (MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY| \ - MDB_WRITEMAP|MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD) + MDB_WRITEMAP|MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD|MDB_PREVSNAPSHOT) #if VALID_FLAGS & PERSISTENT_FLAGS & (CHANGEABLE|CHANGELESS) # error "Persistent DB flags & env flags overlap, but both go in mm_flags" @@ -5178,9 +5191,13 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode rc = mdb_env_setup_locks(env, lpath, mode, &excl); if (rc) goto leave; + if ((flags & MDB_PREVSNAPSHOT) && !excl) { + rc = EAGAIN; + goto leave; + } } - if ((rc = mdb_env_open2(env)) == MDB_SUCCESS) { + if ((rc = mdb_env_open2(env, flags & MDB_PREVSNAPSHOT)) == MDB_SUCCESS) { if (flags & (MDB_RDONLY|MDB_WRITEMAP)) { env->me_mfd = env->me_fd; } else { @@ -5206,7 +5223,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode } } DPRINTF(("opened dbenv %p", (void *) env)); - if (excl > 0) { + if (excl > 0 && !(flags & MDB_PREVSNAPSHOT)) { rc = mdb_env_share_locks(env, &excl); if (rc) goto leave; |