00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024
00025 #include <xapian.h>
00026
00027 #ifdef HAVE_VALGRIND
00028 # include <valgrind/memcheck.h>
00029 #endif
00030
00031 #include "safeerrno.h"
00032
00033 #include <cstdio>
00034 #include <fstream>
00035 #include <string>
00036 #include <vector>
00037
00038 #include <sys/types.h>
00039 #include "safesysstat.h"
00040
00041 #include "index_utils.h"
00042 #include "backendmanager.h"
00043 #include "unixcmds.h"
00044 #include "utils.h"
00045
00046 using namespace std;
00047
00048 void
00049 BackendManager::index_files_to_database(Xapian::WritableDatabase & database,
00050 const vector<string> & files)
00051 {
00052 FileIndexer f(datadir, files);
00053 while (f) database.add_document(f.next());
00054 }
00055
00060 bool
00061 BackendManager::create_dir_if_needed(const string &dirname)
00062 {
00063
00064 struct stat sbuf;
00065 int result = stat(dirname, &sbuf);
00066 if (result < 0) {
00067 if (errno != ENOENT)
00068 throw Xapian::DatabaseOpeningError("Can't stat directory");
00069 if (mkdir(dirname, 0700) < 0)
00070 throw Xapian::DatabaseOpeningError("Can't create directory");
00071 return true;
00072 }
00073 if (!S_ISDIR(sbuf.st_mode))
00074 throw Xapian::DatabaseOpeningError("Is not a directory.");
00075 return false;
00076 }
00077
00078 #ifdef XAPIAN_HAS_INMEMORY_BACKEND
00079 Xapian::WritableDatabase
00080 BackendManager::getwritedb_inmemory(const vector<string> &files)
00081 {
00082 Xapian::WritableDatabase db(Xapian::InMemory::open());
00083 index_files_to_database(db, files);
00084 return db;
00085 }
00086 #endif
00087
00088 #ifdef XAPIAN_HAS_BRASS_BACKEND
00089 string
00090 BackendManager::createdb_brass(const vector<string> &files)
00091 {
00092 string parent_dir = ".brass";
00093 create_dir_if_needed(parent_dir);
00094
00095 string dbdir = parent_dir + "/db";
00096 for (vector<string>::const_iterator i = files.begin();
00097 i != files.end(); ++i) {
00098 dbdir += '=';
00099 dbdir += *i;
00100 }
00101
00102 if (create_dir_if_needed(dbdir)) {
00103
00104 Xapian::WritableDatabase db(Xapian::Brass::open(dbdir, Xapian::DB_CREATE, 2048));
00105 index_files_to_database(db, files);
00106 db.commit();
00107 }
00108 return dbdir;
00109 }
00110
00111 Xapian::WritableDatabase
00112 BackendManager::getwritedb_brass(const string & name,
00113 const vector<string> & files)
00114 {
00115 string dbdir = getwritedb_brass_path(name);
00116
00117
00118 rm_rf(dbdir);
00119 (void)create_dir_if_needed(dbdir);
00120
00121
00122 Xapian::WritableDatabase db(Xapian::Brass::open(dbdir, Xapian::DB_CREATE, 2048));
00123 index_files_to_database(db, files);
00124 return db;
00125 }
00126
00127 std::string
00128 BackendManager::getwritedb_brass_path(const string & name)
00129 {
00130 string parent_dir = ".brass";
00131 create_dir_if_needed(parent_dir);
00132
00133 string dbdir = parent_dir;
00134 dbdir += '/';
00135 dbdir += name;
00136 return dbdir;
00137 }
00138 #endif
00139
00140 #ifdef XAPIAN_HAS_CHERT_BACKEND
00141 string
00142 BackendManager::createdb_chert(const vector<string> &files)
00143 {
00144 string parent_dir = ".chert";
00145 create_dir_if_needed(parent_dir);
00146
00147 string dbdir = parent_dir + "/db";
00148 for (vector<string>::const_iterator i = files.begin();
00149 i != files.end(); ++i) {
00150 dbdir += '=';
00151 dbdir += *i;
00152 }
00153
00154 if (create_dir_if_needed(dbdir)) {
00155
00156 Xapian::WritableDatabase db(Xapian::Chert::open(dbdir, Xapian::DB_CREATE, 2048));
00157 index_files_to_database(db, files);
00158 db.commit();
00159 }
00160 return dbdir;
00161 }
00162
00163 Xapian::WritableDatabase
00164 BackendManager::getwritedb_chert(const string & name,
00165 const vector<string> & files)
00166 {
00167 string dbdir = getwritedb_chert_path(name);
00168
00169
00170 rm_rf(dbdir);
00171 (void)create_dir_if_needed(dbdir);
00172
00173
00174 Xapian::WritableDatabase db(Xapian::Chert::open(dbdir, Xapian::DB_CREATE, 2048));
00175 index_files_to_database(db, files);
00176 return db;
00177 }
00178
00179 std::string
00180 BackendManager::getwritedb_chert_path(const string & name)
00181 {
00182 string parent_dir = ".chert";
00183 create_dir_if_needed(parent_dir);
00184
00185 string dbdir = parent_dir;
00186 dbdir += '/';
00187 dbdir += name;
00188 return dbdir;
00189 }
00190
00191 #endif
00192
00193 #ifdef XAPIAN_HAS_FLINT_BACKEND
00194 string
00195 BackendManager::createdb_flint(const vector<string> &files)
00196 {
00197 string parent_dir = ".flint";
00198 create_dir_if_needed(parent_dir);
00199
00200 string dbdir = parent_dir + "/db";
00201 for (vector<string>::const_iterator i = files.begin();
00202 i != files.end(); i++) {
00203 dbdir += '=';
00204 dbdir += *i;
00205 }
00206
00207 if (create_dir_if_needed(dbdir)) {
00208
00209 Xapian::WritableDatabase db(Xapian::Flint::open(dbdir, Xapian::DB_CREATE, 2048));
00210 index_files_to_database(db, files);
00211 db.commit();
00212 }
00213 return dbdir;
00214 }
00215
00216 Xapian::WritableDatabase
00217 BackendManager::getwritedb_flint(const string & name,
00218 const vector<string> & files)
00219 {
00220 string dbdir = getwritedb_flint_path(name);
00221
00222
00223 rm_rf(dbdir);
00224 (void)create_dir_if_needed(dbdir);
00225
00226
00227 Xapian::WritableDatabase db(Xapian::Flint::open(dbdir, Xapian::DB_CREATE, 2048));
00228 index_files_to_database(db, files);
00229 return db;
00230 }
00231
00232 std::string
00233 BackendManager::getwritedb_flint_path(const string & name)
00234 {
00235 string parent_dir = ".flint";
00236 create_dir_if_needed(parent_dir);
00237
00238 string dbdir = parent_dir;
00239 dbdir += '/';
00240 dbdir += name;
00241 return dbdir;
00242 }
00243
00244 #endif
00245
00246 BackendManager::~BackendManager() { }
00247
00248 std::string
00249 BackendManager::get_dbtype() const
00250 {
00251 return "none";
00252 }
00253
00254 string
00255 BackendManager::do_get_database_path(const vector<string> &)
00256 {
00257 throw Xapian::InvalidArgumentError("Path isn't meaningful for this database type");
00258 }
00259
00260 Xapian::Database
00261 BackendManager::do_get_database(const vector<string> & files)
00262 {
00263 return Xapian::Database(do_get_database_path(files));
00264 }
00265
00266 Xapian::Database
00267 BackendManager::get_database(const vector<string> & files)
00268 {
00269 return do_get_database(files);
00270 }
00271
00272 Xapian::Database
00273 BackendManager::get_database(const string & file)
00274 {
00275 return do_get_database(vector<string>(1, file));
00276 }
00277
00278 Xapian::Database
00279 BackendManager::get_database(const std::string &dbname,
00280 void (*gen)(Xapian::WritableDatabase&,
00281 const std::string &),
00282 const std::string &arg)
00283 {
00284 string dbleaf = "db__";
00285 dbleaf += dbname;
00286 const string & path = get_writable_database_path(dbleaf);
00287 try {
00288 return Xapian::Database(path);
00289 } catch (const Xapian::DatabaseOpeningError &) {
00290 }
00291 rm_rf(path);
00292
00293 string tmp_dbleaf(dbleaf);
00294 tmp_dbleaf += '~';
00295 string tmp_path(path);
00296 tmp_path += '~';
00297
00298 {
00299 Xapian::WritableDatabase wdb = get_writable_database(tmp_dbleaf,
00300 string());
00301 gen(wdb, arg);
00302 }
00303 rename(tmp_path.c_str(), path.c_str());
00304
00305 return Xapian::Database(path);
00306 }
00307
00308 std::string
00309 BackendManager::get_database_path(const std::string &dbname,
00310 void (*gen)(Xapian::WritableDatabase&,
00311 const std::string &),
00312 const std::string &arg)
00313 {
00314 string dbleaf = "db__";
00315 dbleaf += dbname;
00316 const string & path = get_writable_database_path(dbleaf);
00317 try {
00318 (void)Xapian::Database(path);
00319 return path;
00320 } catch (const Xapian::DatabaseOpeningError &) {
00321 }
00322 rm_rf(path);
00323
00324 string tmp_dbleaf(dbleaf);
00325 tmp_dbleaf += '~';
00326 string tmp_path(path);
00327 tmp_path += '~';
00328
00329 {
00330 Xapian::WritableDatabase wdb = get_writable_database(tmp_dbleaf,
00331 string());
00332 gen(wdb, arg);
00333 }
00334 rename(tmp_path.c_str(), path.c_str());
00335
00336 return path;
00337 }
00338
00339 string
00340 BackendManager::get_database_path(const vector<string> & files)
00341 {
00342 return do_get_database_path(files);
00343 }
00344
00345 string
00346 BackendManager::get_database_path(const string & file)
00347 {
00348 return do_get_database_path(vector<string>(1, file));
00349 }
00350
00351 Xapian::WritableDatabase
00352 BackendManager::get_writable_database(const string &, const string &)
00353 {
00354 throw Xapian::InvalidArgumentError("Attempted to open a disabled database");
00355 }
00356
00357 string
00358 BackendManager::get_writable_database_path(const std::string &)
00359 {
00360 throw Xapian::InvalidArgumentError("Path isn't meaningful for this database type");
00361 }
00362
00363 Xapian::Database
00364 BackendManager::get_remote_database(const vector<string> &, unsigned int)
00365 {
00366 string msg = "BackendManager::get_remote_database() called for non-remote database (type is ";
00367 msg += get_dbtype();
00368 msg += ')';
00369 throw Xapian::InvalidOperationError(msg);
00370 }
00371
00372 Xapian::Database
00373 BackendManager::get_writable_database_as_database()
00374 {
00375 string msg = "Backend ";
00376 msg += get_dbtype();
00377 msg += " doesn't support get_writable_database_as_database()";
00378 throw Xapian::InvalidOperationError(msg);
00379 }
00380
00381 Xapian::WritableDatabase
00382 BackendManager::get_writable_database_again()
00383 {
00384 string msg = "Backend ";
00385 msg += get_dbtype();
00386 msg += " doesn't support get_writable_database_again()";
00387 throw Xapian::InvalidOperationError(msg);
00388 }
00389
00390 void
00391 BackendManager::clean_up()
00392 {
00393 }
00394
00395 const char *
00396 BackendManager::get_xapian_progsrv_command()
00397 {
00398 #ifdef HAVE_VALGRIND
00399 if (RUNNING_ON_VALGRIND) {
00400 return "./runsrv "XAPIAN_PROGSRV;
00401 }
00402 #endif
00403 return XAPIAN_PROGSRV;
00404 }