root / tags / 1.0.8 / xapian-core / examples / copydatabase.cc

Revision 11157, 4.4 kB (checked in by olly, 4 months ago)

Backport change from trunk:
examples/copydatabase.cc: Use C++ forms of C headers. Only treat
'\' as a directory separator on platforms where it is. Update
counter every 13 counting up to the end so that the digits all
"rotate" and the counter ends up on the exact total.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/** @file copydatabase.cc
2 * @brief Perform a document-by-document copy of one or more Xapian databases.
3 */
4/* Copyright (C) 2006,2007,2008 Olly Betts
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19 */
20
21#include <config.h>
22
23#include <xapian.h>
24
25#include <iomanip>
26#include <iostream>
27
28#include <cmath> // For log10().
29#include <cstdlib> // For exit().
30#include <cstring> // For strcmp() and strrchr().
31
32using namespace std;
33
34#define PROG_NAME "copydatabase"
35#define PROG_DESC "Perform a document-by-document copy of one or more Xapian databases"
36
37static void
38show_usage(int rc)
39{
40    cout << "Usage: "PROG_NAME" SOURCE_DATABASE... DESTINATION_DATABASE\n\n"
41"Options:\n"
42"  --help           display this help and exit\n"
43"  --version        output version information and exit" << endl;
44    exit(rc);
45}
46
47int
48main(int argc, char **argv)
49try {
50    if (argc > 1 && argv[1][0] == '-') {
51        if (strcmp(argv[1], "--help") == 0) {
52            cout << PROG_NAME" - "PROG_DESC"\n\n";
53            show_usage(0);
54        }
55        if (strcmp(argv[1], "--version") == 0) {
56            cout << PROG_NAME" - "PACKAGE_STRING << endl;
57            exit(0);
58        }
59    }
60
61    // We expect two or more arguments: at least one source database path
62    // followed by the destination database path.
63    if (argc < 3) show_usage(1);
64
65    // Create the destination database, using DB_CREATE so that we don't
66    // try to overwrite or update an existing database in case the user
67    // got the command line argument order wrong.
68    const char *dest = argv[argc - 1];
69    Xapian::WritableDatabase db_out(dest, Xapian::DB_CREATE);
70
71    for (int i = 1; i < argc - 1; ++i) {
72        char * src = argv[i];
73        if (*src) {
74            // Remove any trailing directory separator.
75            char & ch = src[strlen(src) - 1];
76            if (ch == '/' || ch == '\\') ch = '\0';
77        }
78
79        // Open the source database.
80        Xapian::Database db_in(src);
81
82        // Find the leaf-name of the database path for reporting progress.
83        const char * leaf = strrchr(src, '/');
84#if defined __WIN32__ || defined __EMX__
85        if (!leaf) leaf = strrchr(src, '\\');
86#endif
87        if (leaf) ++leaf; else leaf = src;
88
89        // Iterate over all the documents in db_in, copying each to db_out.
90        Xapian::doccount dbsize = db_in.get_doccount();
91        if (dbsize == 0) {
92            cout << leaf << ": empty!" << endl;
93        } else {
94            // Calculate how many decimal digits there are in dbsize.
95            int width = static_cast<int>(log10(double(dbsize))) + 1;
96
97            Xapian::doccount c = 0;
98            Xapian::PostingIterator it = db_in.postlist_begin("");
99            while (it != db_in.postlist_end("")) {
100                db_out.add_document(db_in.get_document(*it));
101
102                // Update for the first 10, and then every 13th document
103                // counting back from the end (this means that all the
104                // digits "rotate" and the counter ends up on the exact
105                // total.
106                ++c;
107                if (c <= 10 || (dbsize - c) % 13 == 0) {
108                    cout << '\r' << leaf << ": ";
109                    cout << setw(width) << c << '/' << dbsize << flush;
110                }
111
112                ++it;
113            }
114
115            cout << endl;
116        }
117
118        cout << "Copying spelling data..." << flush;
119        Xapian::TermIterator spellword = db_in.spellings_begin();
120        while (spellword != db_in.spellings_end()) {
121            db_out.add_spelling(*spellword, spellword.get_termfreq());
122            ++spellword;
123        }
124        cout << " done." << endl;
125
126        cout << "Copying synonym data..." << flush;
127        Xapian::TermIterator synkey = db_in.synonym_keys_begin();
128        while (synkey != db_in.synonym_keys_end()) {
129            string key = *synkey;
130            Xapian::TermIterator syn = db_in.synonyms_begin(key);
131            while (syn != db_in.synonyms_end(key)) {
132                db_out.add_synonym(key, *syn);
133                ++syn;
134            }
135            ++synkey;
136        }
137        cout << " done." << endl;
138    }
139
140    cout << "Flushing..." << flush;
141    // Flush explicitly so that any error is reported.
142    db_out.flush();
143    cout << " done." << endl;
144} catch (const Xapian::Error & e) {
145    cerr << '\n' << argv[0] << ": " << e.get_description() << endl;
146    exit(1);
147}
Note: See TracBrowser for help on using the browser.