ITS#8704 Fix PREVMETA, rename to PREVSNAPSHOT

and enforce exclusive access to environment. Also fix txn_begin/pick_meta
to use correct meta page, and reset the flag after successful commit.
mdb.master3
Howard Chu 7 years ago
parent 16839f9893
commit 3585a1eb97
  1. 12
      libraries/liblmdb/lmdb.h
  2. 32
      libraries/liblmdb/mdb.c
  3. 2
      libraries/liblmdb/mdb_copy.c
  4. 4
      libraries/liblmdb/mdb_dump.c
  5. 4
      libraries/liblmdb/mdb_stat.c

@ -354,8 +354,8 @@ typedef void (MDB_enc_func)(const MDB_val *src, MDB_val *dst, const MDB_val *key
#define MDB_NORDAHEAD 0x800000 #define MDB_NORDAHEAD 0x800000
/** don't initialize malloc'd memory before writing to datafile */ /** don't initialize malloc'd memory before writing to datafile */
#define MDB_NOMEMINIT 0x1000000 #define MDB_NOMEMINIT 0x1000000
/** use the previous meta page rather than the latest one */ /** use the previous snapshot rather than the latest one */
#define MDB_PREVMETA 0x2000000 #define MDB_PREVSNAPSHOT 0x2000000
/** don't use a single mmap, remap individual chunks (needs MDB_RPAGE_CACHE) */ /** don't use a single mmap, remap individual chunks (needs MDB_RPAGE_CACHE) */
#define MDB_REMAP_CHUNKS 0x4000000 #define MDB_REMAP_CHUNKS 0x4000000
/** @} */ /** @} */
@ -672,10 +672,12 @@ int mdb_env_create(MDB_env **env);
* caller is expected to overwrite all of the memory that was * caller is expected to overwrite all of the memory that was
* reserved in that case. * reserved in that case.
* This flag may be changed at any time using #mdb_env_set_flags(). * This flag may be changed at any time using #mdb_env_set_flags().
* <li>#MDB_PREVMETA * <li>#MDB_PREVSNAPSHOT
* Open the environment with the previous meta page rather than the latest * Open the environment with the previous snapshot rather than the latest
* one. This loses the latest transaction, but may help work around some * one. This loses the latest transaction, but may help work around some
* types of corruption. * types of corruption. If opened with write access, this must be the
* only process using the environment. This flag is automatically reset
* after a write transaction is successfully committed.
* </ul> * </ul>
* @param[in] mode The UNIX permissions to set on created files and semaphores. * @param[in] mode The UNIX permissions to set on created files and semaphores.
* This parameter is ignored on Windows. * This parameter is ignored on Windows.

@ -4047,6 +4047,8 @@ done:
return MDB_SUCCESS; return MDB_SUCCESS;
} }
static int ESECT mdb_env_share_locks(MDB_env *env, int *excl);
int int
mdb_txn_commit(MDB_txn *txn) mdb_txn_commit(MDB_txn *txn)
{ {
@ -4274,6 +4276,15 @@ mdb_txn_commit(MDB_txn *txn)
if ((rc = mdb_env_write_meta(txn))) if ((rc = mdb_env_write_meta(txn)))
goto fail; goto fail;
end_mode = MDB_END_COMMITTED|MDB_END_UPDATE; 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: done:
mdb_txn_end(txn, end_mode); mdb_txn_end(txn, end_mode);
@ -4564,7 +4575,8 @@ static MDB_meta *
mdb_env_pick_meta(const MDB_env *env) mdb_env_pick_meta(const MDB_env *env)
{ {
MDB_meta *const *metas = env->me_metas; 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 int ESECT
@ -5139,6 +5151,9 @@ mdb_env_open2(MDB_env *env, int prev)
#endif #endif
env->me_maxpg = env->me_mapsize / env->me_psize; env->me_maxpg = env->me_mapsize / env->me_psize;
if (env->me_txns)
env->me_txns->mti_txnid = meta.mm_txnid;
#if MDB_DEBUG #if MDB_DEBUG
{ {
MDB_meta *meta = mdb_env_pick_meta(env); MDB_meta *meta = mdb_env_pick_meta(env);
@ -5238,9 +5253,6 @@ static int ESECT
mdb_env_share_locks(MDB_env *env, int *excl) mdb_env_share_locks(MDB_env *env, int *excl)
{ {
int rc = 0; int rc = 0;
MDB_meta *meta = mdb_env_pick_meta(env);
env->me_txns->mti_txnid = meta->mm_txnid;
#ifdef _WIN32 #ifdef _WIN32
{ {
@ -5684,7 +5696,7 @@ mdb_env_envflags(MDB_env *env)
/*f*/ MDB_FIXEDMAP, /*h*/ MDB_NORDAHEAD, /*i*/ MDB_NOMEMINIT, /*f*/ MDB_FIXEDMAP, /*h*/ MDB_NORDAHEAD, /*i*/ MDB_NOMEMINIT,
/*l*/ MDB_NOLOCK, /*m*/ MDB_NOMETASYNC, /*n*/ MDB_NOSUBDIR, /*l*/ MDB_NOLOCK, /*m*/ MDB_NOMETASYNC, /*n*/ MDB_NOSUBDIR,
/*r*/ MDB_RDONLY, /*s*/ MDB_NOSYNC, /*t*/ MDB_NOTLS, /*r*/ MDB_RDONLY, /*s*/ MDB_NOSYNC, /*t*/ MDB_NOTLS,
/*v*/ MDB_PREVMETA, /*w*/ MDB_WRITEMAP, /*v*/ MDB_PREVSNAPSHOT, /*w*/ MDB_WRITEMAP,
}; };
unsigned flags = 0; unsigned flags = 0;
const char *s, *opts = getenv("LMDB_FLAGS"); const char *s, *opts = getenv("LMDB_FLAGS");
@ -5724,7 +5736,7 @@ mdb_env_envflags(MDB_env *env)
*/ */
#define CHANGEABLE (MDB_NOSYNC|MDB_NOMETASYNC|MDB_MAPASYNC|MDB_NOMEMINIT) #define CHANGEABLE (MDB_NOSYNC|MDB_NOMETASYNC|MDB_MAPASYNC|MDB_NOMEMINIT)
#define CHANGELESS (MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY| \ #define CHANGELESS (MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY| \
MDB_WRITEMAP|MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD|MDB_PREVMETA|MDB_REMAP_CHUNKS) MDB_WRITEMAP|MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD|MDB_PREVSNAPSHOT|MDB_REMAP_CHUNKS)
#define EXPOSED (CHANGEABLE|CHANGELESS | MDB_ENCRYPT) #define EXPOSED (CHANGEABLE|CHANGELESS | MDB_ENCRYPT)
#if VALID_FLAGS & PERSISTENT_FLAGS & EXPOSED #if VALID_FLAGS & PERSISTENT_FLAGS & EXPOSED
@ -5823,6 +5835,10 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
rc = mdb_env_setup_locks(env, &fname, mode, &excl); rc = mdb_env_setup_locks(env, &fname, mode, &excl);
if (rc) if (rc)
goto leave; goto leave;
if ((flags & MDB_PREVSNAPSHOT) && !excl) {
rc = EAGAIN;
goto leave;
}
} }
rc = mdb_fopen(env, &fname, rc = mdb_fopen(env, &fname,
@ -5837,7 +5853,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
goto leave; goto leave;
} }
if ((rc = mdb_env_open2(env, flags & MDB_PREVMETA)) == MDB_SUCCESS) { if ((rc = mdb_env_open2(env, flags & MDB_PREVSNAPSHOT)) == MDB_SUCCESS) {
if (!(flags & (MDB_RDONLY|MDB_WRITEMAP))) { if (!(flags & (MDB_RDONLY|MDB_WRITEMAP))) {
/* Synchronous fd for meta writes. Needed even with /* Synchronous fd for meta writes. Needed even with
* MDB_NOSYNC/MDB_NOMETASYNC, in case these get reset. * MDB_NOSYNC/MDB_NOMETASYNC, in case these get reset.
@ -5847,7 +5863,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
goto leave; goto leave;
} }
DPRINTF(("opened dbenv %p", (void *) env)); DPRINTF(("opened dbenv %p", (void *) env));
if (excl > 0) { if (excl > 0 && !(flags & MDB_PREVSNAPSHOT)) {
rc = mdb_env_share_locks(env, &excl); rc = mdb_env_share_locks(env, &excl);
if (rc) if (rc)
goto leave; goto leave;

@ -39,7 +39,7 @@ int main(int argc,char * argv[])
if (argv[1][1] == 'n' && argv[1][2] == '\0') if (argv[1][1] == 'n' && argv[1][2] == '\0')
flags |= MDB_NOSUBDIR; flags |= MDB_NOSUBDIR;
else if (argv[1][1] == 'v' && argv[1][2] == '\0') else if (argv[1][1] == 'v' && argv[1][2] == '\0')
flags |= MDB_PREVMETA; flags |= MDB_PREVSNAPSHOT;
else if (argv[1][1] == 'c' && argv[1][2] == '\0') else if (argv[1][1] == 'c' && argv[1][2] == '\0')
cpflags |= MDB_CP_COMPACT; cpflags |= MDB_CP_COMPACT;
else if (argv[1][1] == 'V' && argv[1][2] == '\0') { else if (argv[1][1] == 'V' && argv[1][2] == '\0') {

@ -175,7 +175,7 @@ int main(int argc, char *argv[])
* -n: use NOSUBDIR flag on env_open * -n: use NOSUBDIR flag on env_open
* -p: use printable characters * -p: use printable characters
* -f: write to file instead of stdout * -f: write to file instead of stdout
* -v: use previous metapage * -v: use previous snapshot
* -V: print version and exit * -V: print version and exit
* (default) dump only the main DB * (default) dump only the main DB
*/ */
@ -204,7 +204,7 @@ int main(int argc, char *argv[])
envflags |= MDB_NOSUBDIR; envflags |= MDB_NOSUBDIR;
break; break;
case 'v': case 'v':
envflags |= MDB_PREVMETA; envflags |= MDB_PREVSNAPSHOT;
break; break;
case 'p': case 'p':
mode |= PRINT; mode |= PRINT;

@ -61,7 +61,7 @@ int main(int argc, char *argv[])
* -f: print freelist info * -f: print freelist info
* -r: print reader info * -r: print reader info
* -n: use NOSUBDIR flag on env_open * -n: use NOSUBDIR flag on env_open
* -v: use previous metapage * -v: use previous snapshot
* -V: print version and exit * -V: print version and exit
* (default) print stat of only the main DB * (default) print stat of only the main DB
*/ */
@ -86,7 +86,7 @@ int main(int argc, char *argv[])
envflags |= MDB_NOSUBDIR; envflags |= MDB_NOSUBDIR;
break; break;
case 'v': case 'v':
envflags |= MDB_PREVMETA; envflags |= MDB_PREVSNAPSHOT;
break; break;
case 'r': case 'r':
rdrinfo++; rdrinfo++;

Loading…
Cancel
Save