1 /** @file backendmanager_multi.cc
2 * @brief BackendManager subclass for multi databases.
4 /* Copyright (C) 2007,2008,2009,2011,2012,2013,2015,2017,2018 Olly Betts
5 * Copyright (C) 2008 Lemur Consulting Ltd
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.
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.
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 USA
24 #include "backendmanager_multi.h"
26 #include "filetests.h"
27 #include "index_utils.h"
30 #include <cstdio> // For rename().
32 #include "safeerrno.h"
36 BackendManagerMulti::BackendManagerMulti(const std::string
& datadir_
,
37 BackendManager
* sub_manager_
)
38 : BackendManager(datadir_
),
39 sub_manager(sub_manager_
),
40 cachedir(".multi" + sub_manager_
->get_dbtype())
42 // Ensure the directory we store cached test databases in exists.
43 (void)create_dir_if_needed(cachedir
);
47 BackendManagerMulti::get_dbtype() const
49 return "multi_" + sub_manager
->get_dbtype();
52 #define NUMBER_OF_SUB_DBS 2
55 BackendManagerMulti::createdb_multi(const string
& name
,
56 const vector
<string
>& files
)
63 for (const string
& file
: files
) {
69 string db_path
= cachedir
;
74 remove(db_path
.c_str());
76 if (file_exists(db_path
)) return db_path
;
79 string tmpfile
= db_path
+ ".tmp";
80 ofstream
out(tmpfile
.c_str());
82 string msg
= "Couldn't create file '";
85 msg
+= strerror(errno
);
90 // Open NUMBER_OF_SUB_DBS databases and index files to them alternately so
91 // a multi-db combining them contains the documents in the expected order.
92 Xapian::WritableDatabase dbs
;
93 const string
& subtype
= sub_manager
->get_dbtype();
94 int flags
= Xapian::DB_CREATE_OR_OVERWRITE
;
95 if (subtype
== "glass") {
96 flags
|= Xapian::DB_BACKEND_GLASS
;
98 string msg
= "Unknown multidb subtype: ";
102 string dbbase
= db_path
;
104 size_t dbbase_len
= dbbase
.size();
105 string line
= subtype
;
109 for (size_t n
= 0; n
< NUMBER_OF_SUB_DBS
; ++n
) {
111 dbs
.add_database(Xapian::WritableDatabase(dbbase
, flags
));
112 dbbase
.resize(dbbase_len
);
113 out
<< line
<< n
<< '\n';
117 FileIndexer(get_datadir(), files
).index_to(dbs
);
120 if (rename(tmpfile
.c_str(), db_path
.c_str()) < 0) {
121 throw Xapian::Database("rename failed", errno
);
124 last_wdb_path
= db_path
;
129 BackendManagerMulti::do_get_database_path(const vector
<string
> & files
)
131 return createdb_multi(string(), files
);
134 Xapian::WritableDatabase
135 BackendManagerMulti::get_writable_database(const string
& name
, const string
& file
)
137 vector
<string
> files
;
138 if (!file
.empty()) files
.push_back(file
);
139 return Xapian::WritableDatabase(createdb_multi(name
, files
));
143 BackendManagerMulti::get_writable_database_path(const std::string
& name
)
145 return cachedir
+ "/" + name
;
148 Xapian::WritableDatabase
149 BackendManagerMulti::get_writable_database_again()
151 return Xapian::WritableDatabase(last_wdb_path
);
155 BackendManagerMulti::get_writable_database_path_again()
157 return last_wdb_path
;