X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Fliblmdb%2Fmdb_stat.c;h=f4c0dc1ea730d59530a1da77c5b5e31230a367d3;hb=385193cd520c3b238fe9048d47e8abf8383386bc;hp=e9981f60161416bd71f781efaa973079e7620b2c;hpb=784757faa91b4570465e7fc6453305324e686a0a;p=openldap diff --git a/libraries/liblmdb/mdb_stat.c b/libraries/liblmdb/mdb_stat.c index e9981f6016..f4c0dc1ea7 100644 --- a/libraries/liblmdb/mdb_stat.c +++ b/libraries/liblmdb/mdb_stat.c @@ -1,6 +1,6 @@ /* mdb_stat.c - memory-mapped database status tool */ /* - * Copyright 2011 Howard Chu, Symas Corp. + * Copyright 2011-2018 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -17,21 +17,27 @@ #include #include "lmdb.h" +#ifdef _WIN32 +#define Z "I" +#else +#define Z "z" +#endif + static void prstat(MDB_stat *ms) { #if 0 printf(" Page size: %u\n", ms->ms_psize); #endif printf(" Tree depth: %u\n", ms->ms_depth); - printf(" Branch pages: %zu\n", ms->ms_branch_pages); - printf(" Leaf pages: %zu\n", ms->ms_leaf_pages); - printf(" Overflow pages: %zu\n", ms->ms_overflow_pages); - printf(" Entries: %zu\n", ms->ms_entries); + printf(" Branch pages: %"Z"u\n", ms->ms_branch_pages); + printf(" Leaf pages: %"Z"u\n", ms->ms_leaf_pages); + printf(" Overflow pages: %"Z"u\n", ms->ms_overflow_pages); + printf(" Entries: %"Z"u\n", ms->ms_entries); } static void usage(char *prog) { - fprintf(stderr, "usage: %s dbpath [-e] [-f] [-n] [-a|-s subdb]\n", prog); + fprintf(stderr, "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-a|-s subdb] dbpath\n", prog); exit(EXIT_FAILURE); } @@ -46,7 +52,7 @@ int main(int argc, char *argv[]) char *prog = argv[0]; char *envname; char *subname = NULL; - int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0; + int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0; if (argc < 2) { usage(prog); @@ -56,11 +62,17 @@ int main(int argc, char *argv[]) * -s: print stat of only the named subDB * -e: print env info * -f: print freelist info + * -r: print reader info * -n: use NOSUBDIR flag on env_open + * -V: print version and exit * (default) print stat of only the main DB */ - while ((i = getopt(argc, argv, "aefns:")) != EOF) { + while ((i = getopt(argc, argv, "Vaefnrs:")) != EOF) { switch(i) { + case 'V': + printf("%s\n", MDB_VERSION_STRING); + exit(0); + break; case 'a': if (subname) usage(prog); @@ -75,6 +87,9 @@ int main(int argc, char *argv[]) case 'n': envflags |= MDB_NOSUBDIR; break; + case 'r': + rdrinfo++; + break; case 's': if (alldbs) usage(prog); @@ -90,6 +105,10 @@ int main(int argc, char *argv[]) envname = argv[optind]; rc = mdb_env_create(&env); + if (rc) { + fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc)); + return EXIT_FAILURE; + } if (alldbs || subname) { mdb_env_set_maxdbs(env, 4); @@ -97,64 +116,102 @@ int main(int argc, char *argv[]) rc = mdb_env_open(env, envname, envflags | MDB_RDONLY, 0664); if (rc) { - printf("mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc)); - goto env_close; - } - rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); - if (rc) { - printf("mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); + fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } if (envinfo) { - rc = mdb_env_stat(env, &mst); - rc = mdb_env_info(env, &mei); + (void)mdb_env_stat(env, &mst); + (void)mdb_env_info(env, &mei); printf("Environment Info\n"); printf(" Map address: %p\n", mei.me_mapaddr); - printf(" Map size: %zu\n", mei.me_mapsize); + printf(" Map size: %"Z"u\n", mei.me_mapsize); printf(" Page size: %u\n", mst.ms_psize); - printf(" Max pages: %zu\n", mei.me_mapsize / mst.ms_psize); - printf(" Number of pages used: %zu\n", mei.me_last_pgno+1); - printf(" Last transaction ID: %zu\n", mei.me_last_txnid); + printf(" Max pages: %"Z"u\n", mei.me_mapsize / mst.ms_psize); + printf(" Number of pages used: %"Z"u\n", mei.me_last_pgno+1); + printf(" Last transaction ID: %"Z"u\n", mei.me_last_txnid); printf(" Max readers: %u\n", mei.me_maxreaders); printf(" Number of readers used: %u\n", mei.me_numreaders); } + if (rdrinfo) { + printf("Reader Table Status\n"); + rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout); + if (rdrinfo > 1) { + int dead; + mdb_reader_check(env, &dead); + printf(" %d stale readers cleared.\n", dead); + rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout); + } + if (!(subname || alldbs || freinfo)) + goto env_close; + } + + rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); + if (rc) { + fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); + goto env_close; + } + if (freinfo) { MDB_cursor *cursor; - MDB_val data; + MDB_val key, data; size_t pages = 0, *iptr; printf("Freelist Status\n"); dbi = 0; rc = mdb_cursor_open(txn, dbi, &cursor); if (rc) { - printf("mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); + fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } rc = mdb_stat(txn, dbi, &mst); if (rc) { - printf("mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); + fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } - while ((rc = mdb_cursor_get(cursor, NULL, &data, MDB_NEXT)) == 0) { + prstat(&mst); + while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { iptr = data.mv_data; pages += *iptr; + if (freinfo > 1) { + char *bad = ""; + size_t pg, prev; + ssize_t i, j, span = 0; + j = *iptr++; + for (i = j, prev = 1; --i >= 0; ) { + pg = iptr[i]; + if (pg <= prev) + bad = " [bad sequence]"; + prev = pg; + pg += span; + for (; i >= span && iptr[i-span] == pg; span++, pg++) ; + } + printf(" Transaction %"Z"u, %"Z"d pages, maxspan %"Z"d%s\n", + *(size_t *)key.mv_data, j, span, bad); + if (freinfo > 2) { + for (--j; j >= 0; ) { + pg = iptr[j]; + for (span=1; --j >= 0 && iptr[j] == pg+span; span++) ; + printf(span>1 ? " %9"Z"u[%"Z"d]\n" : " %9"Z"u\n", + pg, span); + } + } + } } mdb_cursor_close(cursor); - prstat(&mst); - printf(" Free pages: %zu\n", pages); + printf(" Free pages: %"Z"u\n", pages); } rc = mdb_open(txn, subname, 0, &dbi); if (rc) { - printf("mdb_open failed, error %d %s\n", rc, mdb_strerror(rc)); + fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } - + rc = mdb_stat(txn, dbi, &mst); if (rc) { - printf("mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); + fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } printf("Status of %s\n", subname ? subname : "Main DB"); @@ -166,12 +223,15 @@ int main(int argc, char *argv[]) rc = mdb_cursor_open(txn, dbi, &cursor); if (rc) { - printf("mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); + fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } - while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT)) == 0) { - char *str = malloc(key.mv_size+1); + while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT_NODUP)) == 0) { + char *str; MDB_dbi db2; + if (memchr(key.mv_data, '\0', key.mv_size)) + continue; + str = malloc(key.mv_size+1); memcpy(str, key.mv_data, key.mv_size); str[key.mv_size] = '\0'; rc = mdb_open(txn, str, 0, &db2); @@ -181,7 +241,7 @@ int main(int argc, char *argv[]) if (rc) continue; rc = mdb_stat(txn, db2, &mst); if (rc) { - printf("mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); + fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } prstat(&mst); @@ -190,6 +250,9 @@ int main(int argc, char *argv[]) mdb_cursor_close(cursor); } + if (rc == MDB_NOTFOUND) + rc = MDB_SUCCESS; + mdb_close(env, dbi); txn_abort: mdb_txn_abort(txn);