lmdb: rework error handling inside mdb_chk.

Change-Id: I226f7b4bccb18261425799ea78bf43436867c7d4
This commit is contained in:
Leo Yuriev 2015-08-07 21:27:11 +03:00
parent 96d69e3fa1
commit c70999052c

View File

@ -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;