00001
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include <xapian.h>
00024
00025 #include <iomanip>
00026 #include <iostream>
00027
00028 #include <cmath>
00029 #include <cstdlib>
00030 #include <cstring>
00031
00032 using namespace std;
00033
00034 #define PROG_NAME "copydatabase"
00035 #define PROG_DESC "Perform a document-by-document copy of one or more Xapian databases"
00036
00037 static void
00038 show_usage(int rc)
00039 {
00040 cout << "Usage: "PROG_NAME" SOURCE_DATABASE... DESTINATION_DATABASE\n\n"
00041 "Options:\n"
00042 " --help display this help and exit\n"
00043 " --version output version information and exit" << endl;
00044 exit(rc);
00045 }
00046
00047 int
00048 main(int argc, char **argv)
00049 try {
00050 if (argc > 1 && argv[1][0] == '-') {
00051 if (strcmp(argv[1], "--help") == 0) {
00052 cout << PROG_NAME" - "PROG_DESC"\n\n";
00053 show_usage(0);
00054 }
00055 if (strcmp(argv[1], "--version") == 0) {
00056 cout << PROG_NAME" - "PACKAGE_STRING << endl;
00057 exit(0);
00058 }
00059 }
00060
00061
00062
00063 if (argc < 3) show_usage(1);
00064
00065
00066
00067
00068 const char *dest = argv[argc - 1];
00069 Xapian::WritableDatabase db_out(dest, Xapian::DB_CREATE);
00070
00071 for (int i = 1; i < argc - 1; ++i) {
00072 char * src = argv[i];
00073 if (*src) {
00074
00075 char & ch = src[strlen(src) - 1];
00076 if (ch == '/' || ch == '\\') ch = '\0';
00077 }
00078
00079
00080 Xapian::Database db_in(src);
00081
00082
00083 const char * leaf = strrchr(src, '/');
00084 #if defined __WIN32__ || defined __EMX__
00085 if (!leaf) leaf = strrchr(src, '\\');
00086 #endif
00087 if (leaf) ++leaf; else leaf = src;
00088
00089
00090 Xapian::doccount dbsize = db_in.get_doccount();
00091 if (dbsize == 0) {
00092 cout << leaf << ": empty!" << endl;
00093 } else {
00094
00095 int width = static_cast<int>(log10(double(dbsize))) + 1;
00096
00097 Xapian::doccount c = 0;
00098 Xapian::PostingIterator it = db_in.postlist_begin("");
00099 while (it != db_in.postlist_end("")) {
00100 db_out.add_document(db_in.get_document(*it));
00101
00102
00103
00104
00105
00106 ++c;
00107 if (c <= 10 || (dbsize - c) % 13 == 0) {
00108 cout << '\r' << leaf << ": ";
00109 cout << setw(width) << c << '/' << dbsize << flush;
00110 }
00111
00112 ++it;
00113 }
00114
00115 cout << endl;
00116 }
00117
00118 cout << "Copying spelling data..." << flush;
00119 Xapian::TermIterator spellword = db_in.spellings_begin();
00120 while (spellword != db_in.spellings_end()) {
00121 db_out.add_spelling(*spellword, spellword.get_termfreq());
00122 ++spellword;
00123 }
00124 cout << " done." << endl;
00125
00126 cout << "Copying synonym data..." << flush;
00127 Xapian::TermIterator synkey = db_in.synonym_keys_begin();
00128 while (synkey != db_in.synonym_keys_end()) {
00129 string key = *synkey;
00130 Xapian::TermIterator syn = db_in.synonyms_begin(key);
00131 while (syn != db_in.synonyms_end(key)) {
00132 db_out.add_synonym(key, *syn);
00133 ++syn;
00134 }
00135 ++synkey;
00136 }
00137 cout << " done." << endl;
00138
00139 cout << "Copying user metadata..." << flush;
00140 Xapian::TermIterator metakey = db_in.metadata_keys_begin();
00141 while (metakey != db_in.metadata_keys_end()) {
00142 string key = *metakey;
00143 db_out.set_metadata(key, db_in.get_metadata(key));
00144 ++metakey;
00145 }
00146 cout << " done." << endl;
00147 }
00148
00149 cout << "Flushing..." << flush;
00150
00151 db_out.flush();
00152 cout << " done." << endl;
00153 } catch (const Xapian::Error & e) {
00154 cerr << '\n' << argv[0] << ": " << e.get_description() << endl;
00155 exit(1);
00156 }