mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 10:40:38 +01:00
Frontported fix for #7673: Make async replication reliable on Linux CS (replica side)
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
631b039c1e
commit
9aaeab2d4b
@ -333,7 +333,7 @@ Config* Config::get(const PathName& lookupName)
|
|||||||
// This routine is used to retrieve the list of replica databases.
|
// This routine is used to retrieve the list of replica databases.
|
||||||
// Therefore it checks only the necessary settings.
|
// Therefore it checks only the necessary settings.
|
||||||
|
|
||||||
void Config::enumerate(Firebird::Array<Config*>& replicas)
|
void Config::enumerate(ReplicaList& replicas)
|
||||||
{
|
{
|
||||||
PathName dbName;
|
PathName dbName;
|
||||||
|
|
||||||
|
@ -33,11 +33,13 @@ namespace Replication
|
|||||||
{
|
{
|
||||||
struct Config : public Firebird::GlobalStorage
|
struct Config : public Firebird::GlobalStorage
|
||||||
{
|
{
|
||||||
|
typedef Firebird::HalfStaticArray<Config*, 4> ReplicaList;
|
||||||
|
|
||||||
Config();
|
Config();
|
||||||
Config(const Config& other);
|
Config(const Config& other);
|
||||||
|
|
||||||
static Config* get(const Firebird::PathName& dbName);
|
static Config* get(const Firebird::PathName& dbName);
|
||||||
static void enumerate(Firebird::Array<Config*>& replicas);
|
static void enumerate(ReplicaList& replicas);
|
||||||
|
|
||||||
Firebird::PathName dbName;
|
Firebird::PathName dbName;
|
||||||
ULONG bufferSize;
|
ULONG bufferSize;
|
||||||
|
@ -81,11 +81,8 @@ namespace
|
|||||||
|
|
||||||
int shutdownHandler(const int, const int, void*)
|
int shutdownHandler(const int, const int, void*)
|
||||||
{
|
{
|
||||||
if (activeThreads.value())
|
if (!shutdownFlag && activeThreads.value())
|
||||||
{
|
{
|
||||||
gds__log("Shutting down the replication server with %d replicated database(s)",
|
|
||||||
(int) activeThreads.value());
|
|
||||||
|
|
||||||
shutdownFlag = true;
|
shutdownFlag = true;
|
||||||
shutdownSemaphore.release(activeThreads.value() + 1);
|
shutdownSemaphore.release(activeThreads.value() + 1);
|
||||||
|
|
||||||
@ -579,15 +576,6 @@ namespace
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void readConfig(TargetList& targets)
|
|
||||||
{
|
|
||||||
Array<Replication::Config*> replicas;
|
|
||||||
Replication::Config::enumerate(replicas);
|
|
||||||
|
|
||||||
for (auto replica : replicas)
|
|
||||||
targets.add(FB_NEW Target(replica));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool validateHeader(const SegmentHeader* header)
|
bool validateHeader(const SegmentHeader* header)
|
||||||
{
|
{
|
||||||
if (strcmp(header->hdr_signature, CHANGELOG_SIGNATURE))
|
if (strcmp(header->hdr_signature, CHANGELOG_SIGNATURE))
|
||||||
@ -988,14 +976,15 @@ namespace
|
|||||||
{
|
{
|
||||||
AutoPtr<Target> target(static_cast<Target*>(arg));
|
AutoPtr<Target> target(static_cast<Target*>(arg));
|
||||||
const auto config = target->getConfig();
|
const auto config = target->getConfig();
|
||||||
|
const auto dbName = config->dbName.c_str();
|
||||||
|
|
||||||
target->verbose("Started replication thread");
|
AutoMemoryPool workingPool(MemoryPool::createPool());
|
||||||
|
ContextPoolHolder threadContext(workingPool);
|
||||||
|
|
||||||
|
target->verbose("Started replication for database %s", dbName);
|
||||||
|
|
||||||
while (!shutdownFlag)
|
while (!shutdownFlag)
|
||||||
{
|
{
|
||||||
AutoMemoryPool workingPool(MemoryPool::createPool());
|
|
||||||
ContextPoolHolder threadContext(workingPool);
|
|
||||||
|
|
||||||
const ProcessStatus ret = process_archive(*workingPool, target);
|
const ProcessStatus ret = process_archive(*workingPool, target);
|
||||||
|
|
||||||
if (ret == PROCESS_CONTINUE)
|
if (ret == PROCESS_CONTINUE)
|
||||||
@ -1003,10 +992,7 @@ namespace
|
|||||||
|
|
||||||
target->shutdown();
|
target->shutdown();
|
||||||
|
|
||||||
if (ret == PROCESS_SHUTDOWN)
|
if (ret != PROCESS_SHUTDOWN)
|
||||||
break;
|
|
||||||
|
|
||||||
if (!shutdownFlag)
|
|
||||||
{
|
{
|
||||||
const ULONG timeout =
|
const ULONG timeout =
|
||||||
(ret == PROCESS_SUSPEND) ? config->applyIdleTimeout : config->applyErrorTimeout;
|
(ret == PROCESS_SUSPEND) ? config->applyIdleTimeout : config->applyErrorTimeout;
|
||||||
@ -1015,7 +1001,7 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target->verbose("Finished replication thread");
|
target->verbose("Finished replication for database %s", dbName);
|
||||||
--activeThreads;
|
--activeThreads;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1023,17 +1009,15 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool REPL_server(CheckStatusWrapper* status, bool wait)
|
bool REPL_server(CheckStatusWrapper* status, const ReplicaList& replicas, bool wait)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
fb_shutdown_callback(0, shutdownHandler, fb_shut_finish, 0);
|
fb_shutdown_callback(0, shutdownHandler, fb_shut_preproviders, 0);
|
||||||
|
|
||||||
TargetList targets;
|
for (const auto replica : replicas)
|
||||||
readConfig(targets);
|
|
||||||
|
|
||||||
for (auto target : targets)
|
|
||||||
{
|
{
|
||||||
|
const auto target = FB_NEW Target(replica);
|
||||||
Thread::start(process_thread, target, THREAD_medium, NULL);
|
Thread::start(process_thread, target, THREAD_medium, NULL);
|
||||||
++activeThreads;
|
++activeThreads;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,6 @@
|
|||||||
#ifndef UTIL_REPL_SERVER_H
|
#ifndef UTIL_REPL_SERVER_H
|
||||||
#define UTIL_REPL_SERVER_H
|
#define UTIL_REPL_SERVER_H
|
||||||
|
|
||||||
bool REPL_server(Firebird::CheckStatusWrapper*, bool);
|
bool REPL_server(Firebird::CheckStatusWrapper*, const ReplicaList&, bool);
|
||||||
|
|
||||||
#endif // UTIL_REPL_SERVER_H
|
#endif // UTIL_REPL_SERVER_H
|
||||||
|
@ -80,6 +80,7 @@
|
|||||||
|
|
||||||
#include "../remote/remote.h"
|
#include "../remote/remote.h"
|
||||||
#include "../jrd/license.h"
|
#include "../jrd/license.h"
|
||||||
|
#include "../jrd/replication/Config.h"
|
||||||
#include "../common/file_params.h"
|
#include "../common/file_params.h"
|
||||||
#include "../remote/inet_proto.h"
|
#include "../remote/inet_proto.h"
|
||||||
#include "../remote/server/serve_proto.h"
|
#include "../remote/server/serve_proto.h"
|
||||||
@ -87,6 +88,7 @@
|
|||||||
#include "../yvalve/gds_proto.h"
|
#include "../yvalve/gds_proto.h"
|
||||||
#include "../common/utils_proto.h"
|
#include "../common/utils_proto.h"
|
||||||
#include "../common/classes/fb_string.h"
|
#include "../common/classes/fb_string.h"
|
||||||
|
#include "../common/classes/semaphore.h"
|
||||||
|
|
||||||
#include "firebird/Interface.h"
|
#include "firebird/Interface.h"
|
||||||
#include "../common/classes/ImplementHelper.h"
|
#include "../common/classes/ImplementHelper.h"
|
||||||
@ -109,8 +111,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "../common/classes/semaphore.h"
|
|
||||||
|
|
||||||
const char* TEMP_DIR = "/tmp";
|
const char* TEMP_DIR = "/tmp";
|
||||||
|
|
||||||
static void set_signal(int, void (*)(int));
|
static void set_signal(int, void (*)(int));
|
||||||
@ -124,6 +124,9 @@ static int INET_SERVER_start = 0;
|
|||||||
static void raiseLimit(int resource);
|
static void raiseLimit(int resource);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using namespace Firebird;
|
||||||
|
|
||||||
|
|
||||||
static void logSecurityDatabaseError(const char* path, ISC_STATUS* status)
|
static void logSecurityDatabaseError(const char* path, ISC_STATUS* status)
|
||||||
{
|
{
|
||||||
// If I/O error happened then rather likely we just miss standard security DB
|
// If I/O error happened then rather likely we just miss standard security DB
|
||||||
@ -131,7 +134,7 @@ static void logSecurityDatabaseError(const char* path, ISC_STATUS* status)
|
|||||||
if (fb_utils::containsErrorCode(status, isc_io_error))
|
if (fb_utils::containsErrorCode(status, isc_io_error))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Firebird::Syslog::Record(Firebird::Syslog::Error, "Security database error");
|
Syslog::Record(Syslog::Error, "Security database error");
|
||||||
gds__log_status(path, status);
|
gds__log_status(path, status);
|
||||||
if (isatty(2))
|
if (isatty(2))
|
||||||
{
|
{
|
||||||
@ -185,6 +188,8 @@ int CLIB_ROUTINE main( int argc, char** argv)
|
|||||||
bool standaloneClassic = false;
|
bool standaloneClassic = false;
|
||||||
bool super = false;
|
bool super = false;
|
||||||
|
|
||||||
|
int replPid = 0;
|
||||||
|
|
||||||
// It's very easy to detect that we are spawned - just check fd 0 to be a socket.
|
// It's very easy to detect that we are spawned - just check fd 0 to be a socket.
|
||||||
const int channel = 0;
|
const int channel = 0;
|
||||||
struct STAT stat0;
|
struct STAT stat0;
|
||||||
@ -279,7 +284,7 @@ int CLIB_ROUTINE main( int argc, char** argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Firebird::Config::getServerMode() == Firebird::MODE_CLASSIC)
|
if (Config::getServerMode() == MODE_CLASSIC)
|
||||||
{
|
{
|
||||||
if (!classic)
|
if (!classic)
|
||||||
standaloneClassic = true;
|
standaloneClassic = true;
|
||||||
@ -289,14 +294,15 @@ int CLIB_ROUTINE main( int argc, char** argv)
|
|||||||
if (classic)
|
if (classic)
|
||||||
{
|
{
|
||||||
gds__log("Server misconfigured - to start it from (x)inetd add ServerMode=Classic to firebird.conf");
|
gds__log("Server misconfigured - to start it from (x)inetd add ServerMode=Classic to firebird.conf");
|
||||||
Firebird::Syslog::Record(Firebird::Syslog::Error, "Server misconfigured - add ServerMode=Classic to firebird.conf");
|
Syslog::Record(Syslog::Error, "Server misconfigured - add ServerMode=Classic to firebird.conf");
|
||||||
exit(STARTUP_ERROR);
|
exit(STARTUP_ERROR);
|
||||||
}
|
}
|
||||||
INET_SERVER_flag |= SRVR_multi_client;
|
INET_SERVER_flag |= SRVR_multi_client;
|
||||||
super = true;
|
super = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // scope
|
{ // scope
|
||||||
Firebird::MasterInterfacePtr master;
|
MasterInterfacePtr master;
|
||||||
master->serverMode(super ? 1 : 0);
|
master->serverMode(super ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,7 +333,7 @@ int CLIB_ROUTINE main( int argc, char** argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !(defined(DEV_BUILD))
|
#if !(defined(DEV_BUILD))
|
||||||
if (Firebird::Config::getBugcheckAbort())
|
if (Config::getBugcheckAbort())
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// try to force core files creation
|
// try to force core files creation
|
||||||
@ -371,15 +377,15 @@ int CLIB_ROUTINE main( int argc, char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check firebird.conf presence - must be for server
|
// check firebird.conf presence - must be for server
|
||||||
if (Firebird::Config::missFirebirdConf())
|
if (Config::missFirebirdConf())
|
||||||
{
|
{
|
||||||
Firebird::Syslog::Record(Firebird::Syslog::Error, "Missing master config file firebird.conf");
|
Syslog::Record(Syslog::Error, "Missing master config file firebird.conf");
|
||||||
exit(STARTUP_ERROR);
|
exit(STARTUP_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!debug)
|
if (!debug)
|
||||||
{
|
{
|
||||||
const char* redirection_file = Firebird::Config::getOutputRedirectionFile();
|
const char* redirection_file = Config::getOutputRedirectionFile();
|
||||||
|
|
||||||
int stdout_no = fileno(stdout);
|
int stdout_no = fileno(stdout);
|
||||||
int stderr_no = fileno(stderr);
|
int stderr_no = fileno(stderr);
|
||||||
@ -417,20 +423,88 @@ int CLIB_ROUTINE main( int argc, char** argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Replication::Config::ReplicaList replicas;
|
||||||
|
Replication::Config::enumerate(replicas);
|
||||||
|
|
||||||
if (super || standaloneClassic)
|
if (super || standaloneClassic)
|
||||||
{
|
{
|
||||||
|
if (standaloneClassic && replicas.hasData())
|
||||||
|
{
|
||||||
|
// Start the replication server now (in the forked process),
|
||||||
|
// because INET_connect() never returns for the standalone Classic
|
||||||
|
|
||||||
|
if ((replPid = fork()) <= 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (replPid) // failed fork attempt
|
||||||
|
system_error::raise("fork", replPid);
|
||||||
|
|
||||||
|
// We've been forked successfully
|
||||||
|
FbLocalStatus localStatus;
|
||||||
|
if (!REPL_server(&localStatus, replicas, true))
|
||||||
|
localStatus.check();
|
||||||
|
}
|
||||||
|
catch (const Exception& ex)
|
||||||
|
{
|
||||||
|
const char* const errorMsg = "Replication server startup error";
|
||||||
|
iscLogException(errorMsg, ex);
|
||||||
|
Syslog::Record(Syslog::Error, errorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!replPid)
|
||||||
|
{
|
||||||
|
fb_shutdown(10000, fb_shutrsn_exit_called);
|
||||||
|
return FINI_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the network listener
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
port = INET_connect(protocol, 0, INET_SERVER_flag, 0, NULL);
|
port = INET_connect(protocol, 0, INET_SERVER_flag, 0, NULL);
|
||||||
}
|
}
|
||||||
catch (const Firebird::Exception& ex)
|
catch (const Exception& ex)
|
||||||
{
|
{
|
||||||
iscLogException("startup:INET_connect:", ex);
|
iscLogException("INET server startup error", ex);
|
||||||
Firebird::StaticStatusVector st;
|
|
||||||
ex.stuffException(st);
|
|
||||||
gds__print_status(st.begin());
|
|
||||||
exit(STARTUP_ERROR);
|
exit(STARTUP_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If INET_connect() returns NULL for the standalone classic, then game is over.
|
||||||
|
// Signal the forked replication server process to terminate and then exit.
|
||||||
|
|
||||||
|
if (!port && replPid > 0) // this implies standaloneClassic being true
|
||||||
|
{
|
||||||
|
if (!kill(replPid, SIGTERM))
|
||||||
|
{
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
// Wait up to one second for the replicator process to finish gracefully
|
||||||
|
for (unsigned n = 0; n < 10; n++)
|
||||||
|
{
|
||||||
|
Thread::sleep(100); // milliseconds
|
||||||
|
|
||||||
|
const auto res = waitpid(replPid, &status, WNOHANG);
|
||||||
|
|
||||||
|
if (res == replPid) // process is terminated
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (res < 0 && !SYSCALL_INTERRUPTED(errno)) // error
|
||||||
|
break;
|
||||||
|
|
||||||
|
// continue waiting otherwise
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force terminating the replicator process if it's still alive
|
||||||
|
if (!WIFEXITED(status))
|
||||||
|
kill(replPid, SIGKILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
fb_shutdown(10000, fb_shutrsn_exit_called);
|
||||||
|
return FINI_OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classic)
|
if (classic)
|
||||||
@ -439,13 +513,13 @@ int CLIB_ROUTINE main( int argc, char** argv)
|
|||||||
if (!port)
|
if (!port)
|
||||||
{
|
{
|
||||||
gds__log("Unable to start INET_server");
|
gds__log("Unable to start INET_server");
|
||||||
Firebird::Syslog::Record(Firebird::Syslog::Error, "Unable to start INET_server");
|
Syslog::Record(Syslog::Error, "Unable to start INET_server");
|
||||||
exit(STARTUP_ERROR);
|
exit(STARTUP_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // scope for interface ptr
|
{ // scope for interface ptr
|
||||||
Firebird::PluginManagerInterfacePtr pi;
|
PluginManagerInterfacePtr pi;
|
||||||
Auth::registerSrpServer(pi);
|
Auth::registerSrpServer(pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,7 +533,7 @@ int CLIB_ROUTINE main( int argc, char** argv)
|
|||||||
ISC_STATUS_ARRAY status;
|
ISC_STATUS_ARRAY status;
|
||||||
isc_db_handle db_handle = 0L;
|
isc_db_handle db_handle = 0L;
|
||||||
|
|
||||||
const Firebird::RefPtr<const Firebird::Config> defConf(Firebird::Config::getDefaultConfig());
|
const RefPtr<const Config> defConf(Config::getDefaultConfig());
|
||||||
const char* path = defConf->getSecurityDatabase();
|
const char* path = defConf->getSecurityDatabase();
|
||||||
const char dpb[] = {isc_dpb_version1, isc_dpb_sec_attach, 1, 1, isc_dpb_address_path, 0};
|
const char dpb[] = {isc_dpb_version1, isc_dpb_sec_attach, 1, 1, isc_dpb_address_path, 0};
|
||||||
|
|
||||||
@ -478,16 +552,18 @@ int CLIB_ROUTINE main( int argc, char** argv)
|
|||||||
}
|
}
|
||||||
} // end scope
|
} // end scope
|
||||||
|
|
||||||
fb_shutdown_callback(NULL, closePort, fb_shut_exit, port);
|
// Start replication server
|
||||||
|
|
||||||
Firebird::FbLocalStatus localStatus;
|
FbLocalStatus localStatus;
|
||||||
if (!REPL_server(&localStatus, false))
|
if (!REPL_server(&localStatus, replicas, false))
|
||||||
{
|
{
|
||||||
const char* errorMsg = "Replication server initialization error";
|
const char* const errorMsg = "Replication server startup error";
|
||||||
iscLogStatus(errorMsg, localStatus->getErrors());
|
iscLogStatus(errorMsg, localStatus->getErrors());
|
||||||
Firebird::Syslog::Record(Firebird::Syslog::Error, errorMsg);
|
Syslog::Record(Syslog::Error, errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fb_shutdown_callback(NULL, closePort, fb_shut_exit, port);
|
||||||
|
|
||||||
SRVR_multi_thread(port, INET_SERVER_flag);
|
SRVR_multi_thread(port, INET_SERVER_flag);
|
||||||
|
|
||||||
// perform atexit shutdown here when all globals in embedded library are active
|
// perform atexit shutdown here when all globals in embedded library are active
|
||||||
@ -496,9 +572,9 @@ int CLIB_ROUTINE main( int argc, char** argv)
|
|||||||
|
|
||||||
return FINI_OK;
|
return FINI_OK;
|
||||||
}
|
}
|
||||||
catch (const Firebird::Exception& ex)
|
catch (const Exception& ex)
|
||||||
{
|
{
|
||||||
Firebird::StaticStatusVector st;
|
StaticStatusVector st;
|
||||||
ex.stuffException(st);
|
ex.stuffException(st);
|
||||||
|
|
||||||
char s[100];
|
char s[100];
|
||||||
@ -506,8 +582,8 @@ int CLIB_ROUTINE main( int argc, char** argv)
|
|||||||
fb_interpret(s, sizeof(s), &status);
|
fb_interpret(s, sizeof(s), &status);
|
||||||
|
|
||||||
iscLogException("Firebird startup error:", ex);
|
iscLogException("Firebird startup error:", ex);
|
||||||
Firebird::Syslog::Record(Firebird::Syslog::Error, "Firebird startup error");
|
Syslog::Record(Syslog::Error, "Firebird startup error");
|
||||||
Firebird::Syslog::Record(Firebird::Syslog::Error, s);
|
Syslog::Record(Syslog::Error, s);
|
||||||
|
|
||||||
exit(STARTUP_ERROR);
|
exit(STARTUP_ERROR);
|
||||||
}
|
}
|
||||||
|
@ -96,6 +96,7 @@
|
|||||||
#include "../common/classes/semaphore.h"
|
#include "../common/classes/semaphore.h"
|
||||||
#include "../common/classes/FpeControl.h"
|
#include "../common/classes/FpeControl.h"
|
||||||
#include "../jrd/license.h"
|
#include "../jrd/license.h"
|
||||||
|
#include "../jrd/replication/Config.h"
|
||||||
#include "../utilities/install/install_nt.h"
|
#include "../utilities/install/install_nt.h"
|
||||||
#include "../remote/remote.h"
|
#include "../remote/remote.h"
|
||||||
#include "../remote/server/os/win32/cntl_proto.h"
|
#include "../remote/server/os/win32/cntl_proto.h"
|
||||||
@ -530,12 +531,18 @@ static THREAD_ENTRY_DECLARE start_connections_thread(THREAD_ENTRY_PARAM)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FbLocalStatus localStatus;
|
Replication::Config::ReplicaList replicas;
|
||||||
if (!REPL_server(&localStatus, false))
|
Replication::Config::enumerate(replicas);
|
||||||
|
|
||||||
|
if (replicas.hasData())
|
||||||
{
|
{
|
||||||
const char* errorMsg = "Replication server initialization error";
|
FbLocalStatus localStatus;
|
||||||
iscLogStatus(errorMsg, localStatus->getErrors());
|
if (!REPL_server(&localStatus, replicas, false))
|
||||||
Syslog::Record(Syslog::Error, errorMsg);
|
{
|
||||||
|
const char* errorMsg = "Replication server initialization error";
|
||||||
|
iscLogStatus(errorMsg, localStatus->getErrors());
|
||||||
|
Syslog::Record(Syslog::Error, errorMsg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user