examples/copydatabase.cc

Go to the documentation of this file.
00001 
00004 /* Copyright (C) 2006,2007,2008 Olly Betts
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00019  */
00020 
00021 #include <config.h>
00022 
00023 #include <xapian.h>
00024 
00025 #include <iomanip>
00026 #include <iostream>
00027 
00028 #include <cmath> // For log10().
00029 #include <cstdlib> // For exit().
00030 #include <cstring> // For strcmp() and strrchr().
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     // We expect two or more arguments: at least one source database path
00062     // followed by the destination database path.
00063     if (argc < 3) show_usage(1);
00064 
00065     // Create the destination database, using DB_CREATE so that we don't
00066     // try to overwrite or update an existing database in case the user
00067     // got the command line argument order wrong.
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             // Remove any trailing directory separator.
00075             char & ch = src[strlen(src) - 1];
00076             if (ch == '/' || ch == '\\') ch = '\0';
00077         }
00078 
00079         // Open the source database.
00080         Xapian::Database db_in(src);
00081 
00082         // Find the leaf-name of the database path for reporting progress.
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         // Iterate over all the documents in db_in, copying each to db_out.
00090         Xapian::doccount dbsize = db_in.get_doccount();
00091         if (dbsize == 0) {
00092             cout << leaf << ": empty!" << endl;
00093         } else {
00094             // Calculate how many decimal digits there are in dbsize.
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                 // Update for the first 10, and then every 13th document
00103                 // counting back from the end (this means that all the
00104                 // digits "rotate" and the counter ends up on the exact
00105                 // total.
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     // Flush explicitly so that any error is reported.
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 }

Documentation for Xapian (version 1.0.10).
Generated on 24 Dec 2008 by Doxygen 1.5.2.