xapian-core  2.1.0
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, see
20  * <https://www.gnu.org/licenses/>.
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 <cerrno>
32 #include <cstdio>
33 #include <string>
34 #include <vector>
35 
36 #include <sys/types.h>
37 #include "safesysstat.h"
38 
39 #include "filetests.h"
40 #include "index_utils.h"
41 #include "backendmanager.h"
42 #include "unixcmds.h"
43 
44 using namespace std;
45 
46 [[noreturn]]
47 static void
48 invalid_operation(const char* msg)
49 {
51 }
52 
53 void
55  const vector<string> & files)
56 {
57  FileIndexer(datadir, files).index_to(database);
58 }
59 
64 bool
66 {
67  if (mkdir(dirname.c_str(), 0700) == 0) {
68  return true;
69  }
70 
71  int mkdir_errno = errno;
72  if (mkdir_errno == EEXIST) {
73  // Something exists at dirname, but we need to check if it is a directory.
74  if (dir_exists(dirname)) {
75  return false;
76  }
77  }
78 
79  throw Xapian::DatabaseOpeningError("Failed to create directory",
80  mkdir_errno);
81 }
82 
84 
85 string
86 BackendManager::do_get_database_path(const vector<string> &)
87 {
88  invalid_operation("Path isn't meaningful for this database type");
89 }
90 
92 BackendManager::do_get_database(const vector<string> & files)
93 {
94  return Xapian::Database(do_get_database_path(files));
95 }
96 
98 BackendManager::get_database(const vector<string> & files)
99 {
100  return do_get_database(files);
101 }
102 
104 BackendManager::get_database(const string & file)
105 {
106  return do_get_database(vector<string>(1, file));
107 }
108 
110 BackendManager::get_database(const std::string &dbname,
111  void (*gen)(Xapian::WritableDatabase&,
112  const std::string &),
113  const std::string &arg)
114 {
115  string dbleaf = "db__";
116  dbleaf += dbname;
117  const string& path = get_generated_database_path(dbleaf);
118  if (path.empty()) {
119  // InMemory doesn't have a path but we want to support generated
120  // databases for it.
122  gen(wdb, arg);
123  // This cast avoids a -Wreturn-std-move warning from older clang (seen
124  // with clang 8 and 11; not seen with clang 13). We can't address this
125  // by adding the suggested std::move() because GCC 13 -Wredundant-move
126  // then warns that the std::move() is redundant!
127  return static_cast<Xapian::Database>(wdb);
128  }
129 
130  if (path_exists(path)) {
131  try {
132  return get_database_by_path(path);
133  } catch (const Xapian::DatabaseOpeningError &) {
134  }
135  }
136  rm_rf(path);
137 
138  string tmp_dbleaf(dbleaf);
139  tmp_dbleaf += '~';
140  string tmp_path(path);
141  tmp_path += '~';
142 
143  {
144  Xapian::WritableDatabase wdb = get_generated_database(tmp_dbleaf);
145  gen(wdb, arg);
146  }
147  finalise_generated_database(tmp_dbleaf);
148  rename(tmp_path.c_str(), path.c_str());
149  // For multi, the shards will use the temporary name, but that's not really
150  // a problem.
151 
152  return get_database_by_path(path);
153 }
154 
155 std::string
156 BackendManager::get_database_path(const std::string &dbname,
157  void (*gen)(Xapian::WritableDatabase&,
158  const std::string &),
159  const std::string &arg)
160 {
161  string dbleaf = "db__";
162  dbleaf += dbname;
163  const string& path = get_generated_database_path(dbleaf);
164  if (path_exists(path)) {
165  try {
166  (void)Xapian::Database(path);
167  return path;
168  } catch (const Xapian::DatabaseOpeningError &) {
169  }
170  }
171  rm_rf(path);
172 
173  string tmp_dbleaf(dbleaf);
174  tmp_dbleaf += '~';
175  string tmp_path(path);
176  tmp_path += '~';
177 
178  {
179  Xapian::WritableDatabase wdb = get_generated_database(tmp_dbleaf);
180  gen(wdb, arg);
181  }
182  finalise_generated_database(tmp_dbleaf);
183  rename(tmp_path.c_str(), path.c_str());
184 
185  return path;
186 }
187 
190 {
191  return Xapian::Database(path);
192 }
193 
194 string
195 BackendManager::get_database_path(const vector<string> & files)
196 {
197  return do_get_database_path(files);
198 }
199 
200 string
202 {
203  return do_get_database_path(vector<string>(1, file));
204 }
205 
207 BackendManager::get_writable_database(const string &, const string &)
208 {
209  invalid_operation("Attempted to open a disabled database");
210 }
211 
214 {
215  string msg = "BackendManager::get_remote_writable_database() "
216  "called for non-remote database (type is ";
217  msg += get_dbtype();
218  msg += ')';
220 }
221 
222 string
224 {
225  invalid_operation("Path isn't meaningful for this database type");
226 }
227 
228 string
230 {
231  invalid_operation("Compaction not supported for this database type");
232 }
233 
236 {
237  return get_writable_database(name, string());
238 }
239 
240 string
242 {
243  invalid_operation("Generated databases aren't supported for this database "
244  "type");
245 }
246 
247 void
249 { }
250 
253  unsigned int,
254  int*)
255 {
256  string msg = "BackendManager::get_remote_database() called for non-remote "
257  "database (type is ";
258  msg += get_dbtype();
259  msg += ')';
261 }
262 
263 string
265  unsigned int)
266 {
267  string msg = "BackendManager::get_writable_database_args() "
268  "called for non-remote database (type is ";
269  msg += get_dbtype();
270  msg += ')';
272 }
273 
276 {
277  return Xapian::Database(get_writable_database_path_again());
278 }
279 
282 {
283  string msg = "Backend ";
284  msg += get_dbtype();
285  msg += " doesn't support get_writable_database_again()";
287 }
288 
289 string
291 {
292  string msg = "Backend ";
293  msg += get_dbtype();
294  msg += " doesn't support get_writable_database_path_again()";
296 }
297 
298 void
300 {
301 }
302 
303 void
305 {
306  throw Xapian::InvalidOperationError("kill_remote() only supported for "
307  "remotetcp databases");
308 }
309 
310 const char *
312 {
313 #ifdef HAVE_VALGRIND
314  if (RUNNING_ON_VALGRIND) {
315  return "./runsrv " XAPIAN_PROGSRV;
316  }
317 #endif
318  return XAPIAN_PROGSRV;
319 }
std::string get_dbtype()
Definition: apitest.cc:41
Xapian::WritableDatabase get_writable_database(const string &dbname)
Definition: apitest.cc:86
static void invalid_operation(const char *msg)
Base class for backend handling in test harness.
#define XAPIAN_PROGSRV
static const char * get_xapian_progsrv_command()
Get the command line required to run xapian-progsrv.
Xapian::Database get_database(const std::vector< std::string > &files)
Get a database instance of the current type.
virtual std::string get_compaction_output_path(const std::string &name)
Get a path to compact a database to.
virtual Xapian::WritableDatabase get_writable_database_again()
Create a WritableDatabase object for the last opened WritableDatabase.
virtual Xapian::WritableDatabase get_generated_database(const std::string &name)
Get a generated writable database instance.
virtual std::string do_get_database_path(const std::vector< std::string > &files)
Virtual method implementing get_database_path().
bool create_dir_if_needed(const std::string &dirname)
Create the directory dirname if needed.
virtual Xapian::Database do_get_database(const std::vector< std::string > &files)
Virtual method implementing get_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.
virtual Xapian::WritableDatabase get_remote_writable_database(std::string args)
Get a remote Xapian::WritableDatabase instance with specified args.
virtual ~BackendManager()
We have virtual methods and want to be able to delete derived classes using a pointer to the base cla...
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.
virtual Xapian::Database get_database_by_path(const std::string &path)
Get a database instance by path.
std::string get_database_path(const std::vector< std::string > &files)
Get the path of a database instance, if such a thing exists.
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 std::string get_generated_database_path(const std::string &name)
Get the path to use for generating a database, if supported.
virtual Xapian::Database get_writable_database_as_database()
Create a Database object for the last opened WritableDatabase.
virtual void finalise_generated_database(const std::string &name)
Finalise the generated database.
virtual void clean_up()
Called after each test, to perform any necessary cleanup.
virtual Xapian::Database get_remote_database(const std::vector< std::string > &files, unsigned int timeout, int *port_ptr)
Get a remote database instance with the specified timeout.
virtual void kill_remote(const Xapian::Database &db)
Kill the remote server associated with db.
virtual Xapian::WritableDatabase get_writable_database(const std::string &name, const std::string &file)
Get a writable database instance.
virtual std::string get_writable_database_path_again()
Get the path of the last opened WritableDatabase.
void index_to(Xapian::WritableDatabase &db)
Definition: index_utils.cc:51
DatabaseOpeningError indicates failure to open a database.
Definition: error.h:569
An indexed database of documents.
Definition: database.h:75
InvalidOperationError indicates the API was used in an invalid way.
Definition: error.h:271
This class provides read/write access to a database.
Definition: database.h:963
Utility functions for testing files.
bool dir_exists(const char *path)
Test if a directory exists.
Definition: filetests.h:145
bool path_exists(const char *path)
Test if a path exists.
Definition: filetests.h:167
utility functions for indexing testcase data
include <sys/stat.h> with portability enhancements
static mt19937 gen
Definition: soaktest.cc:36
Definition: header.h:242
void rm_rf(const string &filename)
Remove a directory and contents, just like the Unix "rm -rf" command.
Definition: unixcmds.cc:111
C++ function versions of useful Unix commands.
Public interfaces for the Xapian library.