Branch data Line data Source code
1 : : /* backendmanager.cc: manage backends for testsuite
2 : : *
3 : : * Copyright 1999,2000,2001 BrightStation PLC
4 : : * Copyright 2002 Ananova Ltd
5 : : * Copyright 2002,2003,2004,2005,2006,2007,2008,2009,2010 Olly Betts
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
20 : : * USA
21 : : */
22 : :
23 : : #include <config.h>
24 : :
25 : : #include <xapian.h>
26 : :
27 : : #ifdef HAVE_VALGRIND
28 : : # include <valgrind/memcheck.h>
29 : : #endif
30 : :
31 : : #include "safeerrno.h"
32 : :
33 : : #include <fstream>
34 : : #include <string>
35 : : #include <vector>
36 : :
37 : : #include <sys/types.h>
38 : : #include "safesysstat.h"
39 : :
40 : : #include "index_utils.h"
41 : : #include "backendmanager.h"
42 : : #include "unixcmds.h"
43 : : #include "utils.h"
44 : :
45 : : using namespace std;
46 : :
47 : : void
48 : 1053 : BackendManager::index_files_to_database(Xapian::WritableDatabase & database,
49 : : const vector<string> & files)
50 : : {
51 : 1053 : FileIndexer f(datadir, files);
52 [ + + ]: 27832 : while (f) database.add_document(f.next());
53 : 1053 : }
54 : :
55 : : /** Create the directory dirname if needed. Returns true if the
56 : : * directory was created and false if it was already there. Throws
57 : : * an exception if there was an error (eg not a directory).
58 : : */
59 : : bool
60 : 5527 : BackendManager::create_dir_if_needed(const string &dirname)
61 : : {
62 : : // create a directory if not present
63 : : struct stat sbuf;
64 : 5527 : int result = stat(dirname, &sbuf);
65 [ + + ]: 5527 : if (result < 0) {
66 [ - + ]: 812 : if (errno != ENOENT)
67 : 0 : throw Xapian::DatabaseOpeningError("Can't stat directory");
68 [ - + ]: 812 : if (mkdir(dirname, 0700) < 0)
69 : 0 : throw Xapian::DatabaseOpeningError("Can't create directory");
70 : 812 : return true; // Successfully created a directory.
71 : : }
72 [ - + ]: 4715 : if (!S_ISDIR(sbuf.st_mode))
73 : 0 : throw Xapian::DatabaseOpeningError("Is not a directory.");
74 : 5527 : return false; // Already a directory.
75 : : }
76 : :
77 : : #ifdef XAPIAN_HAS_INMEMORY_BACKEND
78 : : Xapian::WritableDatabase
79 : 247 : BackendManager::getwritedb_inmemory(const vector<string> &files)
80 : : {
81 : 247 : Xapian::WritableDatabase db(Xapian::InMemory::open());
82 : 247 : index_files_to_database(db, files);
83 : 0 : return db;
84 : : }
85 : : #endif
86 : :
87 : : #ifdef XAPIAN_HAS_BRASS_BACKEND
88 : : string
89 : 568 : BackendManager::createdb_brass(const vector<string> &files)
90 : : {
91 : 568 : string parent_dir = ".brass";
92 : 568 : create_dir_if_needed(parent_dir);
93 : :
94 : 568 : string dbdir = parent_dir + "/db";
95 [ + + ]: 1157 : for (vector<string>::const_iterator i = files.begin();
96 : : i != files.end(); i++) {
97 : 589 : dbdir += '=';
98 : 589 : dbdir += *i;
99 : : }
100 : : // If the database is readonly, we can reuse it if it exists.
101 [ + + ]: 568 : if (create_dir_if_needed(dbdir)) {
102 : : // Directory was created, so do the indexing.
103 : 20 : Xapian::WritableDatabase db(Xapian::Brass::open(dbdir, Xapian::DB_CREATE, 2048));
104 : 20 : index_files_to_database(db, files);
105 : 20 : db.commit();
106 : : }
107 : 568 : return dbdir;
108 : : }
109 : :
110 : : Xapian::WritableDatabase
111 : 252 : BackendManager::getwritedb_brass(const string & name,
112 : : const vector<string> & files)
113 : : {
114 : 252 : string dbdir = getwritedb_brass_path(name);
115 : :
116 : : // For a writable database we need to start afresh each time.
117 : 252 : rm_rf(dbdir);
118 : 252 : (void)create_dir_if_needed(dbdir);
119 : :
120 : : // directory was created, so do the indexing.
121 : 252 : Xapian::WritableDatabase db(Xapian::Brass::open(dbdir, Xapian::DB_CREATE, 2048));
122 : 252 : index_files_to_database(db, files);
123 : 252 : return db;
124 : : }
125 : :
126 : : std::string
127 : 280 : BackendManager::getwritedb_brass_path(const string & name)
128 : : {
129 : 280 : string parent_dir = ".brass";
130 : 280 : create_dir_if_needed(parent_dir);
131 : :
132 : 280 : string dbdir = parent_dir;
133 : 280 : dbdir += '/';
134 : 280 : dbdir += name;
135 : 280 : return dbdir;
136 : : }
137 : : #endif
138 : :
139 : : #ifdef XAPIAN_HAS_CHERT_BACKEND
140 : : string
141 : 612 : BackendManager::createdb_chert(const vector<string> &files)
142 : : {
143 : 612 : string parent_dir = ".chert";
144 : 612 : create_dir_if_needed(parent_dir);
145 : :
146 : 612 : string dbdir = parent_dir + "/db";
147 [ + + ]: 1245 : for (vector<string>::const_iterator i = files.begin();
148 : : i != files.end(); i++) {
149 : 633 : dbdir += '=';
150 : 633 : dbdir += *i;
151 : : }
152 : : // If the database is readonly, we can reuse it if it exists.
153 [ + + ]: 612 : if (create_dir_if_needed(dbdir)) {
154 : : // Directory was created, so do the indexing.
155 : 20 : Xapian::WritableDatabase db(Xapian::Chert::open(dbdir, Xapian::DB_CREATE, 2048));
156 : 20 : index_files_to_database(db, files);
157 : 20 : db.commit();
158 : : }
159 : 612 : return dbdir;
160 : : }
161 : :
162 : : Xapian::WritableDatabase
163 : 252 : BackendManager::getwritedb_chert(const string & name,
164 : : const vector<string> & files)
165 : : {
166 : 252 : string dbdir = getwritedb_chert_path(name);
167 : :
168 : : // For a writable database we need to start afresh each time.
169 : 252 : rm_rf(dbdir);
170 : 252 : (void)create_dir_if_needed(dbdir);
171 : :
172 : : // directory was created, so do the indexing.
173 : 252 : Xapian::WritableDatabase db(Xapian::Chert::open(dbdir, Xapian::DB_CREATE, 2048));
174 : 252 : index_files_to_database(db, files);
175 : 252 : return db;
176 : : }
177 : :
178 : : std::string
179 : 279 : BackendManager::getwritedb_chert_path(const string & name)
180 : : {
181 : 279 : string parent_dir = ".chert";
182 : 279 : create_dir_if_needed(parent_dir);
183 : :
184 : 279 : string dbdir = parent_dir;
185 : 279 : dbdir += '/';
186 : 279 : dbdir += name;
187 : 279 : return dbdir;
188 : : }
189 : :
190 : : #endif
191 : :
192 : : #ifdef XAPIAN_HAS_FLINT_BACKEND
193 : : string
194 : 559 : BackendManager::createdb_flint(const vector<string> &files)
195 : : {
196 : 559 : string parent_dir = ".flint";
197 : 559 : create_dir_if_needed(parent_dir);
198 : :
199 : 559 : string dbdir = parent_dir + "/db";
200 [ + + ]: 1139 : for (vector<string>::const_iterator i = files.begin();
201 : : i != files.end(); i++) {
202 : 580 : dbdir += '=';
203 : 580 : dbdir += *i;
204 : : }
205 : : // If the database is readonly, we can reuse it if it exists.
206 [ + + ]: 559 : if (create_dir_if_needed(dbdir)) {
207 : : // Directory was created, so do the indexing.
208 : 20 : Xapian::WritableDatabase db(Xapian::Flint::open(dbdir, Xapian::DB_CREATE, 2048));
209 : 20 : index_files_to_database(db, files);
210 : 20 : db.commit();
211 : : }
212 : 559 : return dbdir;
213 : : }
214 : :
215 : : Xapian::WritableDatabase
216 : 242 : BackendManager::getwritedb_flint(const string & name,
217 : : const vector<string> & files)
218 : : {
219 : 242 : string dbdir = getwritedb_flint_path(name);
220 : :
221 : : // For a writable database we need to start afresh each time.
222 : 242 : rm_rf(dbdir);
223 : 242 : (void)create_dir_if_needed(dbdir);
224 : :
225 : : // directory was created, so do the indexing.
226 : 242 : Xapian::WritableDatabase db(Xapian::Flint::open(dbdir, Xapian::DB_CREATE, 2048));
227 : 242 : index_files_to_database(db, files);
228 : 242 : return db;
229 : : }
230 : :
231 : : std::string
232 : 269 : BackendManager::getwritedb_flint_path(const string & name)
233 : : {
234 : 269 : string parent_dir = ".flint";
235 : 269 : create_dir_if_needed(parent_dir);
236 : :
237 : 269 : string dbdir = parent_dir;
238 : 269 : dbdir += '/';
239 : 269 : dbdir += name;
240 : 269 : return dbdir;
241 : : }
242 : :
243 : : #endif
244 : :
245 [ # # ][ - + ]: 40 : BackendManager::~BackendManager() { }
[ - + ]
246 : :
247 : : std::string
248 : 3 : BackendManager::get_dbtype() const
249 : : {
250 : 3 : return "none";
251 : : }
252 : :
253 : : string
254 : 0 : BackendManager::do_get_database_path(const vector<string> &)
255 : : {
256 : 0 : throw Xapian::InvalidArgumentError("Path isn't meaningful for this database type");
257 : : }
258 : :
259 : : Xapian::Database
260 : 1083 : BackendManager::do_get_database(const vector<string> & files)
261 : : {
262 : 1083 : return Xapian::Database(do_get_database_path(files));
263 : : }
264 : :
265 : : Xapian::Database
266 : 79 : BackendManager::get_database(const vector<string> & files)
267 : : {
268 : 79 : return do_get_database(files);
269 : : }
270 : :
271 : : Xapian::Database
272 : 2269 : BackendManager::get_database(const string & file)
273 : : {
274 : 2269 : return do_get_database(vector<string>(1, file));
275 : : }
276 : :
277 : : Xapian::Database
278 : 21 : BackendManager::get_database(const std::string &dbname,
279 : : void (*gen)(Xapian::WritableDatabase&,
280 : : const std::string &),
281 : : const std::string &arg)
282 : : {
283 : 21 : string dbleaf = "db__";
284 : 21 : dbleaf += dbname;
285 : 21 : const string & path = get_writable_database_path(dbleaf);
286 : : try {
287 : 21 : return Xapian::Database(path);
288 : 18 : } catch (const Xapian::DatabaseOpeningError &) {
289 : : }
290 : 18 : rm_rf(path);
291 : :
292 : 18 : string tmp_dbleaf(dbleaf);
293 : 18 : tmp_dbleaf += '~';
294 : 18 : string tmp_path(path);
295 : 18 : tmp_path += '~';
296 : :
297 : : {
298 : : Xapian::WritableDatabase wdb = get_writable_database(tmp_dbleaf,
299 : 18 : string());
300 : 18 : gen(wdb, arg);
301 : : }
302 : 18 : rename(tmp_path.c_str(), path.c_str());
303 : :
304 : 21 : return Xapian::Database(path);
305 : : }
306 : :
307 : : std::string
308 : 21 : BackendManager::get_database_path(const std::string &dbname,
309 : : void (*gen)(Xapian::WritableDatabase&,
310 : : const std::string &),
311 : : const std::string &arg)
312 : : {
313 : 21 : string dbleaf = "db__";
314 : 21 : dbleaf += dbname;
315 : 21 : const string & path = get_writable_database_path(dbleaf);
316 : : try {
317 : 21 : (void)Xapian::Database(path);
318 : 0 : return path;
319 : 21 : } catch (const Xapian::DatabaseOpeningError &) {
320 : : }
321 : 21 : rm_rf(path);
322 : :
323 : 21 : string tmp_dbleaf(dbleaf);
324 : 21 : tmp_dbleaf += '~';
325 : 21 : string tmp_path(path);
326 : 21 : tmp_path += '~';
327 : :
328 : : {
329 : : Xapian::WritableDatabase wdb = get_writable_database(tmp_dbleaf,
330 : 21 : string());
331 : 21 : gen(wdb, arg);
332 : : }
333 : 21 : rename(tmp_path.c_str(), path.c_str());
334 : :
335 : 21 : return path;
336 : : }
337 : :
338 : : string
339 : 0 : BackendManager::get_database_path(const vector<string> & files)
340 : : {
341 : 0 : return do_get_database_path(files);
342 : : }
343 : :
344 : : string
345 : 51 : BackendManager::get_database_path(const string & file)
346 : : {
347 : 51 : return do_get_database_path(vector<string>(1, file));
348 : : }
349 : :
350 : : Xapian::WritableDatabase
351 : 0 : BackendManager::get_writable_database(const string &, const string &)
352 : : {
353 : 0 : throw Xapian::InvalidArgumentError("Attempted to open a disabled database");
354 : : }
355 : :
356 : : string
357 : 0 : BackendManager::get_writable_database_path(const std::string &)
358 : : {
359 : 0 : throw Xapian::InvalidArgumentError("Path isn't meaningful for this database type");
360 : : }
361 : :
362 : : Xapian::Database
363 : 0 : BackendManager::get_remote_database(const vector<string> &, unsigned int)
364 : : {
365 : 0 : string msg = "BackendManager::get_remote_database() called for non-remote database (type is ";
366 : 0 : msg += get_dbtype();
367 : 0 : msg += ')';
368 : 0 : throw Xapian::InvalidOperationError(msg);
369 : : }
370 : :
371 : : Xapian::Database
372 : 0 : BackendManager::get_writable_database_as_database()
373 : : {
374 : 0 : string msg = "Backend ";
375 : 0 : msg += get_dbtype();
376 : 0 : msg += " doesn't support get_writable_database_as_database()";
377 : 0 : throw Xapian::InvalidOperationError(msg);
378 : : }
379 : :
380 : : Xapian::WritableDatabase
381 : 0 : BackendManager::get_writable_database_again()
382 : : {
383 : 0 : string msg = "Backend ";
384 : 0 : msg += get_dbtype();
385 : 0 : msg += " doesn't support get_writable_database_again()";
386 : 0 : throw Xapian::InvalidOperationError(msg);
387 : : }
388 : :
389 : : void
390 : 4384 : BackendManager::clean_up()
391 : : {
392 : 4384 : }
393 : :
394 : : const char *
395 : 6 : BackendManager::get_xapian_progsrv_command()
396 : : {
397 : : #ifdef HAVE_VALGRIND
398 : : if (RUNNING_ON_VALGRIND) {
399 : : return "./runsrv "XAPIAN_PROGSRV;
400 : : }
401 : : #endif
402 : 6 : return XAPIAN_PROGSRV;
403 : : }
|