mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-30 22:47:16 +08:00
mdbx-chk: support for turn to a specified meta-page.
Change-Id: I9d088681e7bd66a2f8b5917067c4f847733d17ac
This commit is contained in:
parent
58708f7162
commit
4eab5b238a
@ -218,7 +218,6 @@ static walk_dbi_t *pagemap_lookup_dbi(const char *dbi_name, bool silent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void MDBX_PRINTF_ARGS(4, 5)
|
static void MDBX_PRINTF_ARGS(4, 5)
|
||||||
|
|
||||||
problem_add(const char *object, uint64_t entry_number, const char *msg,
|
problem_add(const char *object, uint64_t entry_number, const char *msg,
|
||||||
const char *extra, ...) {
|
const char *extra, ...) {
|
||||||
total_problems++;
|
total_problems++;
|
||||||
@ -883,11 +882,13 @@ static void usage(char *prog) {
|
|||||||
" -v\t\tmore verbose, could be used multiple times\n"
|
" -v\t\tmore verbose, could be used multiple times\n"
|
||||||
" -q\t\tbe quiet\n"
|
" -q\t\tbe quiet\n"
|
||||||
" -c\t\tforce cooperative mode (don't try exclusive)\n"
|
" -c\t\tforce cooperative mode (don't try exclusive)\n"
|
||||||
" -0|1|2\tforce using specific meta-page 0..2 for checking\n"
|
" -w\t\twrite-mode checking\n"
|
||||||
" -w\t\tlock DB for writing while checking\n"
|
|
||||||
" -d\t\tdisable page-by-page traversal of B-tree\n"
|
" -d\t\tdisable page-by-page traversal of B-tree\n"
|
||||||
" -i\t\tignore wrong order errors (for custom comparators case)\n"
|
" -i\t\tignore wrong order errors (for custom comparators case)\n"
|
||||||
" -s subdb\tprocess a specific subdatabase only\n",
|
" -s subdb\tprocess a specific subdatabase only\n"
|
||||||
|
" -0|1|2\tforce using specific meta-page 0, or 2 for checking\n"
|
||||||
|
" -t\t\tturn to a specified meta-page on successful check\n"
|
||||||
|
" -T\t\tturn to a specified meta-page EVEN ON UNSUCCESSFUL CHECK!\n",
|
||||||
prog);
|
prog);
|
||||||
exit(EXIT_INTERRUPTED);
|
exit(EXIT_INTERRUPTED);
|
||||||
}
|
}
|
||||||
@ -1034,7 +1035,9 @@ int main(int argc, char *argv[]) {
|
|||||||
char *prog = argv[0];
|
char *prog = argv[0];
|
||||||
char *envname;
|
char *envname;
|
||||||
int problems_maindb = 0, problems_freedb = 0, problems_meta = 0;
|
int problems_maindb = 0, problems_freedb = 0, problems_meta = 0;
|
||||||
bool locked = false;
|
bool write_locked = false;
|
||||||
|
bool turn_meta = false;
|
||||||
|
bool force_turn_meta = false;
|
||||||
|
|
||||||
double elapsed;
|
double elapsed;
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
@ -1057,7 +1060,7 @@ int main(int argc, char *argv[]) {
|
|||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
usage(prog);
|
usage(prog);
|
||||||
|
|
||||||
for (int i; (i = getopt(argc, argv, "Vvqnwc012dis:")) != EOF;) {
|
for (int i; (i = getopt(argc, argv, "Vvqnwc012tTdis:")) != EOF;) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 'V':
|
case 'V':
|
||||||
printf("mdbx_chk version %d.%d.%d.%d\n"
|
printf("mdbx_chk version %d.%d.%d.%d\n"
|
||||||
@ -1085,6 +1088,15 @@ int main(int argc, char *argv[]) {
|
|||||||
case '2':
|
case '2':
|
||||||
stuck_meta = 2;
|
stuck_meta = 2;
|
||||||
break;
|
break;
|
||||||
|
case 't':
|
||||||
|
turn_meta = true;
|
||||||
|
break;
|
||||||
|
case 'T':
|
||||||
|
turn_meta = force_turn_meta = true;
|
||||||
|
quiet = false;
|
||||||
|
if (verbose < 2)
|
||||||
|
verbose = 2;
|
||||||
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
quiet = true;
|
quiet = true;
|
||||||
break;
|
break;
|
||||||
@ -1093,6 +1105,11 @@ int main(int argc, char *argv[]) {
|
|||||||
break;
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
envflags &= ~MDBX_RDONLY;
|
envflags &= ~MDBX_RDONLY;
|
||||||
|
#if MDBX_MMAP_INCOHERENT_FILE_WRITE
|
||||||
|
/* Temporary `workaround` for OpenBSD kernel's flaw.
|
||||||
|
* See https://github.com/erthink/libmdbx/issues/67 */
|
||||||
|
envflags |= MDBX_WRITEMAP;
|
||||||
|
#endif /* MDBX_MMAP_INCOHERENT_FILE_WRITE */
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
envflags = (envflags & ~MDBX_EXCLUSIVE) | MDBX_ACCEDE;
|
envflags = (envflags & ~MDBX_EXCLUSIVE) | MDBX_ACCEDE;
|
||||||
@ -1116,14 +1133,31 @@ int main(int argc, char *argv[]) {
|
|||||||
if (optind != argc - 1)
|
if (optind != argc - 1)
|
||||||
usage(prog);
|
usage(prog);
|
||||||
|
|
||||||
if (stuck_meta >= 0) {
|
rc = MDBX_SUCCESS;
|
||||||
if ((envflags & MDBX_EXCLUSIVE) == 0) {
|
if (stuck_meta >= 0 && (envflags & MDBX_EXCLUSIVE) == 0) {
|
||||||
error("exclusive mode is required to using specific meta-page(%d) for "
|
error("exclusive mode is required to using specific meta-page(%d) for "
|
||||||
"checking.\n",
|
"checking.\n",
|
||||||
stuck_meta);
|
stuck_meta);
|
||||||
exit(EXIT_INTERRUPTED);
|
rc = EXIT_INTERRUPTED;
|
||||||
|
}
|
||||||
|
if (turn_meta) {
|
||||||
|
if (stuck_meta < 0) {
|
||||||
|
error("meta-page must be specified (by -0, -1 or -2 options) to turn to "
|
||||||
|
"it.\n");
|
||||||
|
rc = EXIT_INTERRUPTED;
|
||||||
|
}
|
||||||
|
if (envflags & MDBX_RDONLY) {
|
||||||
|
error("write-mode must be enabled to turn to the specified meta-page.\n");
|
||||||
|
rc = EXIT_INTERRUPTED;
|
||||||
|
}
|
||||||
|
if (only_subdb || dont_traversal) {
|
||||||
|
error("whole database checking with tree-traversal are required to turn "
|
||||||
|
"to the specified meta-page.\n");
|
||||||
|
rc = EXIT_INTERRUPTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rc)
|
||||||
|
exit(rc);
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true);
|
SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true);
|
||||||
@ -1189,13 +1223,13 @@ int main(int argc, char *argv[]) {
|
|||||||
print(" - %s mode\n",
|
print(" - %s mode\n",
|
||||||
(envflags & MDBX_EXCLUSIVE) ? "monopolistic" : "cooperative");
|
(envflags & MDBX_EXCLUSIVE) ? "monopolistic" : "cooperative");
|
||||||
|
|
||||||
if ((envflags & MDBX_RDONLY) == 0) {
|
if ((envflags & (MDBX_RDONLY | MDBX_EXCLUSIVE)) == 0) {
|
||||||
rc = mdbx_txn_lock(env, false);
|
rc = mdbx_txn_lock(env, false);
|
||||||
if (rc != MDBX_SUCCESS) {
|
if (rc != MDBX_SUCCESS) {
|
||||||
error("mdbx_txn_lock failed, error %d %s\n", rc, mdbx_strerror(rc));
|
error("mdbx_txn_lock failed, error %d %s\n", rc, mdbx_strerror(rc));
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
locked = true;
|
write_locked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = mdbx_txn_begin(env, nullptr, MDBX_TXN_RDONLY, &txn);
|
rc = mdbx_txn_begin(env, nullptr, MDBX_TXN_RDONLY, &txn);
|
||||||
@ -1372,7 +1406,7 @@ int main(int argc, char *argv[]) {
|
|||||||
steady_meta_id, steady_meta_txnid, envinfo.mi_recent_txnid);
|
steady_meta_id, steady_meta_txnid, envinfo.mi_recent_txnid);
|
||||||
++problems_meta;
|
++problems_meta;
|
||||||
}
|
}
|
||||||
} else if (locked) {
|
} else if (write_locked) {
|
||||||
if (verbose > 1)
|
if (verbose > 1)
|
||||||
print(" - performs lite check recent-txn-id with meta-pages (not a "
|
print(" - performs lite check recent-txn-id with meta-pages (not a "
|
||||||
"monopolistic mode)\n");
|
"monopolistic mode)\n");
|
||||||
@ -1560,9 +1594,9 @@ int main(int argc, char *argv[]) {
|
|||||||
"\n",
|
"\n",
|
||||||
envinfo.mi_recent_txnid);
|
envinfo.mi_recent_txnid);
|
||||||
fflush(nullptr);
|
fflush(nullptr);
|
||||||
if (locked) {
|
if (write_locked) {
|
||||||
mdbx_txn_unlock(env);
|
mdbx_txn_unlock(env);
|
||||||
locked = false;
|
write_locked = false;
|
||||||
}
|
}
|
||||||
rc = mdbx_env_sync_ex(env, true, false);
|
rc = mdbx_env_sync_ex(env, true, false);
|
||||||
if (rc != MDBX_SUCCESS)
|
if (rc != MDBX_SUCCESS)
|
||||||
@ -1573,12 +1607,32 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (turn_meta && stuck_meta >= 0 && !dont_traversal && !only_subdb &&
|
||||||
|
(envflags & (MDBX_RDONLY | MDBX_EXCLUSIVE)) == MDBX_EXCLUSIVE) {
|
||||||
|
const bool successful_check = (rc | total_problems | problems_meta) == 0;
|
||||||
|
if (successful_check || force_turn_meta) {
|
||||||
|
fflush(nullptr);
|
||||||
|
print(" = Performing turn to the specified meta-page (%d) due to %s!\n",
|
||||||
|
stuck_meta,
|
||||||
|
successful_check ? "successful check" : "the -T option was given");
|
||||||
|
fflush(nullptr);
|
||||||
|
rc = mdbx_env_turn_for_recovery(env, stuck_meta);
|
||||||
|
if (rc != MDBX_SUCCESS)
|
||||||
|
error("mdbx_env_turn_for_recovery failed, error %d %s\n", rc,
|
||||||
|
mdbx_strerror(rc));
|
||||||
|
} else {
|
||||||
|
print(" = Skipping turn to the specified meta-page (%d) due to "
|
||||||
|
"unsuccessful check!\n",
|
||||||
|
stuck_meta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bailout:
|
bailout:
|
||||||
if (txn)
|
if (txn)
|
||||||
mdbx_txn_abort(txn);
|
mdbx_txn_abort(txn);
|
||||||
if (locked) {
|
if (write_locked) {
|
||||||
mdbx_txn_unlock(env);
|
mdbx_txn_unlock(env);
|
||||||
locked = false;
|
write_locked = false;
|
||||||
}
|
}
|
||||||
if (env) {
|
if (env) {
|
||||||
const bool dont_sync = rc != 0 || total_problems;
|
const bool dont_sync = rc != 0 || total_problems;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user