mirror of
https://github.com/monero-project/monero.git
synced 2024-12-23 03:59:33 +00:00
ITS#8704 add MDB_PREVSNAPSHOT flag to mdb_env_open
used to open the previous snapshot, in case the latest one is corrupted
This commit is contained in:
parent
86226754a9
commit
9c6eb75c65
8 changed files with 68 additions and 15 deletions
8
external/db_drivers/liblmdb/lmdb.h
vendored
8
external/db_drivers/liblmdb/lmdb.h
vendored
|
@ -311,6 +311,8 @@ typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *rel
|
||||||
#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 snapshot rather than the latest one */
|
||||||
|
#define MDB_PREVSNAPSHOT 0x2000000
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/** @defgroup mdb_dbi_open Database Flags
|
/** @defgroup mdb_dbi_open Database Flags
|
||||||
|
@ -622,6 +624,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_PREVSNAPSHOT
|
||||||
|
* Open the environment with the previous snapshot rather than the latest
|
||||||
|
* one. This loses the latest transaction, but may help work around some
|
||||||
|
* 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.
|
||||||
|
|
41
external/db_drivers/liblmdb/mdb.c
vendored
41
external/db_drivers/liblmdb/mdb.c
vendored
|
@ -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,
|
static int mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata,
|
||||||
pgno_t newpgno, unsigned int nflags);
|
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 MDB_meta *mdb_env_pick_meta(const MDB_env *env);
|
||||||
static int mdb_env_write_meta(MDB_txn *txn);
|
static int mdb_env_write_meta(MDB_txn *txn);
|
||||||
#ifdef MDB_USE_POSIX_MUTEX /* Drop unused excl arg */
|
#ifdef MDB_USE_POSIX_MUTEX /* Drop unused excl arg */
|
||||||
|
@ -3632,6 +3632,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)
|
||||||
{
|
{
|
||||||
|
@ -3854,6 +3856,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);
|
||||||
|
@ -3867,11 +3878,12 @@ fail:
|
||||||
/** Read the environment parameters of a DB environment before
|
/** Read the environment parameters of a DB environment before
|
||||||
* mapping it into memory.
|
* mapping it into memory.
|
||||||
* @param[in] env the environment handle
|
* @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
|
* @param[out] meta address of where to store the meta information
|
||||||
* @return 0 on success, non-zero on failure.
|
* @return 0 on success, non-zero on failure.
|
||||||
*/
|
*/
|
||||||
static int ESECT
|
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_metabuf pbuf;
|
||||||
MDB_page *p;
|
MDB_page *p;
|
||||||
|
@ -3922,7 +3934,7 @@ mdb_env_read_header(MDB_env *env, MDB_meta *meta)
|
||||||
return MDB_VERSION_MISMATCH;
|
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;
|
*meta = *m;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -4131,7 +4143,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
|
||||||
|
@ -4366,7 +4379,7 @@ mdb_fsize(HANDLE fd, mdb_size_t *size)
|
||||||
/** Further setup required for opening an LMDB environment
|
/** Further setup required for opening an LMDB environment
|
||||||
*/
|
*/
|
||||||
static int ESECT
|
static int ESECT
|
||||||
mdb_env_open2(MDB_env *env)
|
mdb_env_open2(MDB_env *env, int prev)
|
||||||
{
|
{
|
||||||
unsigned int flags = env->me_flags;
|
unsigned int flags = env->me_flags;
|
||||||
int i, newenv = 0, rc;
|
int i, newenv = 0, rc;
|
||||||
|
@ -4429,7 +4442,7 @@ mdb_env_open2(MDB_env *env)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((i = mdb_env_read_header(env, &meta)) != 0) {
|
if ((i = mdb_env_read_header(env, prev, &meta)) != 0) {
|
||||||
if (i != ENOENT)
|
if (i != ENOENT)
|
||||||
return i;
|
return i;
|
||||||
DPUTS("new mdbenv");
|
DPUTS("new mdbenv");
|
||||||
|
@ -4505,6 +4518,9 @@ mdb_env_open2(MDB_env *env)
|
||||||
#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);
|
||||||
|
@ -4600,9 +4616,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
|
||||||
{
|
{
|
||||||
|
@ -5056,7 +5069,7 @@ fail:
|
||||||
*/
|
*/
|
||||||
#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_WRITEMAP|MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD|MDB_PREVSNAPSHOT)
|
||||||
|
|
||||||
#if VALID_FLAGS & PERSISTENT_FLAGS & (CHANGEABLE|CHANGELESS)
|
#if VALID_FLAGS & PERSISTENT_FLAGS & (CHANGEABLE|CHANGELESS)
|
||||||
# error "Persistent DB flags & env flags overlap, but both go in mm_flags"
|
# 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);
|
rc = mdb_env_setup_locks(env, lpath, mode, &excl);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
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)) {
|
if (flags & (MDB_RDONLY|MDB_WRITEMAP)) {
|
||||||
env->me_mfd = env->me_fd;
|
env->me_mfd = env->me_fd;
|
||||||
} else {
|
} 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));
|
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;
|
||||||
|
|
6
external/db_drivers/liblmdb/mdb_copy.1
vendored
6
external/db_drivers/liblmdb/mdb_copy.1
vendored
|
@ -11,6 +11,8 @@ mdb_copy \- LMDB environment copy tool
|
||||||
.BR \-c ]
|
.BR \-c ]
|
||||||
[\c
|
[\c
|
||||||
.BR \-n ]
|
.BR \-n ]
|
||||||
|
[\c
|
||||||
|
.BR \-v ]
|
||||||
.B srcpath
|
.B srcpath
|
||||||
[\c
|
[\c
|
||||||
.BR dstpath ]
|
.BR dstpath ]
|
||||||
|
@ -39,6 +41,10 @@ slow down the backup process as it is more CPU-intensive.
|
||||||
.TP
|
.TP
|
||||||
.BR \-n
|
.BR \-n
|
||||||
Open LDMB environment(s) which do not use subdirectories.
|
Open LDMB environment(s) which do not use subdirectories.
|
||||||
|
.TP
|
||||||
|
.BR \-v
|
||||||
|
Use the previous environment state instead of the latest state.
|
||||||
|
This may be useful if the latest state has been corrupted.
|
||||||
|
|
||||||
.SH DIAGNOSTICS
|
.SH DIAGNOSTICS
|
||||||
Exit status is zero if no errors occur.
|
Exit status is zero if no errors occur.
|
||||||
|
|
4
external/db_drivers/liblmdb/mdb_copy.c
vendored
4
external/db_drivers/liblmdb/mdb_copy.c
vendored
|
@ -38,6 +38,8 @@ int main(int argc,char * argv[])
|
||||||
for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) {
|
for (; argc > 1 && argv[1][0] == '-'; argc--, 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')
|
||||||
|
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') {
|
||||||
|
@ -48,7 +50,7 @@ int main(int argc,char * argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc<2 || argc>3) {
|
if (argc<2 || argc>3) {
|
||||||
fprintf(stderr, "usage: %s [-V] [-c] [-n] srcpath [dstpath]\n", progname);
|
fprintf(stderr, "usage: %s [-V] [-c] [-n] [-v] srcpath [dstpath]\n", progname);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
external/db_drivers/liblmdb/mdb_dump.1
vendored
6
external/db_drivers/liblmdb/mdb_dump.1
vendored
|
@ -14,6 +14,8 @@ mdb_dump \- LMDB environment export tool
|
||||||
[\c
|
[\c
|
||||||
.BR \-n ]
|
.BR \-n ]
|
||||||
[\c
|
[\c
|
||||||
|
.BR \-v ]
|
||||||
|
[\c
|
||||||
.BR \-p ]
|
.BR \-p ]
|
||||||
[\c
|
[\c
|
||||||
.BR \-a \ |
|
.BR \-a \ |
|
||||||
|
@ -42,6 +44,10 @@ names will be listed, no data will be output.
|
||||||
.BR \-n
|
.BR \-n
|
||||||
Dump an LMDB database which does not use subdirectories.
|
Dump an LMDB database which does not use subdirectories.
|
||||||
.TP
|
.TP
|
||||||
|
.BR \-v
|
||||||
|
Use the previous environment state instead of the latest state.
|
||||||
|
This may be useful if the latest state has been corrupted.
|
||||||
|
.TP
|
||||||
.BR \-p
|
.BR \-p
|
||||||
If characters in either the key or data items are printing characters (as
|
If characters in either the key or data items are printing characters (as
|
||||||
defined by isprint(3)), output them directly. This option permits users to
|
defined by isprint(3)), output them directly. This option permits users to
|
||||||
|
|
6
external/db_drivers/liblmdb/mdb_dump.c
vendored
6
external/db_drivers/liblmdb/mdb_dump.c
vendored
|
@ -164,7 +164,7 @@ static int dumpit(MDB_txn *txn, MDB_dbi dbi, char *name)
|
||||||
|
|
||||||
static void usage(char *prog)
|
static void usage(char *prog)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "usage: %s [-V] [-f output] [-l] [-n] [-p] [-a|-s subdb] dbpath\n", prog);
|
fprintf(stderr, "usage: %s [-V] [-f output] [-l] [-n] [-p] [-v] [-a|-s subdb] dbpath\n", prog);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +188,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 snapshot
|
||||||
* -V: print version and exit
|
* -V: print version and exit
|
||||||
* (default) dump only the main DB
|
* (default) dump only the main DB
|
||||||
*/
|
*/
|
||||||
|
@ -215,6 +216,9 @@ int main(int argc, char *argv[])
|
||||||
case 'n':
|
case 'n':
|
||||||
envflags |= MDB_NOSUBDIR;
|
envflags |= MDB_NOSUBDIR;
|
||||||
break;
|
break;
|
||||||
|
case 'v':
|
||||||
|
envflags |= MDB_PREVSNAPSHOT;
|
||||||
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
mode |= PRINT;
|
mode |= PRINT;
|
||||||
break;
|
break;
|
||||||
|
|
6
external/db_drivers/liblmdb/mdb_stat.1
vendored
6
external/db_drivers/liblmdb/mdb_stat.1
vendored
|
@ -14,6 +14,8 @@ mdb_stat \- LMDB environment status tool
|
||||||
[\c
|
[\c
|
||||||
.BR \-n ]
|
.BR \-n ]
|
||||||
[\c
|
[\c
|
||||||
|
.BR \-v ]
|
||||||
|
[\c
|
||||||
.BR \-r [ r ]]
|
.BR \-r [ r ]]
|
||||||
[\c
|
[\c
|
||||||
.BR \-a \ |
|
.BR \-a \ |
|
||||||
|
@ -39,6 +41,10 @@ If \fB\-fff\fP is given, display the full list of page IDs in the freelist.
|
||||||
.BR \-n
|
.BR \-n
|
||||||
Display the status of an LMDB database which does not use subdirectories.
|
Display the status of an LMDB database which does not use subdirectories.
|
||||||
.TP
|
.TP
|
||||||
|
.BR \-v
|
||||||
|
Use the previous environment state instead of the latest state.
|
||||||
|
This may be useful if the latest state has been corrupted.
|
||||||
|
.TP
|
||||||
.BR \-r
|
.BR \-r
|
||||||
Display information about the environment reader table.
|
Display information about the environment reader table.
|
||||||
Shows the process ID, thread ID, and transaction ID for each active
|
Shows the process ID, thread ID, and transaction ID for each active
|
||||||
|
|
6
external/db_drivers/liblmdb/mdb_stat.c
vendored
6
external/db_drivers/liblmdb/mdb_stat.c
vendored
|
@ -46,7 +46,7 @@ static void prstat(MDB_stat *ms)
|
||||||
|
|
||||||
static void usage(char *prog)
|
static void usage(char *prog)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-a|-s subdb] dbpath\n", prog);
|
fprintf(stderr, "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-v] [-a|-s subdb] dbpath\n", prog);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +73,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 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
|
||||||
*/
|
*/
|
||||||
|
@ -96,6 +97,9 @@ int main(int argc, char *argv[])
|
||||||
case 'n':
|
case 'n':
|
||||||
envflags |= MDB_NOSUBDIR;
|
envflags |= MDB_NOSUBDIR;
|
||||||
break;
|
break;
|
||||||
|
case 'v':
|
||||||
|
envflags |= MDB_PREVSNAPSHOT;
|
||||||
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
rdrinfo++;
|
rdrinfo++;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue