58 #define REPLICA_STUB_BANNER \ 59 "# Automatically generated by Xapian::DatabaseReplica v" XAPIAN_VERSION ".\n" \ 60 "# Do not manually edit - replication operations may regenerate this file.\n" 70 DatabaseMaster::write_changesets_to_fd(
int fd,
71 const string & start_revision,
74 LOGCALL_VOID(REPLICA,
"DatabaseMaster::write_changesets_to_fd", fd | start_revision | info);
83 "Can't open database: " + e.
get_msg(),
92 bool need_whole_db =
false;
94 if (start_revision.empty()) {
97 const char * ptr = start_revision.data();
98 const char * end = ptr + start_revision.size();
101 string request_uuid(ptr, uuid_length);
103 string db_uuid = db.
internal[0]->get_uuid();
104 if (request_uuid != db_uuid) {
105 need_whole_db =
true;
107 revision.assign(ptr, end - ptr);
110 db.
internal[0]->write_changesets_to_fd(fd, revision, need_whole_db, info);
114 DatabaseMaster::get_description()
const 116 string desc =
"DatabaseMaster(";
181 void update_stub_database()
const;
184 void remove_offline_db();
188 void apply_db_copy(
double end_time);
194 void check_message_type(
int type,
int expected)
const;
202 bool possibly_make_offline_live();
213 explicit Internal(
const string & path_);
219 string get_revision_info()
const;
222 void set_read_fd(
int fd);
226 double reader_close_time);
234 DatabaseReplica::DatabaseReplica(
const string & path)
249 LOGCALL(REPLICA,
string,
"DatabaseReplica::get_revision_info", NO_ARGS);
256 LOGCALL_VOID(REPLICA,
"DatabaseReplica::set_read_fd", fd);
257 internal->set_read_fd(fd);
262 double reader_close_time)
264 LOGCALL(REPLICA,
bool,
"DatabaseReplica::apply_next_changeset", info | reader_close_time);
273 string desc(
"DatabaseReplica(");
274 desc +=
internal->get_description();
284 string stub_path = path;
285 stub_path +=
"/XAPIANDB";
286 string tmp_path = stub_path;
289 ofstream stub(tmp_path.c_str());
291 "auto replica_" << live_id << endl;
294 string msg(
"Failed to update stub db file for replica: ");
301 : path(path_), live_id(0), live_db(), have_offline_db(
false),
302 need_copy_next(
false), offline_revision(), offline_needed_revision(),
303 last_live_changeset_time(), conn(NULL)
305 LOGCALL_CTOR(REPLICA,
"DatabaseReplica::Internal", path_);
306 #if !defined XAPIAN_HAS_CHERT_BACKEND && !defined XAPIAN_HAS_GLASS_BACKEND 309 if (mkdir(
path.c_str(), 0777) == 0) {
320 if (errno != EEXIST) {
326 string stub_path =
path;
327 stub_path +=
"/XAPIANDB";
335 live_db.internal.push_back(NULL);
338 ifstream stub(stub_path.c_str());
340 while (getline(stub, line)) {
341 if (!line.empty() && line[0] !=
'#') {
342 live_id = line[line.size() - 1] -
'0';
353 LOGCALL(REPLICA,
string,
"DatabaseReplica::Internal::get_revision_info", NO_ARGS);
361 string uuid = (
live_db.internal[0])->get_uuid();
388 if (mkdir(offline_path.c_str(), 0777)) {
390 offline_path +
"'", errno);
397 const char * ptr = buf.data();
398 const char * end = ptr + buf.size();
419 if (filename.find(
"..") != string::npos) {
420 throw NetworkError(
"Filename in database contains '..'");
427 string filepath = offline_path +
"/" + filename;
441 if (type != expected) {
444 string m =
"Expected replication protocol message type #";
456 AutoPtr<DatabaseReplicator> replicator;
470 string replicated_uuid = replicator->get_uuid();
471 if (replicated_uuid.empty()) {
498 double reader_close_time)
500 LOGCALL(REPLICA,
bool,
"DatabaseReplica::Internal::apply_next_changeset", info | reader_close_time);
518 AutoPtr<DatabaseReplicator> replicator(
520 replica_uuid = replicator->get_uuid();
562 AutoPtr<DatabaseReplicator> replicator(
568 replicator->apply_changeset_from_conn(*
conn, 0.0,
true);
582 AutoPtr<DatabaseReplicator> replicator(
586 apply_changeset_from_conn(*
conn, 0.0,
false);
601 throw NetworkError(
"Unable to fully synchronise: " + buf);
606 throw NetworkError(
"Unknown replication protocol message (" +
void check_message_type(int type, int expected) const
Check that a message type is as expected.
The Xapian namespace contains public interfaces for the Xapian library.
Define the XAPIAN_NORETURN macro.
A RemoteConnection object provides a bidirectional connection to another RemoteConnection object on a...
RemoteConnection class used by the remote backend.
bool possibly_make_offline_live()
Check if the offline database has reached the required version.
length encoded as a string
int get_message(std::string &result, double end_time)
Read one message from fdin.
This class is used to access a database, or a group of databases.
void set_read_fd(int fd)
Set the file descriptor to read changesets from.
int fullcopy_count
Number of times a full database copy was performed.
Internal(const Internal &)
Don't allow copying.
const int DB_CREATE
Create a new database.
Internal * internal
Internals.
InvalidOperationError indicates the API was used in an invalid way.
string path
The path to the replica directory.
DatabaseOpeningError indicates failure to open a database.
void apply_db_copy(double end_time)
Apply a set of DB copy messages from the connection.
void set_read_fd(int fd)
Set the file descriptor to read changesets from.
Access to a database replica, for applying replication to it.
Constants in the Xapian namespace.
const std::string & get_msg() const
Message giving details of the error, intended for human consumption.
void sleep(double t)
Sleep until the time represented by this object.
#define LOGCALL_DTOR(CATEGORY, CLASS)
double end_time(double timeout)
Return the end time for a timeout in timeout seconds.
WritableDatabase open()
Construct a WritableDatabase object for a new, empty InMemory database.
#define LOGCALL_VOID(CATEGORY, FUNC, PARAMS)
Convert types to std::string.
string get_description() const
Return a string describing this object.
static void throw_connection_closed_unexpectedly()
#define REPLICA_STUB_BANNER
bool have_offline_db
Do we have an offline database currently?
int revision()
Report the revision of the library which the program is linked with.
Utility functions for testing files.
std::string encode_length(T len)
Encode a length as a variable-length string.
std::vector< Xapian::Internal::intrusive_ptr< Internal > > internal
bool apply_next_changeset(ReplicationInfo *info, double reader_close_time)
Read and apply the next changeset.
std::string get_revision_info() const
Get a string describing the current revision of the replica.
include <sys/stat.h> with portability enhancements
string offline_revision
The revision that the secondary database has been updated to.
string get_revision_info() const
Get a string describing the current revision of the replica.
Hierarchy of classes which Xapian can throw as exceptions.
int live_id
The id of the currently live database in the replica (0 or 1).
std::string get_description() const
Return a string describing this object.
Class to manage replication of databases.
void description_append(std::string &desc, const std::string &s)
const int DB_OPEN
Open an existing database.
This class provides read/write access to a database.
Indicates an attempt to use a feature which is unavailable.
bool apply_next_changeset(ReplicationInfo *info, double reader_close_time)
Read and apply the next changeset.
bool need_copy_next
Flag to indicate that the only valid operation next is a full copy.
void remove_offline_db()
Delete the offline database.
string str(int value)
Convert int to std::string.
Information about the steps involved in performing a replication.
int changeset_count
Number of changesets applied.
bool io_tmp_rename(const std::string &tmp_file, const std::string &real_file)
Rename a temporary file to its final position.
void update_stub_database() const
Update the stub database which points to a single database.
string get_replica_path(int id) const
Base class for objects managed by intrusive_ptr.
#define LOGCALL_CTOR(CATEGORY, CLASS, PARAMS)
bool dir_exists(const char *path)
Test if a directory exists.
Define preprocessor symbols for the library version.
bool changed
True if and only if the replication corresponds to a change in the live version of the database...
size_t size() const
Return number of shards in this Database object.
DatabaseCorruptError indicates database corruption was detected.
Append a string to an object description, escaping invalid UTF-8.
string offline_needed_revision
The revision that the secondary database must reach before it can be made live.
Internal implementation of DatabaseReplica.
const int DB_BACKEND_STUB
Open a stub database file.
void decode_length_and_check(const char **p, const char *end, unsigned &out)
Decode a length encoded by encode_length.
Replication protocol version and message numbers.
Replication support for Xapian databases.
int receive_file(const std::string &file, double end_time)
Save the contents of a message as a file.
double now()
Return the current time.
RemoteConnection * conn
The remote connection we're using.
Indicates a problem communicating with a remote database.
Wrappers for low-level POSIX I/O routines.
void send_message(char type, const std::string &s, double end_time)
Send a message.
<unistd.h>, but with compat.
void removedir(const string &dirname)
Remove a directory, and its contents.
Various assertion macros.
Functions for handling a time or time interval in a double.
DatabaseError indicates some sort of database related error.
int sniff_next_message_type(double end_time)
Check what the next message type is.
Factory functions for constructing Database and WritableDatabase objects.
string offline_uuid
The UUID of the secondary database.
File and path manipulation routines.
Wrapper around standard unique_ptr template.
#define LOGCALL(CATEGORY, TYPE, FUNC, PARAMS)
WritableDatabase live_db
The live database being replicated.
~DatabaseReplica()
Destructor.
double last_live_changeset_time
The time at which a changeset was last applied to the live database.