mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-04 17:34:14 +08:00
lmdb: rework error handling inside mdb_chk.
Change-Id: I226f7b4bccb18261425799ea78bf43436867c7d4
This commit is contained in:
parent
96d69e3fa1
commit
c70999052c
95
mdb_chk.c
95
mdb_chk.c
@ -68,7 +68,7 @@ MDB_txn *txn, *locktxn;
|
|||||||
MDB_envinfo info;
|
MDB_envinfo info;
|
||||||
MDB_stat stat;
|
MDB_stat stat;
|
||||||
size_t maxkeysize, reclaimable_pages, freedb_pages, lastpgno;
|
size_t maxkeysize, reclaimable_pages, freedb_pages, lastpgno;
|
||||||
unsigned userdb_count;
|
size_t userdb_count;
|
||||||
unsigned verbose, quiet;
|
unsigned verbose, quiet;
|
||||||
|
|
||||||
struct problem {
|
struct problem {
|
||||||
@ -161,7 +161,7 @@ static struct problem* problems_push() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t problems_pop(struct problem* list) {
|
static size_t problems_pop(struct problem* list) {
|
||||||
size_t total = 0;
|
size_t count = 0;
|
||||||
|
|
||||||
if (problems_list) {
|
if (problems_list) {
|
||||||
int i;
|
int i;
|
||||||
@ -169,7 +169,7 @@ static size_t problems_pop(struct problem* list) {
|
|||||||
print(" - problems: ");
|
print(" - problems: ");
|
||||||
for (i = 0; problems_list; ++i) {
|
for (i = 0; problems_list; ++i) {
|
||||||
struct problem* p = problems_list->pr_next;
|
struct problem* p = problems_list->pr_next;
|
||||||
total += problems_list->count;
|
count += problems_list->count;
|
||||||
print("%s%s (%zu)", i ? ", " : "", problems_list->caption, problems_list->count);
|
print("%s%s (%zu)", i ? ", " : "", problems_list->caption, problems_list->count);
|
||||||
free(problems_list);
|
free(problems_list);
|
||||||
problems_list = p;
|
problems_list = p;
|
||||||
@ -178,7 +178,7 @@ static size_t problems_pop(struct problem* list) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
problems_list = list;
|
problems_list = list;
|
||||||
return total;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pgvisitor(size_t pgno, unsigned pgnumber, void* ctx, const char* dbi,
|
static int pgvisitor(size_t pgno, unsigned pgnumber, void* ctx, const char* dbi,
|
||||||
@ -220,19 +220,18 @@ static int pgvisitor(size_t pgno, unsigned pgnumber, void* ctx, const char* dbi,
|
|||||||
return MDB_SUCCESS;
|
return MDB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef long (visitor)(size_t record_number, MDB_val *key, MDB_val* data);
|
typedef int (visitor)(size_t record_number, MDB_val *key, MDB_val* data);
|
||||||
static long process_db(MDB_dbi dbi, char *name, visitor *handler, int silent);
|
static int process_db(MDB_dbi dbi, char *name, visitor *handler, int silent);
|
||||||
|
|
||||||
static long handle_userdb(size_t record_number, MDB_val *key, MDB_val* data) {
|
static int handle_userdb(size_t record_number, MDB_val *key, MDB_val* data) {
|
||||||
return MDB_SUCCESS;
|
return MDB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long handle_freedb(size_t record_number, MDB_val *key, MDB_val* data) {
|
static int handle_freedb(size_t record_number, MDB_val *key, MDB_val* data) {
|
||||||
char *bad = "";
|
char *bad = "";
|
||||||
size_t pg, prev;
|
size_t pg, prev;
|
||||||
ssize_t i, number, span = 0;
|
ssize_t i, number, span = 0;
|
||||||
size_t *iptr = data->mv_data, txnid = *(size_t*)key->mv_data;
|
size_t *iptr = data->mv_data, txnid = *(size_t*)key->mv_data;
|
||||||
long problem_count = 0;
|
|
||||||
|
|
||||||
if (key->mv_size != sizeof(txnid))
|
if (key->mv_size != sizeof(txnid))
|
||||||
problem_add(record_number, "wrong txn-id size", "(key-size %zi)", key->mv_size);
|
problem_add(record_number, "wrong txn-id size", "(key-size %zi)", key->mv_size);
|
||||||
@ -257,9 +256,10 @@ static long handle_freedb(size_t record_number, MDB_val *key, MDB_val* data) {
|
|||||||
if (pg < 2 /* META_PAGE */ || pg > info.me_last_pgno)
|
if (pg < 2 /* META_PAGE */ || pg > info.me_last_pgno)
|
||||||
problem_add(record_number, "wrong idl entry", "(2 < %zi < %zi)",
|
problem_add(record_number, "wrong idl entry", "(2 < %zi < %zi)",
|
||||||
pg, info.me_last_pgno);
|
pg, info.me_last_pgno);
|
||||||
if (pg <= prev) {
|
else if (pg <= prev) {
|
||||||
bad = " [bad sequence]";
|
bad = " [bad sequence]";
|
||||||
++problem_count;
|
problem_add(record_number, "bad sequence", "(%zi <= %zi)",
|
||||||
|
pg, prev);
|
||||||
}
|
}
|
||||||
prev = pg;
|
prev = pg;
|
||||||
pg += span;
|
pg += span;
|
||||||
@ -279,13 +279,12 @@ static long handle_freedb(size_t record_number, MDB_val *key, MDB_val* data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return problem_count;
|
return MDB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long handle_maindb(size_t record_number, MDB_val *key, MDB_val* data) {
|
static int handle_maindb(size_t record_number, MDB_val *key, MDB_val* data) {
|
||||||
char *name;
|
char *name;
|
||||||
int i;
|
int i, rc;
|
||||||
long rc;
|
|
||||||
|
|
||||||
name = key->mv_data;
|
name = key->mv_data;
|
||||||
for(i = 0; i < key->mv_size; ++i) {
|
for(i = 0; i < key->mv_size; ++i) {
|
||||||
@ -306,7 +305,7 @@ static long handle_maindb(size_t record_number, MDB_val *key, MDB_val* data) {
|
|||||||
return handle_userdb(record_number, key, data);
|
return handle_userdb(record_number, key, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long process_db(MDB_dbi dbi, char *name, visitor *handler, int silent)
|
static int process_db(MDB_dbi dbi, char *name, visitor *handler, int silent)
|
||||||
{
|
{
|
||||||
MDB_cursor *mc;
|
MDB_cursor *mc;
|
||||||
MDB_stat ms;
|
MDB_stat ms;
|
||||||
@ -379,6 +378,12 @@ static long process_db(MDB_dbi dbi, char *name, visitor *handler, int silent)
|
|||||||
prev_data.mv_size = 0;
|
prev_data.mv_size = 0;
|
||||||
rc = mdb_cursor_get(mc, &key, &data, MDB_FIRST);
|
rc = mdb_cursor_get(mc, &key, &data, MDB_FIRST);
|
||||||
while (rc == MDB_SUCCESS) {
|
while (rc == MDB_SUCCESS) {
|
||||||
|
if (gotsignal) {
|
||||||
|
print(" - interrupted by signal\n");
|
||||||
|
rc = EINTR;
|
||||||
|
goto bailout;
|
||||||
|
}
|
||||||
|
|
||||||
if (key.mv_size == 0) {
|
if (key.mv_size == 0) {
|
||||||
problem_add(record_count, "key with zero length", NULL);
|
problem_add(record_count, "key with zero length", NULL);
|
||||||
} else if (key.mv_size > maxkeysize) {
|
} else if (key.mv_size > maxkeysize) {
|
||||||
@ -422,9 +427,11 @@ static long process_db(MDB_dbi dbi, char *name, visitor *handler, int silent)
|
|||||||
print(" - fixed data-size %zu\n", data.mv_size );
|
print(" - fixed data-size %zu\n", data.mv_size );
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = gotsignal ? EINTR : (handler ? handler(record_count, &key, &data) : 0);
|
if (handler) {
|
||||||
if (rc)
|
rc = handler(record_count, &key, &data);
|
||||||
goto bailout;
|
if (rc)
|
||||||
|
goto bailout;
|
||||||
|
}
|
||||||
|
|
||||||
record_count++;
|
record_count++;
|
||||||
key_bytes += key.mv_size;
|
key_bytes += key.mv_size;
|
||||||
@ -434,8 +441,10 @@ static long process_db(MDB_dbi dbi, char *name, visitor *handler, int silent)
|
|||||||
prev_data = data;
|
prev_data = data;
|
||||||
rc = mdb_cursor_get(mc, &key, &data, MDB_NEXT);
|
rc = mdb_cursor_get(mc, &key, &data, MDB_NEXT);
|
||||||
}
|
}
|
||||||
if (rc == MDB_NOTFOUND)
|
if (rc != MDB_NOTFOUND)
|
||||||
rc = MDB_SUCCESS;
|
error(" - mdb_cursor_get failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||||
|
else
|
||||||
|
rc = 0;
|
||||||
|
|
||||||
if (record_count != ms.ms_entries)
|
if (record_count != ms.ms_entries)
|
||||||
problem_add(record_count, "differentent number of entries",
|
problem_add(record_count, "differentent number of entries",
|
||||||
@ -449,7 +458,7 @@ bailout:
|
|||||||
|
|
||||||
mdb_cursor_close(mc);
|
mdb_cursor_close(mc);
|
||||||
mdb_dbi_close(env, dbi);
|
mdb_dbi_close(env, dbi);
|
||||||
return rc ? rc : problems_count;
|
return rc || problems_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usage(char *prog)
|
static void usage(char *prog)
|
||||||
@ -485,8 +494,7 @@ int main(int argc, char *argv[])
|
|||||||
char *prog = argv[0];
|
char *prog = argv[0];
|
||||||
char *envname;
|
char *envname;
|
||||||
int envflags = MDB_RDONLY;
|
int envflags = MDB_RDONLY;
|
||||||
long problems_maindb = 0, problems_freedb = 0;
|
int problems_maindb = 0, problems_freedb = 0, problems_meta = 0;
|
||||||
int problems_meta = 0;
|
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
@ -709,35 +717,32 @@ int main(int argc, char *argv[])
|
|||||||
print(", available %zu (%.1f%%)\n", value, value / percent);
|
print(", available %zu (%.1f%%)\n", value, value / percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pgcount != lastpgno - freedb_pages) {
|
if (problems_maindb == 0 && problems_freedb == 0) {
|
||||||
error("used pages mismatch (%zu != %zu)\n", pgcount, lastpgno - freedb_pages);
|
if (pgcount != lastpgno - freedb_pages) {
|
||||||
goto bailout;
|
error("used pages mismatch (%zu != %zu)\n", pgcount, lastpgno - freedb_pages);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dbi_pages[0] != freedb_pages) {
|
||||||
|
error("gc pages mismatch (%zu != %zu)\n", dbi_pages[0], freedb_pages);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! process_db(-1, NULL, handle_maindb, 1)) {
|
||||||
|
if (! userdb_count && verbose)
|
||||||
|
print(" - does not contain multiple databases\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (dbi_pages[0] != freedb_pages) {
|
|
||||||
error("gc pages mismatch (%zu != %zu)\n", dbi_pages[0], freedb_pages);
|
|
||||||
goto bailout;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (problems_maindb == 0 && problems_freedb == 0)
|
|
||||||
process_db(-1, NULL, handle_maindb, 1);
|
|
||||||
|
|
||||||
mdb_txn_abort(txn);
|
|
||||||
if (locktxn)
|
|
||||||
mdb_txn_abort(locktxn);
|
|
||||||
|
|
||||||
if (! userdb_count && verbose)
|
|
||||||
print("%s: %s does not contain multiple databases\n", prog, envname);
|
|
||||||
|
|
||||||
if (rc)
|
|
||||||
error("%s: %s: %s\n", prog, envname, mdb_strerror(rc));
|
|
||||||
|
|
||||||
bailout:
|
bailout:
|
||||||
|
if (locktxn)
|
||||||
|
mdb_txn_abort(locktxn);
|
||||||
|
if (txn)
|
||||||
|
mdb_txn_abort(txn);
|
||||||
mdb_env_close(env);
|
mdb_env_close(env);
|
||||||
free(pagemap);
|
free(pagemap);
|
||||||
if (rc)
|
if (rc)
|
||||||
return EXIT_FAILURE + 2;
|
return EXIT_FAILURE + 2;
|
||||||
total_problems += problems_meta;
|
total_problems += problems_meta;
|
||||||
if (total_problems) {
|
if (total_problems || problems_maindb || problems_freedb) {
|
||||||
print("Total %zu error(s) is detected.\n", total_problems);
|
print("Total %zu error(s) is detected.\n", total_problems);
|
||||||
if (problems_meta || problems_maindb || problems_freedb)
|
if (problems_meta || problems_maindb || problems_freedb)
|
||||||
return EXIT_FAILURE + 1;
|
return EXIT_FAILURE + 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user