00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024 #include <xapian/error.h>
00025 #include "btree.h"
00026 #include "bcursor.h"
00027 #include "quartz_types.h"
00028 #include <iostream>
00029 #include <vector>
00030 #include <string>
00031 #include <ctype.h>
00032
00033 #include "autoptr.h"
00034 #include "gnu_getopt.h"
00035
00036 using namespace std;
00037
00038 #define PROG_NAME "quartzdump"
00039 #define PROG_DESC "Dump a quartz table for debugging purposes"
00040
00041 #define OPT_HELP 1
00042 #define OPT_VERSION 2
00043
00044 static void show_usage() {
00045 cout << "Usage: "PROG_NAME" [OPTIONS] TABLE...\n\n"
00046 "Options:\n"
00047 " -r, --revision=REVNO Revision number to open (default: highest)\n"
00048 " -s, --start-key=START Start at key START\n"
00049 " -e, --end-key=END End at key END\n"
00050 " --help display this help and exit\n"
00051 " --version output version information and exit" << endl;
00052 }
00053
00054 static string hex_encode(const string & input) {
00055 const char * table = "0123456789abcdef";
00056 string result;
00057 for (string::const_iterator i = input.begin(); i != input.end(); ++i) {
00058 unsigned char val = *i;
00059 if (isprint(val)) {
00060 if (val == ' ' || val == '\\') result += '\\';
00061 result += val;
00062 } else {
00063 result += "\\x";
00064 result += table[val >> 4];
00065 result += table[val & 0x0f];
00066 }
00067 }
00068
00069 return result;
00070 }
00071
00072 int
00073 main(int argc, char *argv[])
00074 {
00075 vector<string> tables;
00076 quartz_revision_number_t revnum = 0;
00077 bool use_revno = false;
00078 string startkey;
00079 string endkey;
00080 bool use_endkey = false;
00081
00082 bool syntax_error = false;
00083
00084 const struct option long_opts[] = {
00085 {"revision", required_argument, 0, 'r'},
00086 {"start-key", required_argument, 0, 's'},
00087 {"end-key", required_argument, 0, 'e'},
00088 {"help", no_argument, 0, OPT_HELP},
00089 {"version", no_argument, 0, OPT_VERSION},
00090 {NULL, 0, 0, 0}
00091 };
00092
00093 int c;
00094 while ((c = gnu_getopt_long(argc, argv, "r:s:e:", long_opts, 0)) == 0) {
00095 switch (c) {
00096 case 'r':
00097 revnum = atoi(optarg);
00098 use_revno = true;
00099 break;
00100 case 's':
00101 startkey = optarg;
00102 break;
00103 case 'e':
00104 endkey = optarg;
00105 use_endkey = true;
00106 break;
00107 case OPT_HELP:
00108 cout << PROG_NAME" - "PROG_DESC"\n\n";
00109 show_usage();
00110 exit(0);
00111 case OPT_VERSION:
00112 cout << PROG_NAME" - "PACKAGE_STRING << endl;
00113 exit(0);
00114 default:
00115 syntax_error = true;
00116 break;
00117 }
00118 }
00119
00120 while (argv[optind]) {
00121 tables.push_back(argv[optind++]);
00122 }
00123
00124 if (syntax_error || tables.empty()) {
00125 show_usage();
00126 exit(1);
00127 }
00128
00129 vector<string>::const_iterator i;
00130 for (i = tables.begin(); i != tables.end(); i++) {
00131 try {
00132 Btree table(*i, true);
00133 if (use_revno) {
00134 table.open(revnum);
00135 } else {
00136 table.open();
00137 }
00138
00139 quartz_revision_number_t openrev = table.get_open_revision_number();
00140 quartz_revision_number_t latestrev = table.get_latest_revision_number();
00141
00142 quartz_tablesize_t entrycount = table.get_entry_count();
00143
00144 cout << "Table `" << *i << "' at revision " << openrev;
00145 if (openrev != latestrev)
00146 cout << " (Newest revision is " << latestrev << ")";
00147 cout << endl;
00148
00149 cout << "table contains " << entrycount <<
00150 (entrycount == 1 ? " entry" : " entries") << endl;
00151
00152 AutoPtr<Bcursor> cursor(table.cursor_get());
00153
00154 string key = startkey;
00155 cursor->find_entry(key);
00156
00157 if (startkey.empty() || cursor->current_key < startkey) {
00158 cursor->next();
00159 }
00160
00161 while (!cursor->after_end()) {
00162 if (use_endkey && cursor->current_key > endkey) break;
00163 cursor->read_tag();
00164 cout << hex_encode(cursor->current_key) << " -> "
00165 << hex_encode(cursor->current_tag) << "\n";
00166 cursor->next();
00167 }
00168 } catch (const Xapian::Error &e) {
00169 cerr << "Error: " << e.get_description() << endl;
00170 return 1;
00171 }
00172 }
00173 }