mdbx-tools: refine mdbx_stat.

This commit is contained in:
Leonid Yuriev 2020-05-15 11:59:15 +03:00
parent efe4fd2cc9
commit 6fa2748fc7

View File

@ -43,7 +43,7 @@ static void signal_handler(int sig) {
#endif /* !WINDOWS */ #endif /* !WINDOWS */
static void prstat(MDBX_stat *ms) { static void print_stat(MDBX_stat *ms) {
printf(" Pagesize: %u\n", ms->ms_psize); printf(" Pagesize: %u\n", ms->ms_psize);
printf(" Tree depth: %u\n", ms->ms_depth); printf(" Tree depth: %u\n", ms->ms_depth);
printf(" Branch pages: %" PRIu64 "\n", ms->ms_branch_pages); printf(" Branch pages: %" PRIu64 "\n", ms->ms_branch_pages);
@ -52,7 +52,7 @@ static void prstat(MDBX_stat *ms) {
printf(" Entries: %" PRIu64 "\n", ms->ms_entries); printf(" Entries: %" PRIu64 "\n", ms->ms_entries);
} }
static void usage(char *prog) { static void usage(const char *prog) {
fprintf(stderr, fprintf(stderr,
"usage: %s [-V] [-e] [-f[f[f]]] [-r[r]] [-a|-s name] dbpath\n" "usage: %s [-V] [-e] [-f[f[f]]] [-r[r]] [-a|-s name] dbpath\n"
" -V\t\tprint version and exit\n" " -V\t\tprint version and exit\n"
@ -87,6 +87,11 @@ static int reader_list_func(void *ctx, int num, int slot, mdbx_pid_t pid,
return user_break ? MDBX_RESULT_TRUE : MDBX_RESULT_FALSE; return user_break ? MDBX_RESULT_TRUE : MDBX_RESULT_FALSE;
} }
const char *prog;
static void error(const char *func, int rc) {
fprintf(stderr, "%s: %s() error %d %s\n", prog, func, rc, mdbx_strerror(rc));
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int o, rc; int o, rc;
MDBX_env *env; MDBX_env *env;
@ -94,9 +99,9 @@ int main(int argc, char *argv[]) {
MDBX_dbi dbi; MDBX_dbi dbi;
MDBX_stat mst; MDBX_stat mst;
MDBX_envinfo mei; MDBX_envinfo mei;
char *prog = argv[0]; prog = argv[0];
char *envname; char *envname;
char *subname = NULL; char *subname = nullptr;
int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0; int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0;
if (argc < 2) if (argc < 2)
@ -166,41 +171,51 @@ int main(int argc, char *argv[]) {
printf("mdbx_stat %s (%s, T-%s)\nRunning for %s...\n", printf("mdbx_stat %s (%s, T-%s)\nRunning for %s...\n",
mdbx_version.git.describe, mdbx_version.git.datetime, mdbx_version.git.describe, mdbx_version.git.datetime,
mdbx_version.git.tree, envname); mdbx_version.git.tree, envname);
fflush(NULL); fflush(nullptr);
rc = mdbx_env_create(&env); rc = mdbx_env_create(&env);
if (rc) { if (unlikely(rc != MDBX_SUCCESS)) {
fprintf(stderr, "mdbx_env_create failed, error %d %s\n", rc, error("mdbx_env_create", rc);
mdbx_strerror(rc));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (alldbs || subname) if (alldbs || subname) {
mdbx_env_set_maxdbs(env, 4); rc = mdbx_env_set_maxdbs(env, 2);
if (unlikely(rc != MDBX_SUCCESS)) {
error("mdbx_env_set_maxdbs", rc);
goto env_close;
}
}
rc = mdbx_env_open(env, envname, envflags | MDBX_RDONLY, 0664); rc = mdbx_env_open(env, envname, envflags | MDBX_RDONLY, 0664);
if (rc) { if (unlikely(rc != MDBX_SUCCESS)) {
fprintf(stderr, "mdbx_env_open failed, error %d %s\n", rc, error("mdbx_env_open", rc);
mdbx_strerror(rc));
goto env_close; goto env_close;
} }
rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn); rc = mdbx_txn_begin(env, nullptr, MDBX_RDONLY, &txn);
if (rc) { if (unlikely(rc != MDBX_SUCCESS)) {
fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc, error("mdbx_txn_begin", rc);
mdbx_strerror(rc)); goto txn_abort;
goto env_close;
} }
if (envinfo || freinfo) { if (envinfo || freinfo) {
(void)mdbx_env_info_ex(env, txn, &mei, sizeof(mei)); rc = mdbx_env_info_ex(env, txn, &mei, sizeof(mei));
if (unlikely(rc != MDBX_SUCCESS)) {
error("mdbx_env_info_ex", rc);
goto txn_abort;
}
} else { } else {
/* LY: zap warnings from gcc */ /* LY: zap warnings from gcc */
memset(&mei, 0, sizeof(mei)); memset(&mei, 0, sizeof(mei));
} }
if (envinfo) { if (envinfo) {
(void)mdbx_env_stat_ex(env, txn, &mst, sizeof(mst)); rc = mdbx_env_stat_ex(env, txn, &mst, sizeof(mst));
if (unlikely(rc != MDBX_SUCCESS)) {
error("mdbx_env_stat_ex", rc);
goto txn_abort;
}
printf("Environment Info\n"); printf("Environment Info\n");
printf(" Pagesize: %u\n", mst.ms_psize); printf(" Pagesize: %u\n", mst.ms_psize);
if (mei.mi_geo.lower != mei.mi_geo.upper) { if (mei.mi_geo.lower != mei.mi_geo.upper) {
@ -240,11 +255,19 @@ int main(int argc, char *argv[]) {
if (rdrinfo) { if (rdrinfo) {
rc = mdbx_reader_list(env, reader_list_func, nullptr); rc = mdbx_reader_list(env, reader_list_func, nullptr);
if (MDBX_IS_ERROR(rc)) {
error("mdbx_reader_list", rc);
goto txn_abort;
}
if (rc == MDBX_RESULT_TRUE) if (rc == MDBX_RESULT_TRUE)
printf("Reader Table is empty\n"); printf("Reader Table is empty\n");
else if (rc == MDBX_SUCCESS && rdrinfo > 1) { else if (rc == MDBX_SUCCESS && rdrinfo > 1) {
int dead; int dead;
rc = mdbx_reader_check(env, &dead); rc = mdbx_reader_check(env, &dead);
if (MDBX_IS_ERROR(rc)) {
error("mdbx_reader_check", rc);
goto txn_abort;
}
if (rc == MDBX_RESULT_TRUE) { if (rc == MDBX_RESULT_TRUE) {
printf(" %d stale readers cleared.\n", dead); printf(" %d stale readers cleared.\n", dead);
rc = mdbx_reader_list(env, reader_list_func, nullptr); rc = mdbx_reader_list(env, reader_list_func, nullptr);
@ -253,38 +276,31 @@ int main(int argc, char *argv[]) {
} else } else
printf(" No stale readers.\n"); printf(" No stale readers.\n");
} }
if (MDBX_IS_ERROR(rc)) {
fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc,
mdbx_strerror(rc));
goto env_close;
}
if (!(subname || alldbs || freinfo)) if (!(subname || alldbs || freinfo))
goto env_close; goto txn_abort;
} }
if (freinfo) { if (freinfo) {
MDBX_cursor *cursor;
MDBX_val key, data;
pgno_t pages = 0, *iptr;
pgno_t reclaimable = 0;
printf("Garbage Collection\n"); printf("Garbage Collection\n");
dbi = 0; dbi = 0;
MDBX_cursor *cursor;
rc = mdbx_cursor_open(txn, dbi, &cursor); rc = mdbx_cursor_open(txn, dbi, &cursor);
if (rc) { if (unlikely(rc != MDBX_SUCCESS)) {
fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc, error("mdbx_cursor_open", rc);
mdbx_strerror(rc));
goto txn_abort; goto txn_abort;
} }
rc = mdbx_dbi_stat(txn, dbi, &mst, sizeof(mst)); rc = mdbx_dbi_stat(txn, dbi, &mst, sizeof(mst));
if (rc) { if (unlikely(rc != MDBX_SUCCESS)) {
fprintf(stderr, "mdbx_dbi_stat failed, error %d %s\n", rc, error("mdbx_dbi_stat", rc);
mdbx_strerror(rc));
goto txn_abort; goto txn_abort;
} }
prstat(&mst); print_stat(&mst);
while ((rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT)) ==
MDBX_SUCCESS) { pgno_t pages = 0, *iptr;
pgno_t reclaimable = 0;
MDBX_val key, data;
while (MDBX_SUCCESS ==
(rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT))) {
if (user_break) { if (user_break) {
rc = MDBX_EINTR; rc = MDBX_EINTR;
break; break;
@ -332,6 +348,7 @@ int main(int argc, char *argv[]) {
} }
} }
mdbx_cursor_close(cursor); mdbx_cursor_close(cursor);
cursor = nullptr;
switch (rc) { switch (rc) {
case MDBX_SUCCESS: case MDBX_SUCCESS:
@ -341,8 +358,7 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "Interrupted by signal/user\n"); fprintf(stderr, "Interrupted by signal/user\n");
goto txn_abort; goto txn_abort;
default: default:
fprintf(stderr, "mdbx_cursor_get failed, error %d %s\n", rc, error("mdbx_cursor_get", rc);
mdbx_strerror(rc));
goto txn_abort; goto txn_abort;
} }
@ -381,58 +397,74 @@ int main(int argc, char *argv[]) {
} }
rc = mdbx_dbi_open(txn, subname, 0, &dbi); rc = mdbx_dbi_open(txn, subname, 0, &dbi);
if (rc) { if (unlikely(rc != MDBX_SUCCESS)) {
fprintf(stderr, "mdbx_open failed, error %d %s\n", rc, mdbx_strerror(rc)); error("mdbx_dbi_open", rc);
goto txn_abort; goto txn_abort;
} }
rc = mdbx_dbi_stat(txn, dbi, &mst, sizeof(mst)); rc = mdbx_dbi_stat(txn, dbi, &mst, sizeof(mst));
if (rc) { if (unlikely(rc != MDBX_SUCCESS)) {
fprintf(stderr, "mdbx_dbi_stat failed, error %d %s\n", rc, error("mdbx_dbi_stat", rc);
mdbx_strerror(rc));
goto txn_abort; goto txn_abort;
} }
printf("Status of %s\n", subname ? subname : "Main DB"); printf("Status of %s\n", subname ? subname : "Main DB");
prstat(&mst); print_stat(&mst);
if (alldbs) { if (alldbs) {
MDBX_cursor *cursor; MDBX_cursor *cursor;
MDBX_val key;
rc = mdbx_cursor_open(txn, dbi, &cursor); rc = mdbx_cursor_open(txn, dbi, &cursor);
if (rc) { if (unlikely(rc != MDBX_SUCCESS)) {
fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc, error("mdbx_cursor_open", rc);
mdbx_strerror(rc));
goto txn_abort; goto txn_abort;
} }
while ((rc = mdbx_cursor_get(cursor, &key, NULL, MDBX_NEXT_NODUP)) == 0) {
char *str; MDBX_val key;
MDBX_dbi db2; while (MDBX_SUCCESS ==
(rc = mdbx_cursor_get(cursor, &key, nullptr, MDBX_NEXT_NODUP))) {
MDBX_dbi subdbi;
if (memchr(key.iov_base, '\0', key.iov_len)) if (memchr(key.iov_base, '\0', key.iov_len))
continue; continue;
str = mdbx_malloc(key.iov_len + 1); subname = mdbx_malloc(key.iov_len + 1);
memcpy(str, key.iov_base, key.iov_len); memcpy(subname, key.iov_base, key.iov_len);
str[key.iov_len] = '\0'; subname[key.iov_len] = '\0';
rc = mdbx_dbi_open(txn, str, 0, &db2); rc = mdbx_dbi_open(txn, subname, 0, &subdbi);
if (rc == MDBX_SUCCESS) if (rc == MDBX_SUCCESS)
printf("Status of %s\n", str); printf("Status of %s\n", subname);
mdbx_free(str); mdbx_free(subname);
if (rc) if (unlikely(rc != MDBX_SUCCESS)) {
continue; if (rc == MDBX_INCOMPATIBLE)
rc = mdbx_dbi_stat(txn, db2, &mst, sizeof(mst)); continue;
if (rc) { error("mdbx_dbi_open", rc);
fprintf(stderr, "mdbx_dbi_stat failed, error %d %s\n", rc, goto txn_abort;
mdbx_strerror(rc)); }
rc = mdbx_dbi_stat(txn, subdbi, &mst, sizeof(mst));
if (unlikely(rc != MDBX_SUCCESS)) {
error("mdbx_dbi_stat", rc);
goto txn_abort;
}
print_stat(&mst);
rc = mdbx_dbi_close(env, subdbi);
if (unlikely(rc != MDBX_SUCCESS)) {
error("mdbx_dbi_close", rc);
goto txn_abort; goto txn_abort;
} }
prstat(&mst);
mdbx_dbi_close(env, db2);
} }
mdbx_cursor_close(cursor); mdbx_cursor_close(cursor);
cursor = nullptr;
} }
if (rc == MDBX_NOTFOUND) switch (rc) {
rc = MDBX_SUCCESS; case MDBX_SUCCESS:
case MDBX_NOTFOUND:
break;
case MDBX_EINTR:
fprintf(stderr, "Interrupted by signal/user\n");
break;
default:
if (unlikely(rc != MDBX_SUCCESS))
error("mdbx_cursor_get", rc);
}
mdbx_dbi_close(env, dbi); mdbx_dbi_close(env, dbi);
txn_abort: txn_abort: