xapian-core  1.4.27
backendmanager.cc
Go to the documentation of this file.
1 
4 /* Copyright 1999,2000,2001 BrightStation PLC
5  * Copyright 2002 Ananova Ltd
6  * Copyright 2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2016,2017,2018 Olly Betts
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
21  * USA
22  */
23 
24 #include <config.h>
25 
26 #include <xapian.h>
27 
28 #ifdef HAVE_VALGRIND
29 # include <valgrind/memcheck.h>
30 #endif
31 
32 #include <cerrno>
33 #include <cstdio>
34 #include <fstream>
35 #include <string>
36 #include <vector>
37 
38 #include <sys/types.h>
39 #include "safesysstat.h"
40 
41 #include "filetests.h"
42 #include "index_utils.h"
43 #include "backendmanager.h"
44 #include "unixcmds.h"
45 
46 using namespace std;
47 
48 void
50  const vector<string> & files)
51 {
52  FileIndexer(datadir, files).index_to(database);
53 }
54 
59 bool
61 {
62  if (mkdir(dirname.c_str(), 0700) == 0) {
63  return true;
64  }
65 
66  int mkdir_errno = errno;
67  if (mkdir_errno == EEXIST) {
68  // Something exists at dirname, but we need to check if it is a directory.
69  if (dir_exists(dirname)) {
70  return false;
71  }
72  }
73 
74  throw Xapian::DatabaseOpeningError("Failed to create directory",
75  mkdir_errno);
76 }
77 
79 
80 string
81 BackendManager::do_get_database_path(const vector<string> &)
82 {
83  throw Xapian::InvalidArgumentError("Path isn't meaningful for this database type");
84 }
85 
87 BackendManager::do_get_database(const vector<string> & files)
88 {
89  return Xapian::Database(do_get_database_path(files));
90 }
91 
93 BackendManager::get_database(const vector<string> & files)
94 {
95  return do_get_database(files);
96 }
97 
99 BackendManager::get_database(const string & file)
100 {
101  return do_get_database(vector<string>(1, file));
102 }
103 
105 BackendManager::get_database(const std::string &dbname,
106  void (*gen)(Xapian::WritableDatabase&,
107  const std::string &),
108  const std::string &arg)
109 {
110  string dbleaf = "db__";
111  dbleaf += dbname;
112  const string& path = get_generated_database_path(dbleaf);
113  if (path.empty()) {
114  // InMemory doesn't have a path but we want to support generated
115  // databases for it.
117  gen(wdb, arg);
118  // This cast avoids a -Wreturn-std-move warning from older clang (seen
119  // with clang 8 and 11; not seen with clang 13). We can't address this
120  // by adding the suggested std::move() because GCC 13 -Wredundant-move
121  // then warns that the std::move() is redundant!
122  return static_cast<Xapian::Database>(wdb);
123  }
124 
125  if (path_exists(path)) {
126  try {
127  return get_database_by_path(path);
128  } catch (const Xapian::DatabaseOpeningError &) {
129  }
130  }
131  rm_rf(path);
132 
133  string tmp_dbleaf(dbleaf);
134  tmp_dbleaf += '~';
135  string tmp_path(path);
136  tmp_path += '~';
137 
138  {
139  Xapian::WritableDatabase wdb = get_generated_database(tmp_dbleaf);
140  gen(wdb, arg);
141  }
142  finalise_generated_database(tmp_dbleaf);
143  rename(tmp_path.c_str(), path.c_str());
144  // For multi, the shards will use the temporary name, but that's not really
145  // a problem.
146 
147  return get_database_by_path(path);
148 }
149 
150 std::string
151 BackendManager::get_database_path(const std::string &dbname,
152  void (*gen)(Xapian::WritableDatabase&,
153  const std::string &),
154  const std::string &arg)
155 {
156  string dbleaf = "db__";
157  dbleaf += dbname;
158  const string& path = get_generated_database_path(dbleaf);
159  if (path_exists(path)) {
160  try {
161  (void)Xapian::Database(path);
162  return path;
163  } catch (const Xapian::DatabaseOpeningError &) {
164  }
165  }
166  rm_rf(path);
167 
168  string tmp_dbleaf(dbleaf);
169  tmp_dbleaf += '~';
170  string tmp_path(path);
171  tmp_path += '~';
172 
173  {
174  Xapian::WritableDatabase wdb = get_generated_database(tmp_dbleaf);
175  gen(wdb, arg);
176  }
177  finalise_generated_database(tmp_dbleaf);
178  rename(tmp_path.c_str(), path.c_str());
179 
180  return path;
181 }
182 
185 {
186  return Xapian::Database(path);
187 }
188 
189 string
190 BackendManager::get_database_path(const vector<string> & files)
191 {
192  return do_get_database_path(files);
193 }
194 
195 string
197 {
198  return do_get_database_path(vector<string>(1, file));
199 }
200 
202 BackendManager::get_writable_database(const string &, const string &)
203 {
204  throw Xapian::InvalidArgumentError("Attempted to open a disabled database");
205 }
206 
209 {
210  string msg = "BackendManager::get_remote_writable_database() "
211  "called for non-remote database (type is ";
212  msg += get_dbtype();
213  msg += ')';
215 }
216 
217 string
219 {
220  throw Xapian::InvalidArgumentError("Path isn't meaningful for this database type");
221 }
222 
225 {
226  return get_writable_database(name, string());
227 }
228 
229 string
231 {
232  throw Xapian::InvalidArgumentError("Compaction now supported for this database type");
233 }
234 
235 string
237 {
238  throw Xapian::InvalidArgumentError("Generated databases aren't supported for this database type");
239 }
240 
241 void
243 { }
244 
246 BackendManager::get_remote_database(const vector<string> &, unsigned int)
247 {
248  string msg = "BackendManager::get_remote_database() called for non-remote database (type is ";
249  msg += get_dbtype();
250  msg += ')';
252 }
253 
254 string
256  unsigned int)
257 {
258  string msg = "BackendManager::get_writable_database_args() "
259  "called for non-remote database (type is ";
260  msg += get_dbtype();
261  msg += ')';
263 }
264 
267 {
268  return Xapian::Database(get_writable_database_path_again());
269 }
270 
273 {
274  string msg = "Backend ";
275  msg += get_dbtype();
276  msg += " doesn't support get_writable_database_again()";
278 }
279 
280 string
282 {
283  string msg = "Backend ";
284  msg += get_dbtype();
285  msg += " doesn't support get_writable_database_path_again()";
287 }
288 
289 void
291 {
292 }
293 
294 const char *
296 {
297 #ifdef HAVE_VALGRIND
298  if (RUNNING_ON_VALGRIND) {
299  return "./runsrv " XAPIAN_PROGSRV;
300  }
301 #endif
302  return XAPIAN_PROGSRV;
303 }
static const char * get_xapian_progsrv_command()
Get the command line required to run xapian-progsrv.
virtual Xapian::Database get_remote_database(const std::vector< std::string > &files, unsigned int timeout)
Get a remote database instance with the specified timeout.
This class is used to access a database, or a group of databases.
Definition: database.h:68
Xapian::Database get_database(const std::vector< std::string > &files)
Get a database instance of the current type.
InvalidOperationError indicates the API was used in an invalid way.
Definition: error.h:283
DatabaseOpeningError indicates failure to open a database.
Definition: error.h:581
virtual std::string get_generated_database_path(const std::string &name)
Get the path to use for generating a database, if supported.
Xapian::WritableDatabase get_writable_database(const string &dbname)
Definition: apitest.cc:87
std::string get_database_path(const std::vector< std::string > &files)
Get the path of a database instance, if such a thing exists.
virtual Xapian::WritableDatabase get_generated_database(const std::string &name)
Get a generated writable database instance.
C++ function versions of useful Unix commands.
STL namespace.
#define XAPIAN_PROGSRV
Utility functions for testing files.
virtual std::string get_writable_database_path(const std::string &name)
Get the path of a writable database instance, if such a thing exists.
virtual Xapian::WritableDatabase get_writable_database(const std::string &name, const std::string &file)
Get a writable database instance.
include <sys/stat.h> with portability enhancements
void rm_rf(const string &filename)
Remove a directory and contents, just like the Unix "rm -rf" command.
Definition: unixcmds.cc:111
bool create_dir_if_needed(const std::string &dirname)
Create the directory dirname if needed.
InvalidArgumentError indicates an invalid parameter value was passed to the API.
Definition: error.h:241
virtual Xapian::WritableDatabase get_writable_database_again()
Create a WritableDatabase object for the last opened WritableDatabase.
virtual Xapian::Database get_database_by_path(const std::string &path)
Get a database instance by path.
Base class for backend handling in test harness.
This class provides read/write access to a database.
Definition: database.h:789
Public interfaces for the Xapian library.
virtual Xapian::WritableDatabase get_remote_writable_database(std::string args)
Get a remote Xapian::WritableDatabase instance with specified args.
std::string get_dbtype()
Definition: apitest.cc:42
virtual std::string get_writable_database_path_again()
Get the path of the last opened WritableDatabase.
bool dir_exists(const char *path)
Test if a directory exists.
Definition: filetests.h:136
virtual void clean_up()
Called after each test, to perform any necessary cleanup.
static mt19937 gen
Definition: soaktest.cc:37
virtual ~BackendManager()
We have virtual methods and want to be able to delete derived classes using a pointer to the base cla...
virtual Xapian::Database do_get_database(const std::vector< std::string > &files)
Virtual method implementing get_database().
virtual std::string do_get_database_path(const std::vector< std::string > &files)
Virtual method implementing get_database_path().
void index_to(Xapian::WritableDatabase &db)
Definition: index_utils.cc:52
virtual Xapian::Database get_writable_database_as_database()
Create a Database object for the last opened WritableDatabase.
virtual std::string get_writable_database_args(const std::string &path, unsigned int timeout)
Get the args for opening a writable remote database with the specified timeout.
Definition: header.h:151
utility functions for indexing testcase data
virtual std::string get_compaction_output_path(const std::string &name)
Get a path to compact a database to.
bool path_exists(const char *path)
Test if a path exists.
Definition: filetests.h:158
virtual void finalise_generated_database(const std::string &name)
Finalise the generated database.
void index_files_to_database(Xapian::WritableDatabase &database, const std::vector< std::string > &files)
Index data from zero or more text files into a database.