0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <stdio.h>
0015 #include <stdlib.h>
0016 #include <string.h>
0017 #include <unistd.h>
0018 #include "exdb.h"
0019
0020 #define Z EDB_FMT_Z
0021 #define Yu EDB_PRIy(u)
0022
0023 static void prstat(EDB_stat *ms)
0024 {
0025 #if 0
0026 printf(" Page size: %u\n", ms->ms_psize);
0027 #endif
0028 printf(" Tree depth: %u\n", ms->ms_depth);
0029 printf(" Branch pages: %"Yu"\n", ms->ms_branch_pages);
0030 printf(" Leaf pages: %"Yu"\n", ms->ms_leaf_pages);
0031 printf(" Overflow pages: %"Yu"\n", ms->ms_overflow_pages);
0032 printf(" Entries: %"Yu"\n", ms->ms_entries);
0033 }
0034
0035 static void usage(char *prog)
0036 {
0037 fprintf(stderr, "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-v] [-a|-s subdb] dbpath\n", prog);
0038 exit(EXIT_FAILURE);
0039 }
0040
0041 int main(int argc, char *argv[])
0042 {
0043 int i, rc;
0044 EDB_env *env;
0045 EDB_txn *txn;
0046 EDB_dbi dbi;
0047 EDB_stat mst;
0048 EDB_envinfo mei;
0049 char *prog = argv[0];
0050 char *envname;
0051 char *subname = NULL;
0052 int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0;
0053
0054 if (argc < 2) {
0055 usage(prog);
0056 }
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 while ((i = getopt(argc, argv, "Vaefnrs:v")) != EOF) {
0069 switch(i) {
0070 case 'V':
0071 printf("%s\n", EDB_VERSION_STRING);
0072 exit(0);
0073 break;
0074 case 'a':
0075 if (subname)
0076 usage(prog);
0077 alldbs++;
0078 break;
0079 case 'e':
0080 envinfo++;
0081 break;
0082 case 'f':
0083 freinfo++;
0084 break;
0085 case 'n':
0086 envflags |= EDB_NOSUBDIR;
0087 break;
0088 case 'v':
0089 envflags |= EDB_PREVSNAPSHOT;
0090 break;
0091 case 'r':
0092 rdrinfo++;
0093 break;
0094 case 's':
0095 if (alldbs)
0096 usage(prog);
0097 subname = optarg;
0098 break;
0099 default:
0100 usage(prog);
0101 }
0102 }
0103
0104 if (optind != argc - 1)
0105 usage(prog);
0106
0107 envname = argv[optind];
0108 rc = edb_env_create(&env);
0109 if (rc) {
0110 fprintf(stderr, "edb_env_create failed, error %d %s\n", rc, edb_strerror(rc));
0111 return EXIT_FAILURE;
0112 }
0113
0114 if (alldbs || subname) {
0115 edb_env_set_maxdbs(env, 4);
0116 }
0117
0118 rc = edb_env_open(env, envname, envflags | EDB_RDONLY, 0664);
0119 if (rc) {
0120 fprintf(stderr, "edb_env_open failed, error %d %s\n", rc, edb_strerror(rc));
0121 goto env_close;
0122 }
0123
0124 if (envinfo) {
0125 (void)edb_env_stat(env, &mst);
0126 (void)edb_env_info(env, &mei);
0127 printf("Environment Info\n");
0128 printf(" Map address: %p\n", mei.me_mapaddr);
0129 printf(" Map size: %"Yu"\n", mei.me_mapsize);
0130 printf(" Page size: %u\n", mst.ms_psize);
0131 printf(" Max pages: %"Yu"\n", mei.me_mapsize / mst.ms_psize);
0132 printf(" Number of pages used: %"Yu"\n", mei.me_last_pgno+1);
0133 printf(" Last transaction ID: %"Yu"\n", mei.me_last_txnid);
0134 printf(" Max readers: %u\n", mei.me_maxreaders);
0135 printf(" Number of readers used: %u\n", mei.me_numreaders);
0136 }
0137
0138 if (rdrinfo) {
0139 printf("Reader Table Status\n");
0140 rc = edb_reader_list(env, (EDB_msg_func *)fputs, stdout);
0141 if (rdrinfo > 1) {
0142 int dead;
0143 edb_reader_check(env, &dead);
0144 printf(" %d stale readers cleared.\n", dead);
0145 rc = edb_reader_list(env, (EDB_msg_func *)fputs, stdout);
0146 }
0147 if (!(subname || alldbs || freinfo))
0148 goto env_close;
0149 }
0150
0151 rc = edb_txn_begin(env, NULL, EDB_RDONLY, &txn);
0152 if (rc) {
0153 fprintf(stderr, "edb_txn_begin failed, error %d %s\n", rc, edb_strerror(rc));
0154 goto env_close;
0155 }
0156
0157 if (freinfo) {
0158 EDB_cursor *cursor;
0159 EDB_val key, data;
0160 edb_size_t pages = 0, *iptr;
0161
0162 printf("Freelist Status\n");
0163 dbi = 0;
0164 rc = edb_cursor_open(txn, dbi, &cursor);
0165 if (rc) {
0166 fprintf(stderr, "edb_cursor_open failed, error %d %s\n", rc, edb_strerror(rc));
0167 goto txn_abort;
0168 }
0169 rc = edb_stat(txn, dbi, &mst);
0170 if (rc) {
0171 fprintf(stderr, "edb_stat failed, error %d %s\n", rc, edb_strerror(rc));
0172 goto txn_abort;
0173 }
0174 prstat(&mst);
0175 while ((rc = edb_cursor_get(cursor, &key, &data, EDB_NEXT)) == 0) {
0176 iptr = data.mv_data;
0177 pages += *iptr;
0178 if (freinfo > 1) {
0179 char *bad = "";
0180 edb_size_t pg, prev;
0181 ssize_t i, j, span = 0;
0182 j = *iptr++;
0183 for (i = j, prev = 1; --i >= 0; ) {
0184 pg = iptr[i];
0185 if (pg <= prev)
0186 bad = " [bad sequence]";
0187 prev = pg;
0188 pg += span;
0189 for (; i >= span && iptr[i-span] == pg; span++, pg++) ;
0190 }
0191 printf(" Transaction %"Yu", %"Z"d pages, maxspan %"Z"d%s\n",
0192 *(edb_size_t *)key.mv_data, j, span, bad);
0193 if (freinfo > 2) {
0194 for (--j; j >= 0; ) {
0195 pg = iptr[j];
0196 for (span=1; --j >= 0 && iptr[j] == pg+span; span++) ;
0197 printf(span>1 ? " %9"Yu"[%"Z"d]\n" : " %9"Yu"\n",
0198 pg, span);
0199 }
0200 }
0201 }
0202 }
0203 edb_cursor_close(cursor);
0204 printf(" Free pages: %"Yu"\n", pages);
0205 }
0206
0207 rc = edb_open(txn, subname, 0, &dbi);
0208 if (rc) {
0209 fprintf(stderr, "edb_open failed, error %d %s\n", rc, edb_strerror(rc));
0210 goto txn_abort;
0211 }
0212
0213 rc = edb_stat(txn, dbi, &mst);
0214 if (rc) {
0215 fprintf(stderr, "edb_stat failed, error %d %s\n", rc, edb_strerror(rc));
0216 goto txn_abort;
0217 }
0218 printf("Status of %s\n", subname ? subname : "Main DB");
0219 prstat(&mst);
0220
0221 if (alldbs) {
0222 EDB_cursor *cursor;
0223 EDB_val key;
0224
0225 rc = edb_cursor_open(txn, dbi, &cursor);
0226 if (rc) {
0227 fprintf(stderr, "edb_cursor_open failed, error %d %s\n", rc, edb_strerror(rc));
0228 goto txn_abort;
0229 }
0230 while ((rc = edb_cursor_get(cursor, &key, NULL, EDB_NEXT_NODUP)) == 0) {
0231 char *str;
0232 EDB_dbi db2;
0233 if (memchr(key.mv_data, '\0', key.mv_size))
0234 continue;
0235 str = malloc(key.mv_size+1);
0236 memcpy(str, key.mv_data, key.mv_size);
0237 str[key.mv_size] = '\0';
0238 rc = edb_open(txn, str, 0, &db2);
0239 if (rc == EDB_SUCCESS)
0240 printf("Status of %s\n", str);
0241 free(str);
0242 if (rc) continue;
0243 rc = edb_stat(txn, db2, &mst);
0244 if (rc) {
0245 fprintf(stderr, "edb_stat failed, error %d %s\n", rc, edb_strerror(rc));
0246 goto txn_abort;
0247 }
0248 prstat(&mst);
0249 edb_close(env, db2);
0250 }
0251 edb_cursor_close(cursor);
0252 }
0253
0254 if (rc == EDB_NOTFOUND)
0255 rc = EDB_SUCCESS;
0256
0257 edb_close(env, dbi);
0258 txn_abort:
0259 edb_txn_abort(txn);
0260 env_close:
0261 edb_env_close(env);
0262
0263 return rc ? EXIT_FAILURE : EXIT_SUCCESS;
0264 }