xapian-core  2.0.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 <fstream>
34 #include <string>
35 #include <vector>
36 
37 #include <sys/types.h>
38 #include "safesysstat.h"
39 
40 #include "filetests.h"
41 #include "index_utils.h"
42 #include "backendmanager.h"
43 #include "unixcmds.h"
44 
45 using namespace std;
46 
47 [[noreturn]]
48 static void
49 invalid_operation(const char* msg)
50 {
52 }
53 
54 void
56  const vector<string> & files)
57 {
58  FileIndexer(datadir, files).index_to(database);
59 }
60 
65 bool
67 {
68  if (mkdir(dirname.c_str(), 0700) == 0) {
69  return true;
70  }
71 
72  int mkdir_errno = errno;
73  if (mkdir_errno == EEXIST) {
74  // Something exists at dirname, but we need to check if it is a directory.
75  if (dir_exists(dirname)) {
76  return false;
77  }
78  }
79 
80  throw Xapian::DatabaseOpeningError("Failed to create directory",
81  mkdir_errno);
82 }
83 
85 
86 string
87 BackendManager::do_get_database_path(const vector<string> &)
88 {
89  invalid_operation("Path isn't meaningful for this database type");
90 }
91 
93 BackendManager::do_get_database(const vector<string> & files)
94 {
95  return Xapian::Database(do_get_database_path(files));
96 }
97 
99 BackendManager::get_database(const vector<string> & files)
100 {
101  return do_get_database(files);
102 }
103 
105 BackendManager::get_database(const string & file)
106 {
107  return do_get_database(vector<string>(1, file));
108 }
109 
111 BackendManager::get_database(const std::string &dbname,
112  void (*gen)(Xapian::WritableDatabase&,
113  const std::string &),
114  const std::string &arg)
115 {
116  string dbleaf = "db__";
117  dbleaf += dbname;
118  const string& path = get_generated_database_path(dbleaf);
119  if (path.empty()) {
120  // InMemory doesn't have a path but we want to support generated
121  // databases for it.
123  gen(wdb, arg);
124  // This cast avoids a -Wreturn-std-move warning from older clang (seen
125  // with clang 8 and 11; not seen with clang 13). We can't address this
126  // by adding the suggested std::move() because GCC 13 -Wredundant-move
127  // then warns that the std::move() is redundant!
128  return static_cast<Xapian::Database>(wdb);
129  }
130 
131  if (path_exists(path)) {
132  try {
133  return get_database_by_path(path);
134  } catch (const Xapian::DatabaseOpeningError &) {
135  }
136  }
137  rm_rf(path);
138 
139  string tmp_dbleaf(dbleaf);
140  tmp_dbleaf += '~';
141  string tmp_path(path);
142  tmp_path += '~';
143 
144  {
145  Xapian::WritableDatabase wdb = get_generated_database(tmp_dbleaf);
146  gen(wdb, arg);
147  }
148  finalise_generated_database(tmp_dbleaf);
149  rename(tmp_path.c_str(), path.c_str());
150  // For multi, the shards will use the temporary name, but that's not really
151  // a problem.
152 
153  return get_database_by_path(path);
154 }
155 
156 std::string
157 BackendManager::get_database_path(const std::string &dbname,
158  void (*gen)(Xapian::WritableDatabase&,
159  const std::string &),
160  const std::string &arg)
161 {
162  string dbleaf = "db__";
163  dbleaf += dbname;
164  const string& path = get_generated_database_path(dbleaf);
165  if (path_exists(path)) {
166  try {
167  (void)Xapian::Database(path);
168  return path;
169  } catch (const Xapian::DatabaseOpeningError &) {
170  }
171  }
172  rm_rf(path);
173 
174  string tmp_dbleaf(dbleaf);
175  tmp_dbleaf += '~';
176  string tmp_path(path);
177  tmp_path += '~';
178 
179  {
180  Xapian::WritableDatabase wdb = get_generated_database(tmp_dbleaf);
181  gen(wdb, arg);
182  }
183  finalise_generated_database(tmp_dbleaf);
184  rename(tmp_path.c_str(), path.c_str());
185 
186  return path;
187 }
188 
191 {
192  return Xapian::Database(path);
193 }
194 
195 string
196 BackendManager::get_database_path(const vector<string> & files)
197 {
198  return do_get_database_path(files);
199 }
200 
201 string
203 {
204  return do_get_database_path(vector<string>(1, file));
205 }
206 
208 BackendManager::get_writable_database(const string &, const string &)
209 {
210  invalid_operation("Attempted to open a disabled database");
211 }
212 
215 {
216  string msg = "BackendManager::get_remote_writable_database() "
217  "called for non-remote database (type is ";
218  msg += get_dbtype();
219  msg += ')';
221 }
222 
223 string
225 {
226  invalid_operation("Path isn't meaningful for this database type");
227 }
228 
229 string
231 {
232  invalid_operation("Compaction not supported for this database type");
233 }
234 
237 {
238  return get_writable_database(name, string());
239 }
240 
241 string
243 {
244  invalid_operation("Generated databases aren't supported for this database "
245  "type");
246 }
247 
248 void
250 { }
251 
254  unsigned int,
255  int*)
256 {
257  string msg = "BackendManager::get_remote_database() called for non-remote "
258  "database (type is ";
259  msg += get_dbtype();
260  msg += ')';
262 }
263 
264 string
266  unsigned int)
267 {
268  string msg = "BackendManager::get_writable_database_args() "
269  "called for non-remote database (type is ";
270  msg += get_dbtype();
271  msg += ')';
273 }
274 
277 {
278  return Xapian::Database(get_writable_database_path_again());
279 }
280 
283 {
284  string msg = "Backend ";
285  msg += get_dbtype();
286  msg += " doesn't support get_writable_database_again()";
288 }
289 
290 string
292 {
293  string msg = "Backend ";
294  msg += get_dbtype();
295  msg += " doesn't support get_writable_database_path_again()";
297 }
298 
299 void
301 {
302 }
303 
304 void
306 {
307  throw Xapian::InvalidOperationError("kill_remote() only supported for "
308  "remotetcp databases");
309 }
310 
311 const char *
313 {
314 #ifdef HAVE_VALGRIND
315  if (RUNNING_ON_VALGRIND) {
316  return "./runsrv " XAPIAN_PROGSRV;
317  }
318 #endif
319  return XAPIAN_PROGSRV;
320 }
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:52
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:964
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:215
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.