Branch data Line data Source code
1 : : /** @file backendmanager_multi.cc
2 : : * @brief BackendManager subclass for multi databases.
3 : : */
4 : : /* Copyright (C) 2007,2008,2009 Olly Betts
5 : : * Copyright (C) 2008 Lemur Consulting Ltd
6 : : *
7 : : * This program is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU General Public License as
9 : : * published by the Free Software Foundation; either version 2 of the
10 : : * License, or (at your option) any later version.
11 : : *
12 : : * This program is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : : * GNU General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU General Public License
18 : : * along with this program; if not, write to the Free Software
19 : : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 : : */
21 : :
22 : : #include <config.h>
23 : :
24 : : #include "backendmanager_multi.h"
25 : :
26 : : #include "index_utils.h"
27 : : #include "str.h"
28 : : #include "utils.h"
29 : :
30 : : #include <cstdio> // For rename().
31 : : #include <cstring>
32 : : #include "safeerrno.h"
33 : :
34 : : using namespace std;
35 : :
36 : 3 : BackendManagerMulti::BackendManagerMulti(const std::string & subtype_)
37 : 3 : : subtype(subtype_)
38 : : {
39 [ + + + + ]: 3 : if (!(false
[ - + ]
[ - + # # ]
[ # # ][ # # ]
[ # # ]
40 : : #ifdef XAPIAN_HAS_BRASS_BACKEND
41 : : || subtype == "brass"
42 : : #endif
43 : : #ifdef XAPIAN_HAS_CHERT_BACKEND
44 : : || subtype == "chert"
45 : : #endif
46 : : #ifdef XAPIAN_HAS_FLINT_BACKEND
47 : : || subtype == "flint"
48 : : #endif
49 : : )) {
50 : 0 : throw ("Unknown backend type \"" + subtype + "\" specified for multi database subdatabases");
51 : : }
52 : 3 : }
53 : :
54 : : std::string
55 : 32 : BackendManagerMulti::get_dbtype() const
56 : : {
57 : 32 : return "multi_" + subtype;
58 : : }
59 : :
60 : : #define NUMBER_OF_SUB_DBS 2
61 : :
62 : : string
63 : 475 : BackendManagerMulti::createdb_multi(const vector<string> & files)
64 : : {
65 : 475 : string dbdir = ".multi" + subtype;
66 : 475 : create_dir_if_needed(dbdir);
67 : :
68 : 475 : string dbname = "db";
69 : 475 : vector<string>::const_iterator i;
70 [ + + ]: 959 : for (i = files.begin(); i != files.end(); ++i) {
71 : 484 : dbname += "__";
72 : 484 : dbname += *i;
73 : : }
74 : 475 : string dbpath = dbdir + "/" + dbname;
75 : :
76 [ + + ]: 475 : if (file_exists(dbpath)) return dbpath;
77 : :
78 : 54 : string tmpfile = dbpath;
79 : 54 : tmpfile += ".tmp";
80 : 54 : ofstream out(tmpfile.c_str());
81 [ - + ]: 54 : if (!out.is_open()) {
82 : 0 : string msg = "Couldn't create file '";
83 : 0 : msg += tmpfile;
84 : 0 : msg += "' (";
85 : 0 : msg += strerror(errno);
86 : 0 : msg += ')';
87 : 0 : throw msg;
88 : : }
89 : :
90 : : // Open NUMBER_OF_SUB_DBS databases and index files to the alternately so a
91 : : // multi-db combining them contains the documents in the expected order.
92 [ + + ][ # # ]: 162 : Xapian::WritableDatabase dbs[NUMBER_OF_SUB_DBS];
[ # # ]
93 [ + + ]: 162 : for (size_t n = 0; n < NUMBER_OF_SUB_DBS; ++n) {
94 : 108 : string subdbdir = dbname;
95 : 108 : subdbdir += "___";
96 : 108 : subdbdir += str(n);
97 : : #if defined XAPIAN_HAS_BRASS_BACKEND
98 [ + + ]: 108 : if (subtype == "brass") {
99 : 36 : dbs[n] = Xapian::Brass::open(dbdir + "/" + subdbdir, Xapian::DB_CREATE_OR_OVERWRITE);
100 : 36 : out << "brass " << subdbdir << '\n';
101 : : }
102 : : #endif
103 : : #if defined XAPIAN_HAS_CHERT_BACKEND
104 [ + + ]: 108 : if (subtype == "chert") {
105 : 36 : dbs[n] = Xapian::Chert::open(dbdir + "/" + subdbdir, Xapian::DB_CREATE_OR_OVERWRITE);
106 : 36 : out << "chert " << subdbdir << '\n';
107 : : }
108 : : #endif
109 : : #ifdef XAPIAN_HAS_FLINT_BACKEND
110 [ + + ]: 108 : if (subtype == "flint") {
111 : 36 : dbs[n] = Xapian::Flint::open(dbdir + "/" + subdbdir, Xapian::DB_CREATE_OR_OVERWRITE);
112 : 36 : out << "flint " << subdbdir << '\n';
113 : : }
114 : : #endif
115 : :
116 : : }
117 : 54 : out.close();
118 : :
119 : 54 : size_t c = 0;
120 : 54 : FileIndexer f(get_datadir(), files);
121 [ + + ]: 5532 : while (f) {
122 : 5478 : dbs[c].add_document(f.next());
123 : 5478 : c = (c + 1) % NUMBER_OF_SUB_DBS;
124 : : }
125 : :
126 : 54 : rename(tmpfile.c_str(), dbpath.c_str());
127 : :
128 [ # # ][ + + ]: 583 : return dbpath;
129 : : }
130 : :
131 : : string
132 : 475 : BackendManagerMulti::do_get_database_path(const vector<string> & files)
133 : : {
134 : 475 : return createdb_multi(files);
135 : : }
136 : :
137 : : Xapian::WritableDatabase
138 : 0 : BackendManagerMulti::get_writable_database(const string &, const string &)
139 : : {
140 : 0 : throw Xapian::UnimplementedError("Multi-databases don't support writing");
141 : : }
|