pg_indent'ing all files…

Conflicts:
	version.h
This commit is contained in:
Christian Kruse
2014-03-06 16:07:01 +01:00
committed by Jaime Casanova
parent 069f9ff2ed
commit 1c67e105ff
16 changed files with 1494 additions and 1279 deletions

View File

@@ -71,6 +71,7 @@ check_dir(char *dir)
} }
#ifdef WIN32 #ifdef WIN32
/* /*
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
* released version * released version

View File

@@ -23,13 +23,14 @@
#include "repmgr.h" #include "repmgr.h"
void void
parse_config(const char *config_file, t_configuration_options *options) parse_config(const char *config_file, t_configuration_options * options)
{ {
char *s, buff[MAXLINELENGTH]; char *s,
buff[MAXLINELENGTH];
char name[MAXLEN]; char name[MAXLEN];
char value[MAXLEN]; char value[MAXLEN];
FILE *fp = fopen (config_file, "r"); FILE *fp = fopen(config_file, "r");
/* Initialize */ /* Initialize */
memset(options->cluster_name, 0, sizeof(options->cluster_name)); memset(options->cluster_name, 0, sizeof(options->cluster_name));
@@ -56,17 +57,18 @@ parse_config(const char *config_file, t_configuration_options *options)
options->retry_promote_interval_secs = 300; options->retry_promote_interval_secs = 300;
/* /*
* Since some commands don't require a config file at all, not * Since some commands don't require a config file at all, not having one
* having one isn't necessarily a problem. * isn't necessarily a problem.
*/ */
if (fp == NULL) if (fp == NULL)
{ {
log_err(_("Did not find the configuration file '%s', continuing\n"), config_file); log_err(_("Did not find the configuration file '%s', continuing\n"),
config_file);
return; return;
} }
/* Read next line */ /* Read next line */
while ((s = fgets (buff, sizeof buff, fp)) != NULL) while ((s = fgets(buff, sizeof buff, fp)) != NULL)
{ {
/* Skip blank lines and comments */ /* Skip blank lines and comments */
if (buff[0] == '\n' || buff[0] == '#') if (buff[0] == '\n' || buff[0] == '#')
@@ -77,22 +79,23 @@ parse_config(const char *config_file, t_configuration_options *options)
/* Copy into correct entry in parameters struct */ /* Copy into correct entry in parameters struct */
if (strcmp(name, "cluster") == 0) if (strcmp(name, "cluster") == 0)
strncpy (options->cluster_name, value, MAXLEN); strncpy(options->cluster_name, value, MAXLEN);
else if (strcmp(name, "node") == 0) else if (strcmp(name, "node") == 0)
options->node = atoi(value); options->node = atoi(value);
else if (strcmp(name, "conninfo") == 0) else if (strcmp(name, "conninfo") == 0)
strncpy (options->conninfo, value, MAXLEN); strncpy(options->conninfo, value, MAXLEN);
else if (strcmp(name, "rsync_options") == 0) else if (strcmp(name, "rsync_options") == 0)
strncpy (options->rsync_options, value, QUERY_STR_LEN); strncpy(options->rsync_options, value, QUERY_STR_LEN);
else if (strcmp(name, "ssh_options") == 0) else if (strcmp(name, "ssh_options") == 0)
strncpy (options->ssh_options, value, QUERY_STR_LEN); strncpy(options->ssh_options, value, QUERY_STR_LEN);
else if (strcmp(name, "loglevel") == 0) else if (strcmp(name, "loglevel") == 0)
strncpy (options->loglevel, value, MAXLEN); strncpy(options->loglevel, value, MAXLEN);
else if (strcmp(name, "logfacility") == 0) else if (strcmp(name, "logfacility") == 0)
strncpy (options->logfacility, value, MAXLEN); strncpy(options->logfacility, value, MAXLEN);
else if (strcmp(name, "failover") == 0) else if (strcmp(name, "failover") == 0)
{ {
char failoverstr[MAXLEN]; char failoverstr[MAXLEN];
strncpy(failoverstr, value, MAXLEN); strncpy(failoverstr, value, MAXLEN);
if (strcmp(failoverstr, "manual") == 0) if (strcmp(failoverstr, "manual") == 0)
@@ -120,9 +123,9 @@ parse_config(const char *config_file, t_configuration_options *options)
else if (strcmp(name, "reconnect_interval") == 0) else if (strcmp(name, "reconnect_interval") == 0)
options->reconnect_intvl = atoi(value); options->reconnect_intvl = atoi(value);
else if (strcmp(name, "pg_bindir") == 0) else if (strcmp(name, "pg_bindir") == 0)
strncpy (options->pg_bindir, value, MAXLEN); strncpy(options->pg_bindir, value, MAXLEN);
else if (strcmp(name, "pg_ctl_options") == 0) else if (strcmp(name, "pg_ctl_options") == 0)
strncpy (options->pgctl_options, value, MAXLEN); strncpy(options->pgctl_options, value, MAXLEN);
else if (strcmp(name, "logfile") == 0) else if (strcmp(name, "logfile") == 0)
strncpy(options->logfile, value, MAXLEN); strncpy(options->logfile, value, MAXLEN);
else if (strcmp(name, "monitor_interval_secs") == 0) else if (strcmp(name, "monitor_interval_secs") == 0)
@@ -134,10 +137,10 @@ parse_config(const char *config_file, t_configuration_options *options)
} }
/* Close file */ /* Close file */
fclose (fp); fclose(fp);
/* Check config settings */ /* Check config settings */
if (strnlen(options->cluster_name, MAXLEN)==0) if (strnlen(options->cluster_name, MAXLEN) == 0)
{ {
log_err(_("Cluster name is missing. Check the configuration file.\n")); log_err(_("Cluster name is missing. Check the configuration file.\n"));
exit(ERR_BAD_CONFIG); exit(ERR_BAD_CONFIG);
@@ -176,22 +179,23 @@ parse_config(const char *config_file, t_configuration_options *options)
char * char *
trim (char *s) trim(char *s)
{ {
/* Initialize start, end pointers */ /* Initialize start, end pointers */
char *s1 = s, *s2 = &s[strlen (s) - 1]; char *s1 = s,
*s2 = &s[strlen(s) - 1];
/* Trim and delimit right side */ /* Trim and delimit right side */
while ( (isspace (*s2)) && (s2 >= s1) ) while ((isspace(*s2)) && (s2 >= s1))
--s2; --s2;
*(s2+1) = '\0'; *(s2 + 1) = '\0';
/* Trim left side */ /* Trim left side */
while ( (isspace (*s1)) && (s1 < s2) ) while ((isspace(*s1)) && (s1 < s2))
++s1; ++s1;
/* Copy finished string */ /* Copy finished string */
memmove (s, s1, s2 - s1); memmove(s, s1, s2 - s1);
s[s2 - s1 + 1] = '\0'; s[s2 - s1 + 1] = '\0';
return s; return s;
@@ -206,7 +210,7 @@ parse_line(char *buff, char *name, char *value)
/* /*
* first we find the name of the parameter * first we find the name of the parameter
*/ */
for ( ; i < MAXLEN; ++i) for (; i < MAXLEN; ++i)
{ {
if (buff[i] != '=') if (buff[i] != '=')
name[j++] = buff[i]; name[j++] = buff[i];
@@ -219,7 +223,7 @@ parse_line(char *buff, char *name, char *value)
* Now the value * Now the value
*/ */
j = 0; j = 0;
for ( ++i ; i < MAXLEN; ++i) for (++i; i < MAXLEN; ++i)
if (buff[i] == '\'') if (buff[i] == '\'')
continue; continue;
else if (buff[i] != '\n') else if (buff[i] != '\n')
@@ -231,7 +235,7 @@ parse_line(char *buff, char *name, char *value)
} }
bool bool
reload_configuration(char *config_file, t_configuration_options *orig_options) reload_configuration(char *config_file, t_configuration_options * orig_options)
{ {
PGconn *conn; PGconn *conn;
@@ -313,15 +317,15 @@ reload_configuration(char *config_file, t_configuration_options *orig_options)
orig_options->master_response_timeout = new_options.master_response_timeout; orig_options->master_response_timeout = new_options.master_response_timeout;
orig_options->reconnect_attempts = new_options.reconnect_attempts; orig_options->reconnect_attempts = new_options.reconnect_attempts;
orig_options->reconnect_intvl = new_options.reconnect_intvl; orig_options->reconnect_intvl = new_options.reconnect_intvl;
/* /*
* XXX These ones can change with a simple SIGHUP? * XXX These ones can change with a simple SIGHUP?
*
strcpy (orig_options->loglevel, new_options.loglevel); * strcpy (orig_options->loglevel, new_options.loglevel); strcpy
strcpy (orig_options->logfacility, new_options.logfacility); * (orig_options->logfacility, new_options.logfacility);
*
logger_shutdown(); * logger_shutdown(); XXX do we have progname here ? logger_init(progname,
XXX do we have progname here ? * orig_options.loglevel, orig_options.logfacility);
logger_init(progname, orig_options.loglevel, orig_options.logfacility);
*/ */
return true; return true;

View File

@@ -49,9 +49,9 @@ typedef struct
#define T_CONFIGURATION_OPTIONS_INITIALIZER { "", -1, "", MANUAL_FAILOVER, -1, "", "", "", "", "", "", "", -1, -1, -1, "", "", "", 0, 0 } #define T_CONFIGURATION_OPTIONS_INITIALIZER { "", -1, "", MANUAL_FAILOVER, -1, "", "", "", "", "", "", "", -1, -1, -1, "", "", "", 0, 0 }
void parse_config(const char *config_file, t_configuration_options *options); void parse_config(const char *config_file, t_configuration_options * options);
void parse_line(char *buff, char *name, char *value); void parse_line(char *buff, char *name, char *value);
char *trim(char *s); char *trim(char *s);
bool reload_configuration(char *config_file, t_configuration_options *orig_options); bool reload_configuration(char *config_file, t_configuration_options * orig_options);
#endif #endif

View File

@@ -53,7 +53,8 @@ establishDBConnection(const char *conninfo, const bool exit_on_error)
} }
PGconn * PGconn *
establishDBConnectionByParams(const char *keywords[], const char *values[],const bool exit_on_error) establishDBConnectionByParams(const char *keywords[], const char *values[],
const bool exit_on_error)
{ {
/* Make a connection to the database */ /* Make a connection to the database */
PGconn *conn = PQconnectdbParams(keywords, values, true); PGconn *conn = PQconnectdbParams(keywords, values, true);
@@ -124,6 +125,7 @@ bool
is_pgup(PGconn *conn, int timeout) is_pgup(PGconn *conn, int timeout)
{ {
char sqlquery[QUERY_STR_LEN]; char sqlquery[QUERY_STR_LEN];
/* Check the connection status twice in case it changes after reset */ /* Check the connection status twice in case it changes after reset */
bool twice = false; bool twice = false;
@@ -159,8 +161,12 @@ is_pgup(PGconn *conn, int timeout)
break; break;
failed: failed:
/* we need to retry, because we might just have loose the connection once */
/*
* we need to retry, because we might just have loose the
* connection once
*/
if (twice) if (twice)
return false; return false;
PQreset(conn); /* reconnect */ PQreset(conn); /* reconnect */
@@ -176,7 +182,7 @@ failed:
* if 8 or inferior returns an empty string * if 8 or inferior returns an empty string
*/ */
char * char *
pg_version(PGconn *conn, char* major_version) pg_version(PGconn *conn, char *major_version)
{ {
PGresult *res; PGresult *res;
@@ -378,8 +384,8 @@ getMasterConnection(PGconn *standby_conn, char *schema, char *cluster,
/* /*
* Can't use the is_standby() function here because on error that * Can't use the is_standby() function here because on error that
* function closes the connection passed and exits. This still * function closes the connection passed and exits. This still needs
* needs to close master_conn first. * to close master_conn first.
*/ */
res2 = PQexec(master_conn, "SELECT pg_is_in_recovery()"); res2 = PQexec(master_conn, "SELECT pg_is_in_recovery()");
@@ -408,14 +414,13 @@ getMasterConnection(PGconn *standby_conn, char *schema, char *cluster,
} }
} }
/* If we finish this loop without finding a master then /*
* we doesn't have the info or the master has failed (or we * If we finish this loop without finding a master then we doesn't have
* reached max_connections or superuser_reserved_connections, * the info or the master has failed (or we reached max_connections or
* anything else I'm missing?). * superuser_reserved_connections, anything else I'm missing?).
* *
* Probably we will need to check the error to know if we need * Probably we will need to check the error to know if we need to start
* to start failover procedure or just fix some situation on the * failover procedure or just fix some situation on the standby.
* standby.
*/ */
PQclear(res1); PQclear(res1);
return NULL; return NULL;
@@ -423,8 +428,8 @@ getMasterConnection(PGconn *standby_conn, char *schema, char *cluster,
/* /*
* wait until current query finishes ignoring any results, this could be an async command * wait until current query finishes ignoring any results, this could be an
* or a cancelation of a query * async command or a cancelation of a query
* return 1 if Ok; 0 if any error ocurred; -1 if timeout reached * return 1 if Ok; 0 if any error ocurred; -1 if timeout reached
*/ */
int int
@@ -433,7 +438,9 @@ wait_connection_availability(PGconn *conn, long long timeout)
PGresult *res; PGresult *res;
fd_set read_set; fd_set read_set;
int sock = PQsocket(conn); int sock = PQsocket(conn);
struct timeval tmout, before, after; struct timeval tmout,
before,
after;
struct timezone tz; struct timezone tz;
/* recalc to microseconds */ /* recalc to microseconds */
@@ -450,10 +457,11 @@ wait_connection_availability(PGconn *conn, long long timeout)
if (PQisBusy(conn) == 0) if (PQisBusy(conn) == 0)
{ {
do { do
{
res = PQgetResult(conn); res = PQgetResult(conn);
PQclear(res); PQclear(res);
} while(res != NULL); } while (res != NULL);
break; break;
} }
@@ -505,9 +513,8 @@ CancelQuery(PGconn *conn, int timeout)
return false; return false;
/* /*
* PQcancel can only return 0 if socket()/connect()/send() * PQcancel can only return 0 if socket()/connect()/send() fails, in any
* fails, in any of those cases we can assume something * of those cases we can assume something bad happened to the connection
* bad happened to the connection
*/ */
if (PQcancel(pgcancel, errbuf, ERRBUFF_SIZE) == 0) if (PQcancel(pgcancel, errbuf, ERRBUFF_SIZE) == 0)
{ {

View File

@@ -29,7 +29,7 @@ PGconn *establishDBConnectionByParams(const char *keywords[],
int is_standby(PGconn *conn); int is_standby(PGconn *conn);
int is_witness(PGconn *conn, char *schema, char *cluster, int node_id); int is_witness(PGconn *conn, char *schema, char *cluster, int node_id);
bool is_pgup(PGconn *conn, int timeout); bool is_pgup(PGconn *conn, int timeout);
char *pg_version(PGconn *conn, char* major_version); char *pg_version(PGconn *conn, char *major_version);
int guc_set(PGconn *conn, const char *parameter, const char *op, int guc_set(PGconn *conn, const char *parameter, const char *op,
const char *value); const char *value);
int guc_set_typed(PGconn *conn, const char *parameter, const char *op, int guc_set_typed(PGconn *conn, const char *parameter, const char *op,
@@ -41,4 +41,5 @@ PGconn *getMasterConnection(PGconn *standby_conn, char *schema, char *cluster,
int wait_connection_availability(PGconn *conn, long long timeout); int wait_connection_availability(PGconn *conn, long long timeout);
bool CancelQuery(PGconn *conn, int timeout); bool CancelQuery(PGconn *conn, int timeout);
#endif #endif

37
log.c
View File

@@ -39,7 +39,9 @@
/* #define REPMGR_DEBUG */ /* #define REPMGR_DEBUG */
void stderr_log_with_level(const char *level_name, int level, const char *fmt, ...) { void
stderr_log_with_level(const char *level_name, int level, const char *fmt,...)
{
size_t len = strlen(fmt); size_t len = strlen(fmt);
char fmt1[len + 150]; char fmt1[len + 150];
time_t t; time_t t;
@@ -47,7 +49,8 @@ void stderr_log_with_level(const char *level_name, int level, const char *fmt, .
char buff[100]; char buff[100];
va_list ap; va_list ap;
if(log_level >= level) { if (log_level >= level)
{
time(&t); time(&t);
tm = localtime(&t); tm = localtime(&t);
@@ -64,15 +67,15 @@ void stderr_log_with_level(const char *level_name, int level, const char *fmt, .
} }
static int detect_log_level(const char* level); static int detect_log_level(const char *level);
static int detect_log_facility(const char* facility); static int detect_log_facility(const char *facility);
int log_type = REPMGR_STDERR; int log_type = REPMGR_STDERR;
int log_level = LOG_NOTICE; int log_level = LOG_NOTICE;
bool logger_init(t_configuration_options *opts, const char* ident, const char* level, const char* facility) bool
logger_init(t_configuration_options * opts, const char *ident, const char *level, const char *facility)
{ {
int l; int l;
int f; int f;
@@ -134,17 +137,17 @@ bool logger_init(t_configuration_options *opts, const char* ident, const char* l
if (log_type == REPMGR_SYSLOG) if (log_type == REPMGR_SYSLOG)
{ {
setlogmask (LOG_UPTO (log_level)); setlogmask(LOG_UPTO(log_level));
openlog (ident, LOG_CONS | LOG_PID | LOG_NDELAY, syslog_facility); openlog(ident, LOG_CONS | LOG_PID | LOG_NDELAY, syslog_facility);
stderr_log_notice(_("Setup syslog (level: %s, facility: %s)\n"), level, facility); stderr_log_notice(_("Setup syslog (level: %s, facility: %s)\n"), level, facility);
} }
#endif #endif
if (*opts->logfile) if (*opts->logfile)
{ {
FILE *fd; FILE *fd;
fd = freopen(opts->logfile, "a", stderr); fd = freopen(opts->logfile, "a", stderr);
if (fd == NULL) if (fd == NULL)
@@ -158,9 +161,9 @@ bool logger_init(t_configuration_options *opts, const char* ident, const char* l
} }
bool logger_shutdown(void) bool
logger_shutdown(void)
{ {
#ifdef HAVE_SYSLOG #ifdef HAVE_SYSLOG
if (log_type == REPMGR_SYSLOG) if (log_type == REPMGR_SYSLOG)
closelog(); closelog();
@@ -174,13 +177,15 @@ bool logger_shutdown(void)
* options, which might increase requested logging over what's specified * options, which might increase requested logging over what's specified
* in the regular configuration file. * in the regular configuration file.
*/ */
void logger_min_verbose(int minimum) void
logger_min_verbose(int minimum)
{ {
if (log_level < minimum) if (log_level < minimum)
log_level = minimum; log_level = minimum;
} }
int detect_log_level(const char* level) int
detect_log_level(const char *level)
{ {
if (!strcmp(level, "DEBUG")) if (!strcmp(level, "DEBUG"))
return LOG_DEBUG; return LOG_DEBUG;
@@ -202,13 +207,15 @@ int detect_log_level(const char* level)
return 0; return 0;
} }
int detect_log_facility(const char* facility) int
detect_log_facility(const char *facility)
{ {
int local = 0; int local = 0;
if (!strncmp(facility, "LOCAL", 5) && strlen(facility) == 6) if (!strncmp(facility, "LOCAL", 5) && strlen(facility) == 6)
{ {
local = atoi (&facility[5]); local = atoi(&facility[5]);
switch (local) switch (local)
{ {

11
log.h
View File

@@ -25,7 +25,9 @@
#define REPMGR_SYSLOG 1 #define REPMGR_SYSLOG 1
#define REPMGR_STDERR 2 #define REPMGR_STDERR 2
void stderr_log_with_level(const char *level_name, int level, const char *fmt, ...) __attribute__ ((format (PG_PRINTF_ATTRIBUTE, 3, 4))); void
stderr_log_with_level(const char *level_name, int level, const char *fmt,...)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
/* Standard error logging */ /* Standard error logging */
#define stderr_log_debug(...) stderr_log_with_level("DEBUG", LOG_DEBUG, __VA_ARGS__) #define stderr_log_debug(...) stderr_log_with_level("DEBUG", LOG_DEBUG, __VA_ARGS__)
@@ -88,7 +90,6 @@ void stderr_log_with_level(const char *level_name, int level, const char *fmt, .
if (log_type == REPMGR_SYSLOG) syslog(LOG_ALERT, __VA_ARGS__); \ if (log_type == REPMGR_SYSLOG) syslog(LOG_ALERT, __VA_ARGS__); \
else stderr_log_alert(__VA_ARGS__); \ else stderr_log_alert(__VA_ARGS__); \
} }
#else #else
#define LOG_EMERG 0 /* system is unusable */ #define LOG_EMERG 0 /* system is unusable */
@@ -108,13 +109,15 @@ void stderr_log_with_level(const char *level_name, int level, const char *fmt, .
#define log_crit(...) stderr_log_crit(__VA_ARGS__) #define log_crit(...) stderr_log_crit(__VA_ARGS__)
#define log_alert(...) stderr_log_alert(__VA_ARGS__) #define log_alert(...) stderr_log_alert(__VA_ARGS__)
#define log_emerg(...) stderr_log_emerg(__VA_ARGS__) #define log_emerg(...) stderr_log_emerg(__VA_ARGS__)
#endif #endif
/* Logger initialisation and shutdown */ /* Logger initialisation and shutdown */
bool logger_shutdown(void); bool logger_shutdown(void);
bool logger_init(t_configuration_options *opts, const char* ident, const char* level, const char* facility);
bool logger_init(t_configuration_options * opts, const char *ident,
const char *level, const char *facility);
void logger_min_verbose(int minimum); void logger_min_verbose(int minimum);
extern int log_type; extern int log_type;

460
repmgr.c

File diff suppressed because it is too large Load Diff

333
repmgrd.c
View File

@@ -49,21 +49,20 @@ const XLogRecPtr InvalidXLogRecPtr = {0, 0};
#endif #endif
#if PG_VERSION_NUM >= 90300 #if PG_VERSION_NUM >= 90300
#define XLAssign(a, b) \ #define XLAssign(a, b) \
a = b a = b
#define XLAssignValue(a, xlogid, xrecoff) \ #define XLAssignValue(a, xlogid, xrecoff) \
a = xrecoff a = xrecoff
#define XLByteLT(a, b) \ #define XLByteLT(a, b) \
(a < b) (a < b)
#else #else
#define XLAssign(a, b) \ #define XLAssign(a, b) \
a.xlogid = b.xlogid; \ a.xlogid = b.xlogid; \
a.xrecoff = b.xrecoff a.xrecoff = b.xrecoff
#define XLAssignValue(a, uxlogid, uxrecoff) \ #define XLAssignValue(a, uxlogid, uxrecoff) \
a.xlogid = uxlogid; \ a.xlogid = uxlogid; \
a.xrecoff = uxrecoff a.xrecoff = uxrecoff
#endif #endif
@@ -115,7 +114,7 @@ char *pid_file = NULL;
*/ */
t_configuration_options config = T_CONFIGURATION_OPTIONS_INITIALIZER; t_configuration_options config = T_CONFIGURATION_OPTIONS_INITIALIZER;
static void help(const char* progname); static void help(const char *progname);
static void usage(void); static void usage(void);
static void checkClusterConfiguration(PGconn *conn); static void checkClusterConfiguration(PGconn *conn);
static void checkNodeConfiguration(void); static void checkNodeConfiguration(void);
@@ -148,7 +147,8 @@ static void do_daemonize(void);
static void check_and_create_pid_file(const char *pid_file); static void check_and_create_pid_file(const char *pid_file);
static void static void
CloseConnections() { CloseConnections()
{
if (primaryConn != NULL && PQisBusy(primaryConn) == 1) if (primaryConn != NULL && PQisBusy(primaryConn) == 1)
CancelQuery(primaryConn, local_options.master_response_timeout); CancelQuery(primaryConn, local_options.master_response_timeout);
@@ -177,11 +177,13 @@ main(int argc, char **argv)
}; };
int optindex; int optindex;
int c, ret; int c,
ret;
bool daemonize = false; bool daemonize = false;
FILE *fd; FILE *fd;
char standby_version[MAXVERSIONSTR], *ret_ver; char standby_version[MAXVERSIONSTR],
*ret_ver;
progname = get_progname(argv[0]); progname = get_progname(argv[0]);
@@ -234,9 +236,9 @@ main(int argc, char **argv)
check_and_create_pid_file(pid_file); check_and_create_pid_file(pid_file);
} }
#ifndef WIN32 #ifndef WIN32
setup_event_handlers(); setup_event_handlers();
#endif #endif
/* /*
* Read the configuration file: repmgr.conf * Read the configuration file: repmgr.conf
@@ -263,7 +265,8 @@ main(int argc, char **argv)
strerror(errno)); strerror(errno));
} }
logger_init(&local_options, progname, local_options.loglevel, local_options.logfacility); logger_init(&local_options, progname, local_options.loglevel,
local_options.logfacility);
if (verbose) if (verbose)
logger_min_verbose(LOG_INFO); logger_min_verbose(LOG_INFO);
@@ -278,9 +281,11 @@ main(int argc, char **argv)
} }
} }
snprintf(repmgr_schema, MAXLEN, "%s%s", DEFAULT_REPMGR_SCHEMA_PREFIX, local_options.cluster_name); snprintf(repmgr_schema, MAXLEN, "%s%s", DEFAULT_REPMGR_SCHEMA_PREFIX,
local_options.cluster_name);
log_info(_("%s Connecting to database '%s'\n"), progname, local_options.conninfo); log_info(_("%s Connecting to database '%s'\n"), progname,
local_options.conninfo);
myLocalConn = establishDBConnection(local_options.conninfo, true); myLocalConn = establishDBConnection(local_options.conninfo, true);
/* should be v9 or better */ /* should be v9 or better */
@@ -288,26 +293,26 @@ main(int argc, char **argv)
ret_ver = pg_version(myLocalConn, standby_version); ret_ver = pg_version(myLocalConn, standby_version);
if (ret_ver == NULL || strcmp(standby_version, "") == 0) if (ret_ver == NULL || strcmp(standby_version, "") == 0)
{ {
if(ret_ver != NULL) if (ret_ver != NULL)
log_err(_("%s needs standby to be PostgreSQL 9.0 or better\n"), progname); log_err(_("%s needs standby to be PostgreSQL 9.0 or better\n"),
progname);
terminate(ERR_BAD_CONFIG); terminate(ERR_BAD_CONFIG);
} }
/* /*
* MAIN LOOP * MAIN LOOP This loops cicles once per failover and at startup
* This loops cicles once per failover and at startup * Requisites: - myLocalConn needs to be already setted with an active
* Requisites: * connection - no master connection
* - myLocalConn needs to be already setted with an active connection
* - no master connection
*/ */
do do
{ {
/* /*
* Set my server mode, establish a connection to primary * Set my server mode, establish a connection to primary and start
* and start monitor * monitor
*/ */
ret = is_witness(myLocalConn, repmgr_schema, local_options.cluster_name, local_options.node); ret = is_witness(myLocalConn, repmgr_schema,
local_options.cluster_name, local_options.node);
if (ret == 1) if (ret == 1)
myLocalMode = WITNESS_MODE; myLocalMode = WITNESS_MODE;
@@ -321,9 +326,11 @@ main(int argc, char **argv)
myLocalMode = PRIMARY_MODE; myLocalMode = PRIMARY_MODE;
} }
/* XXX we did this before changing is_standby() to return int; we /*
* XXX we did this before changing is_standby() to return int; we
* should not exit at this point, but for now we do until we have a * should not exit at this point, but for now we do until we have a
* better strategy */ * better strategy
*/
if (ret == -1) if (ret == -1)
terminate(1); terminate(1);
@@ -331,7 +338,8 @@ main(int argc, char **argv)
{ {
case PRIMARY_MODE: case PRIMARY_MODE:
primary_options.node = local_options.node; primary_options.node = local_options.node;
strncpy(primary_options.conninfo, local_options.conninfo, MAXLEN); strncpy(primary_options.conninfo, local_options.conninfo,
MAXLEN);
primaryConn = myLocalConn; primaryConn = myLocalConn;
checkClusterConfiguration(myLocalConn); checkClusterConfiguration(myLocalConn);
@@ -345,36 +353,42 @@ main(int argc, char **argv)
update_registration(); update_registration();
} }
log_info(_("%s Starting continuous primary connection check\n"), progname); log_info(_("%s Starting continuous primary connection check\n"),
progname);
/* Check that primary is still alive, and standbies are sending info */
/* /*
* Every local_options.monitor_interval_secs seconds, do master checks * Check that primary is still alive, and standbies are
* XXX * sending info
* Check that standbies are sending info */
/*
* Every local_options.monitor_interval_secs seconds, do
* master checks XXX Check that standbies are sending info
*/ */
do do
{ {
if (CheckConnection(primaryConn, "master")) if (CheckConnection(primaryConn, "master"))
{ {
/* /*
CheckActiveStandbiesConnections(); * CheckActiveStandbiesConnections();
CheckInactiveStandbies(); * CheckInactiveStandbies();
*/ */
sleep(local_options.monitor_interval_secs); sleep(local_options.monitor_interval_secs);
} }
else else
{ {
/* XXX /*
* May we do something more verbose ? * XXX May we do something more verbose ?
*/ */
terminate(1); terminate(1);
} }
if (got_SIGHUP) if (got_SIGHUP)
{ {
/* if we can reload, then could need to change myLocalConn */ /*
* if we can reload, then could need to change
* myLocalConn
*/
if (reload_configuration(config_file, &local_options)) if (reload_configuration(config_file, &local_options))
{ {
PQfinish(myLocalConn); PQfinish(myLocalConn);
@@ -384,6 +398,7 @@ main(int argc, char **argv)
if (*local_options.logfile) if (*local_options.logfile)
{ {
FILE *fd; FILE *fd;
fd = freopen(local_options.logfile, "a", stderr); fd = freopen(local_options.logfile, "a", stderr);
if (fd == NULL) if (fd == NULL)
{ {
@@ -423,15 +438,18 @@ main(int argc, char **argv)
} }
/* /*
* Every local_options.monitor_interval_secs seconds, do checks * Every local_options.monitor_interval_secs seconds, do
* checks
*/ */
if (myLocalMode == WITNESS_MODE) if (myLocalMode == WITNESS_MODE)
{ {
log_info(_("%s Starting continuous witness node monitoring\n"), progname); log_info(_("%s Starting continuous witness node monitoring\n"),
progname);
} }
else if (myLocalMode == STANDBY_MODE) else if (myLocalMode == STANDBY_MODE)
{ {
log_info(_("%s Starting continuous standby node monitoring\n"), progname); log_info(_("%s Starting continuous standby node monitoring\n"),
progname);
} }
do do
@@ -444,7 +462,10 @@ main(int argc, char **argv)
if (got_SIGHUP) if (got_SIGHUP)
{ {
/* if we can reload, then could need to change myLocalConn */ /*
* if we can reload, then could need to change
* myLocalConn
*/
if (reload_configuration(config_file, &local_options)) if (reload_configuration(config_file, &local_options))
{ {
PQfinish(myLocalConn); PQfinish(myLocalConn);
@@ -456,7 +477,8 @@ main(int argc, char **argv)
} while (!failover_done); } while (!failover_done);
break; break;
default: default:
log_err(_("%s: Unrecognized mode for node %d\n"), progname, local_options.node); log_err(_("%s: Unrecognized mode for node %d\n"), progname,
local_options.node);
} }
failover_done = false; failover_done = false;
@@ -485,13 +507,17 @@ WitnessMonitor(void)
* Check if the master is still available, if after 5 minutes of retries * Check if the master is still available, if after 5 minutes of retries
* we cannot reconnect, return false. * we cannot reconnect, return false.
*/ */
CheckConnection(primaryConn, "master"); /* this take up to local_options.reconnect_attempts * local_options.reconnect_intvl seconds */ CheckConnection(primaryConn, "master"); /* this take up to
* local_options.reconnect_atte
* mpts *
* local_options.reconnect_intv
* l seconds */
if (PQstatus(primaryConn) != CONNECTION_OK) if (PQstatus(primaryConn) != CONNECTION_OK)
{ {
/* /*
* If we can't reconnect, just exit... * If we can't reconnect, just exit... XXX we need to make witness
* XXX we need to make witness connect to the new master * connect to the new master
*/ */
terminate(0); terminate(0);
} }
@@ -501,12 +527,13 @@ WitnessMonitor(void)
return; return;
/* /*
* Cancel any query that is still being executed, * Cancel any query that is still being executed, so i can insert the
* so i can insert the current record * current record
*/ */
if (!CancelQuery(primaryConn, local_options.master_response_timeout)) if (!CancelQuery(primaryConn, local_options.master_response_timeout))
return; return;
if (wait_connection_availability(primaryConn, local_options.master_response_timeout) != 1) if (wait_connection_availability(primaryConn,
local_options.master_response_timeout) != 1)
return; return;
/* Get local xlog info */ /* Get local xlog info */
@@ -532,11 +559,12 @@ WitnessMonitor(void)
"VALUES(%d, %d, '%s'::timestamp with time zone, " "VALUES(%d, %d, '%s'::timestamp with time zone, "
" pg_current_xlog_location(), null, " " pg_current_xlog_location(), null, "
" 0, 0)", " 0, 0)",
repmgr_schema, primary_options.node, local_options.node, monitor_witness_timestamp); repmgr_schema, primary_options.node, local_options.node,
monitor_witness_timestamp);
/* /*
* Execute the query asynchronously, but don't check for a result. We * Execute the query asynchronously, but don't check for a result. We will
* will check the result next time we pause for a monitor step. * check the result next time we pause for a monitor step.
*/ */
log_debug("WitnessMonitor: %s\n", sqlquery); log_debug("WitnessMonitor: %s\n", sqlquery);
if (PQsendQuery(primaryConn, sqlquery) == 0) if (PQsendQuery(primaryConn, sqlquery) == 0)
@@ -564,14 +592,19 @@ StandbyMonitor(void)
unsigned long long int lsn_standby_received; unsigned long long int lsn_standby_received;
unsigned long long int lsn_standby_applied; unsigned long long int lsn_standby_applied;
int connection_retries, ret; int connection_retries,
ret;
bool did_retry = false; bool did_retry = false;
/* /*
* Check if the master is still available, if after 5 minutes of retries * Check if the master is still available, if after 5 minutes of retries
* we cannot reconnect, try to get a new master. * we cannot reconnect, try to get a new master.
*/ */
CheckConnection(primaryConn, "master"); /* this take up to local_options.reconnect_attempts * local_options.reconnect_intvl seconds */ CheckConnection(primaryConn, "master"); /* this take up to
* local_options.reconnect_atte
* mpts *
* local_options.reconnect_intv
* l seconds */
if (!CheckConnection(myLocalConn, "standby")) if (!CheckConnection(myLocalConn, "standby"))
{ {
@@ -593,16 +626,24 @@ StandbyMonitor(void)
local_options.cluster_name, &primary_options.node, NULL); local_options.cluster_name, &primary_options.node, NULL);
if (PQstatus(primaryConn) == CONNECTION_OK) if (PQstatus(primaryConn) == CONNECTION_OK)
{ {
/* Connected, we can continue the process so break the loop */ /*
log_err(_("Connected to node %d, continue monitoring.\n"), primary_options.node); * Connected, we can continue the process so break the
* loop
*/
log_err(_("Connected to node %d, continue monitoring.\n"),
primary_options.node);
break; break;
} }
else else
{ {
log_err(_("We haven't found a new master, waiting before retry...\n")); log_err(_("We haven't found a new master, waiting before retry...\n"));
/* wait local_options.retry_promote_interval_secs minutes before retries,
* after 6 failures (6 * local_options.monitor_interval_secs /*
* seconds) we stop trying */ * wait local_options.retry_promote_interval_secs minutes
* before retries, after 6 failures (6 *
* local_options.monitor_interval_secs seconds) we stop
* trying
*/
sleep(local_options.retry_promote_interval_secs); sleep(local_options.retry_promote_interval_secs);
} }
} }
@@ -616,8 +657,8 @@ StandbyMonitor(void)
else if (local_options.failover == AUTOMATIC_FAILOVER) else if (local_options.failover == AUTOMATIC_FAILOVER)
{ {
/* /*
* When we returns from this function we will have a new primary and * When we returns from this function we will have a new primary
* a new primaryConn * and a new primaryConn
*/ */
do_failover(); do_failover();
return; return;
@@ -625,7 +666,8 @@ StandbyMonitor(void)
} }
/* Check if we still are a standby, we could have been promoted */ /* Check if we still are a standby, we could have been promoted */
do { do
{
ret = is_standby(myLocalConn); ret = is_standby(myLocalConn);
switch (ret) switch (ret)
@@ -646,7 +688,7 @@ StandbyMonitor(void)
break; break;
} }
} while(ret == -1); } while (ret == -1);
if (did_retry) if (did_retry)
{ {
@@ -658,8 +700,8 @@ StandbyMonitor(void)
return; return;
/* /*
* Cancel any query that is still being executed, * Cancel any query that is still being executed, so i can insert the
* so i can insert the current record * current record
*/ */
if (!CancelQuery(primaryConn, local_options.master_response_timeout)) if (!CancelQuery(primaryConn, local_options.master_response_timeout))
return; return;
@@ -682,8 +724,8 @@ StandbyMonitor(void)
} }
strncpy(monitor_standby_timestamp, PQgetvalue(res, 0, 0), MAXLEN); strncpy(monitor_standby_timestamp, PQgetvalue(res, 0, 0), MAXLEN);
strncpy(last_wal_standby_received , PQgetvalue(res, 0, 1), MAXLEN); strncpy(last_wal_standby_received, PQgetvalue(res, 0, 1), MAXLEN);
strncpy(last_wal_standby_applied , PQgetvalue(res, 0, 2), MAXLEN); strncpy(last_wal_standby_applied, PQgetvalue(res, 0, 2), MAXLEN);
strncpy(last_wal_standby_applied_timestamp, PQgetvalue(res, 0, 3), MAXLEN); strncpy(last_wal_standby_applied_timestamp, PQgetvalue(res, 0, 3), MAXLEN);
PQclear(res); PQclear(res);
@@ -722,8 +764,8 @@ StandbyMonitor(void)
(lsn_standby_received - lsn_standby_applied)); (lsn_standby_received - lsn_standby_applied));
/* /*
* Execute the query asynchronously, but don't check for a result. We * Execute the query asynchronously, but don't check for a result. We will
* will check the result next time we pause for a monitor step. * check the result next time we pause for a monitor step.
*/ */
log_debug("StandbyMonitor: %s\n", sqlquery); log_debug("StandbyMonitor: %s\n", sqlquery);
if (PQsendQuery(primaryConn, sqlquery) == 0) if (PQsendQuery(primaryConn, sqlquery) == 0)
@@ -756,8 +798,8 @@ do_failover(void)
PGconn *nodeConn = NULL; PGconn *nodeConn = NULL;
/* /*
* will get info about until 50 nodes, * will get info about until 50 nodes, which seems to be large enough for
* which seems to be large enough for most scenarios * most scenarios
*/ */
nodeInfo nodes[50]; nodeInfo nodes[50];
@@ -785,21 +827,28 @@ do_failover(void)
total_nodes = PQntuples(res); total_nodes = PQntuples(res);
log_debug(_("%s: there are %d nodes registered\n"), progname, total_nodes); log_debug(_("%s: there are %d nodes registered\n"), progname, total_nodes);
/* Build an array with the nodes and indicate which ones are visible and ready */ /*
* Build an array with the nodes and indicate which ones are visible and
* ready
*/
for (i = 0; i < total_nodes; i++) for (i = 0; i < total_nodes; i++)
{ {
nodes[i].nodeId = atoi(PQgetvalue(res, i, 0)); nodes[i].nodeId = atoi(PQgetvalue(res, i, 0));
strncpy(nodes[i].conninfostr, PQgetvalue(res, i, 1), MAXLEN); strncpy(nodes[i].conninfostr, PQgetvalue(res, i, 1), MAXLEN);
nodes[i].is_witness = (strcmp(PQgetvalue(res, i, 2), "t") == 0) ? true : false; nodes[i].is_witness = (strcmp(PQgetvalue(res, i, 2), "t") == 0) ? true : false;
/* Initialize on false so if we can't reach this node we know that later */ /*
* Initialize on false so if we can't reach this node we know that
* later
*/
nodes[i].is_visible = false; nodes[i].is_visible = false;
nodes[i].is_ready = false; nodes[i].is_ready = false;
XLAssignValue(nodes[i].xlog_location, 0, 0); XLAssignValue(nodes[i].xlog_location, 0, 0);
log_debug(_("%s: node=%d conninfo=\"%s\" witness=%s\n"), log_debug(_("%s: node=%d conninfo=\"%s\" witness=%s\n"),
progname, nodes[i].nodeId, nodes[i].conninfostr, (nodes[i].is_witness) ? "true" : "false"); progname, nodes[i].nodeId, nodes[i].conninfostr,
(nodes[i].is_witness) ? "true" : "false");
nodeConn = establishDBConnection(nodes[i].conninfostr, false); nodeConn = establishDBConnection(nodes[i].conninfostr, false);
@@ -819,11 +868,12 @@ do_failover(void)
} }
PQclear(res); PQclear(res);
log_debug(_("Total nodes counted: registered=%d, visible=%d\n"), total_nodes, visible_nodes); log_debug(_("Total nodes counted: registered=%d, visible=%d\n"),
total_nodes, visible_nodes);
/* /*
* am i on the group that should keep alive? * am i on the group that should keep alive? if i see less than half of
* if i see less than half of total_nodes then i should do nothing * total_nodes then i should do nothing
*/ */
if (visible_nodes < (total_nodes / 2.0)) if (visible_nodes < (total_nodes / 2.0))
{ {
@@ -844,9 +894,11 @@ do_failover(void)
continue; continue;
nodeConn = establishDBConnection(nodes[i].conninfostr, false); nodeConn = establishDBConnection(nodes[i].conninfostr, false);
/* XXX
* This shouldn't happen, if this happens it means this is a major problem /*
* maybe network outages? anyway, is better for a human to react * XXX This shouldn't happen, if this happens it means this is a major
* problem maybe network outages? anyway, is better for a human to
* react
*/ */
if (PQstatus(nodeConn) != CONNECTION_OK) if (PQstatus(nodeConn) != CONNECTION_OK)
{ {
@@ -861,7 +913,8 @@ do_failover(void)
res = PQexec(nodeConn, sqlquery); res = PQexec(nodeConn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK) if (PQresultStatus(res) != PGRES_TUPLES_OK)
{ {
log_info(_("Can't get node's last standby location: %s\n"), PQerrorMessage(nodeConn)); log_info(_("Can't get node's last standby location: %s\n"),
PQerrorMessage(nodeConn));
log_info(_("Connection details: %s\n"), nodes[i].conninfostr); log_info(_("Connection details: %s\n"), nodes[i].conninfostr);
PQclear(res); PQclear(res);
PQfinish(nodeConn); PQfinish(nodeConn);
@@ -869,7 +922,8 @@ do_failover(void)
} }
if (sscanf(PQgetvalue(res, 0, 0), "%X/%X", &uxlogid, &uxrecoff) != 2) if (sscanf(PQgetvalue(res, 0, 0), "%X/%X", &uxlogid, &uxrecoff) != 2)
log_info(_("could not parse transaction log location \"%s\"\n"), PQgetvalue(res, 0, 0)); log_info(_("could not parse transaction log location \"%s\"\n"),
PQgetvalue(res, 0, 0));
log_debug("XLog position of node %d: log id=%u (%X), offset=%u (%X)\n", log_debug("XLog position of node %d: log id=%u (%X), offset=%u (%X)\n",
nodes[i].nodeId, uxlogid, uxlogid, uxrecoff, uxrecoff); nodes[i].nodeId, uxlogid, uxlogid, uxrecoff, uxrecoff);
@@ -894,7 +948,9 @@ do_failover(void)
res = PQexec(myLocalConn, sqlquery); res = PQexec(myLocalConn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK) if (PQresultStatus(res) != PGRES_TUPLES_OK)
{ {
log_err(_("PQexec failed: %s.\nReport an invalid value to not be considered as new primary and exit.\n"), PQerrorMessage(myLocalConn)); log_err(_("PQexec failed: %s.\nReport an invalid value to not be "
" considered as new primary and exit.\n"),
PQerrorMessage(myLocalConn));
PQclear(res); PQclear(res);
sprintf(last_wal_standby_applied, "'%X/%X'", 0, 0); sprintf(last_wal_standby_applied, "'%X/%X'", 0, 0);
update_shared_memory(last_wal_standby_applied); update_shared_memory(last_wal_standby_applied);
@@ -910,8 +966,8 @@ do_failover(void)
while (!nodes[i].is_ready) while (!nodes[i].is_ready)
{ {
/* /*
* the witness will always be masked as ready if it's still * the witness will always be masked as ready if it's still not
* not marked that way and avoid a useless query * marked that way and avoid a useless query
*/ */
if (nodes[i].is_witness) if (nodes[i].is_witness)
{ {
@@ -932,25 +988,32 @@ do_failover(void)
break; break;
nodeConn = establishDBConnection(nodes[i].conninfostr, false); nodeConn = establishDBConnection(nodes[i].conninfostr, false);
/* XXX
* This shouldn't happen, if this happens it means this is a major problem /*
* maybe network outages? anyway, is better for a human to react * XXX This shouldn't happen, if this happens it means this is a
* major problem maybe network outages? anyway, is better for a
* human to react
*/ */
if (PQstatus(nodeConn) != CONNECTION_OK) if (PQstatus(nodeConn) != CONNECTION_OK)
{ {
/* XXX */ /* XXX */
log_info(_("At this point, it could be some race conditions that are acceptable, assume the node is restarting and starting failover procedure\n")); log_info(_("At this point, it could be some race conditions "
"that are acceptable, assume the node is restarting "
"and starting failover procedure\n"));
break; break;
} }
uxlogid = 0; uxlogid = 0;
uxrecoff = 0; uxrecoff = 0;
sqlquery_snprintf(sqlquery, "SELECT %s.repmgr_get_last_standby_location()", repmgr_schema); sqlquery_snprintf(sqlquery, "SELECT %s.repmgr_get_last_standby_location()",
repmgr_schema);
res = PQexec(nodeConn, sqlquery); res = PQexec(nodeConn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK) if (PQresultStatus(res) != PGRES_TUPLES_OK)
{ {
log_err(_("PQexec failed: %s.\nReport an invalid value to not be considered as new primary and exit.\n"), PQerrorMessage(nodeConn)); log_err(_("PQexec failed: %s.\nReport an invalid value to not"
"be considered as new primary and exit.\n"),
PQerrorMessage(nodeConn));
PQclear(res); PQclear(res);
PQfinish(nodeConn); PQfinish(nodeConn);
terminate(ERR_DB_QUERY); terminate(ERR_DB_QUERY);
@@ -958,7 +1021,8 @@ do_failover(void)
if (sscanf(PQgetvalue(res, 0, 0), "%X/%X", &uxlogid, &uxrecoff) != 2) if (sscanf(PQgetvalue(res, 0, 0), "%X/%X", &uxlogid, &uxrecoff) != 2)
{ {
log_info(_("could not parse transaction log location \"%s\"\n"), PQgetvalue(res, 0, 0)); log_info(_("could not parse transaction log location \"%s\"\n"),
PQgetvalue(res, 0, 0));
/* we can't do anything but fail at this point... */ /* we can't do anything but fail at this point... */
if (*PQgetvalue(res, 0, 0) == '\0') if (*PQgetvalue(res, 0, 0) == '\0')
@@ -1009,7 +1073,10 @@ do_failover(void)
if (!find_best) if (!find_best)
{ {
/* start with the first ready node, and then move on to the next one */ /*
* start with the first ready node, and then move on to the next
* one
*/
best_candidate.nodeId = nodes[i].nodeId; best_candidate.nodeId = nodes[i].nodeId;
XLAssign(best_candidate.xlog_location, nodes[i].xlog_location); XLAssign(best_candidate.xlog_location, nodes[i].xlog_location);
best_candidate.is_ready = nodes[i].is_ready; best_candidate.is_ready = nodes[i].is_ready;
@@ -1018,10 +1085,11 @@ do_failover(void)
} }
/* we use the macros provided by xlogdefs.h to compare XLogRecPtr */ /* we use the macros provided by xlogdefs.h to compare XLogRecPtr */
/* /*
* Nodes are retrieved ordered by priority, so if the current * Nodes are retrieved ordered by priority, so if the current best
* best candidate is lower than the next node's wal location * candidate is lower than the next node's wal location then assign
* then assign next node as the new best candidate. * next node as the new best candidate.
*/ */
if (XLByteLT(best_candidate.xlog_location, nodes[i].xlog_location)) if (XLByteLT(best_candidate.xlog_location, nodes[i].xlog_location))
{ {
@@ -1037,7 +1105,8 @@ do_failover(void)
{ {
if (best_candidate.is_witness) if (best_candidate.is_witness)
{ {
log_err(_("%s: Node selected as new master is a witness. Can't be promoted.\n"), progname); log_err(_("%s: Node selected as new master is a witness. Can't be promoted.\n"),
progname);
terminate(ERR_FAILOVER_FAIL); terminate(ERR_FAILOVER_FAIL);
} }
@@ -1047,7 +1116,8 @@ do_failover(void)
if (verbose) if (verbose)
log_info(_("%s: This node is the best candidate to be the new primary, promoting...\n"), log_info(_("%s: This node is the best candidate to be the new primary, promoting...\n"),
progname); progname);
log_debug(_("promote command is: \"%s\"\n"), local_options.promote_command); log_debug(_("promote command is: \"%s\"\n"),
local_options.promote_command);
if (log_type == REPMGR_STDERR && *local_options.logfile) if (log_type == REPMGR_STDERR && *local_options.logfile)
{ {
@@ -1057,7 +1127,8 @@ do_failover(void)
r = system(local_options.promote_command); r = system(local_options.promote_command);
if (r != 0) if (r != 0)
{ {
log_err(_("%s: promote command failed. You could check and try it manually.\n"), progname); log_err(_("%s: promote command failed. You could check and try it manually.\n"),
progname);
terminate(ERR_BAD_CONFIG); terminate(ERR_BAD_CONFIG);
} }
} }
@@ -1070,9 +1141,10 @@ do_failover(void)
log_info(_("%s: Node %d is the best candidate to be the new primary, we should follow it...\n"), log_info(_("%s: Node %d is the best candidate to be the new primary, we should follow it...\n"),
progname, best_candidate.nodeId); progname, best_candidate.nodeId);
log_debug(_("follow command is: \"%s\"\n"), local_options.follow_command); log_debug(_("follow command is: \"%s\"\n"), local_options.follow_command);
/* /*
* New Primary need some time to be promoted. * New Primary need some time to be promoted. The follow command
* The follow command should take care of that. * should take care of that.
*/ */
if (log_type == REPMGR_STDERR && *local_options.logfile) if (log_type == REPMGR_STDERR && *local_options.logfile)
{ {
@@ -1082,13 +1154,15 @@ do_failover(void)
r = system(local_options.follow_command); r = system(local_options.follow_command);
if (r != 0) if (r != 0)
{ {
log_err(_("%s: follow command failed. You could check and try it manually.\n"), progname); log_err(_("%s: follow command failed. You could check and try it manually.\n"),
progname);
terminate(ERR_BAD_CONFIG); terminate(ERR_BAD_CONFIG);
} }
} }
else else
{ {
log_err(_("%s: Did not find candidates. You should check and try manually.\n"), progname); log_err(_("%s: Did not find candidates. You should check and try manually.\n"),
progname);
terminate(ERR_FAILOVER_FAIL); terminate(ERR_FAILOVER_FAIL);
} }
@@ -1106,10 +1180,9 @@ CheckConnection(PGconn *conn, const char *type)
int connection_retries; int connection_retries;
/* /*
* Check if the master is still available * Check if the master is still available if after
* if after local_options.reconnect_attempts * local_options.reconnect_intvl seconds of retries * local_options.reconnect_attempts * local_options.reconnect_intvl
* we cannot reconnect * seconds of retries we cannot reconnect return false
* return false
*/ */
for (connection_retries = 0; connection_retries < local_options.reconnect_attempts; connection_retries++) for (connection_retries = 0; connection_retries < local_options.reconnect_attempts; connection_retries++)
{ {
@@ -1124,16 +1197,18 @@ CheckConnection(PGconn *conn, const char *type)
} }
else else
{ {
if ( connection_retries > 0) if (connection_retries > 0)
{ {
log_info(_("%s: Connection to %s has been restored.\n"), progname, type); log_info(_("%s: Connection to %s has been restored.\n"),
progname, type);
} }
return true; return true;
} }
} }
if (!is_pgup(conn, local_options.master_response_timeout)) if (!is_pgup(conn, local_options.master_response_timeout))
{ {
log_err(_("%s: We couldn't reconnect for long enough, exiting...\n"), progname); log_err(_("%s: We couldn't reconnect for long enough, exiting...\n"),
progname);
/* XXX Anything else to do here? */ /* XXX Anything else to do here? */
return false; return false;
} }
@@ -1200,8 +1275,8 @@ checkNodeConfiguration(void)
} }
/* /*
* If there isn't any results then we have not configured this node yet * If there isn't any results then we have not configured this node yet in
* in repmgr, if that is the case we will insert the node to the cluster, * repmgr, if that is the case we will insert the node to the cluster,
* except if it is a witness * except if it is a witness
*/ */
if (PQntuples(res) == 0) if (PQntuples(res) == 0)
@@ -1249,18 +1324,20 @@ walLocationToBytes(char *wal_location)
log_err(_("wrong log location format: %s\n"), wal_location); log_err(_("wrong log location format: %s\n"), wal_location);
return 0; return 0;
} }
return (( (long long) xlogid * 16 * 1024 * 1024 * 255) + xrecoff); return (((long long) xlogid * 16 * 1024 * 1024 * 255) + xrecoff);
} }
void usage(void) void
usage(void)
{ {
log_err(_("%s: Replicator manager daemon \n"), progname); log_err(_("%s: Replicator manager daemon \n"), progname);
log_err(_("Try \"%s --help\" for more information.\n"), progname); log_err(_("Try \"%s --help\" for more information.\n"), progname);
} }
void help(const char *progname) void
help(const char *progname)
{ {
printf(_("Usage: %s [OPTIONS]\n"), progname); printf(_("Usage: %s [OPTIONS]\n"), progname);
printf(_("Replicator manager daemon for PostgreSQL.\n")); printf(_("Replicator manager daemon for PostgreSQL.\n"));
@@ -1328,7 +1405,8 @@ update_shared_memory(char *last_wal_standby_applied)
res = PQexec(myLocalConn, sqlquery); res = PQexec(myLocalConn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK) if (PQresultStatus(res) != PGRES_TUPLES_OK)
{ {
log_warning(_("Cannot update this standby's shared memory: %s\n"), PQerrorMessage(myLocalConn)); log_warning(_("Cannot update this standby's shared memory: %s\n"),
PQerrorMessage(myLocalConn));
/* XXX is this enough reason to terminate this repmgrd? */ /* XXX is this enough reason to terminate this repmgrd? */
} }
else if (strcmp(PQgetvalue(res, 0, 0), "f") == 0) else if (strcmp(PQgetvalue(res, 0, 0), "f") == 0)
@@ -1350,12 +1428,14 @@ update_registration(void)
" SET conninfo = '%s', " " SET conninfo = '%s', "
" priority = %d " " priority = %d "
" WHERE id = %d", " WHERE id = %d",
repmgr_schema, local_options.conninfo, local_options.priority, local_options.node); repmgr_schema, local_options.conninfo,
local_options.priority, local_options.node);
res = PQexec(primaryConn, sqlquery); res = PQexec(primaryConn, sqlquery);
if (PQresultStatus(res) != PGRES_COMMAND_OK) if (PQresultStatus(res) != PGRES_COMMAND_OK)
{ {
log_err(_("Cannot update registration: %s\n"), PQerrorMessage(primaryConn)); log_err(_("Cannot update registration: %s\n"),
PQerrorMessage(primaryConn));
terminate(ERR_DB_CON); terminate(ERR_DB_CON);
} }
PQclear(res); PQclear(res);
@@ -1364,7 +1444,8 @@ update_registration(void)
static void static void
do_daemonize() do_daemonize()
{ {
char *ptr, path[MAXLEN]; char *ptr,
path[MAXLEN];
pid_t pid = fork(); pid_t pid = fork();
int ret; int ret;
@@ -1377,7 +1458,7 @@ do_daemonize()
case 0: /* child process */ case 0: /* child process */
pid = setsid(); pid = setsid();
if (pid == (pid_t)-1) if (pid == (pid_t) -1)
{ {
log_err("Error in setsid(): %s\n", strerror(errno)); log_err("Error in setsid(): %s\n", strerror(errno));
exit(ERR_SYS_FAILURE); exit(ERR_SYS_FAILURE);
@@ -1386,7 +1467,7 @@ do_daemonize()
/* ensure that we are no longer able to open a terminal */ /* ensure that we are no longer able to open a terminal */
pid = fork(); pid = fork();
if(pid == -1) /* error case */ if (pid == -1) /* error case */
{ {
log_err("Error in fork(): %s\n", strerror(errno)); log_err("Error in fork(): %s\n", strerror(errno));
exit(ERR_SYS_FAILURE); exit(ERR_SYS_FAILURE);
@@ -1446,7 +1527,9 @@ check_and_create_pid_file(const char *pid_file)
if (fd == NULL) if (fd == NULL)
{ {
log_err("PID file %s exists but could not opened for reading. If repmgrd is no longer alive remove the file and restart repmgrd.\n", pid_file); log_err("PID file %s exists but could not opened for reading. "
"If repmgrd is no longer alive remove the file and restart repmgrd.\n",
pid_file);
exit(ERR_BAD_CONFIG); exit(ERR_BAD_CONFIG);
} }
@@ -1466,7 +1549,9 @@ check_and_create_pid_file(const char *pid_file)
{ {
if (kill(pid, 0) != -1) if (kill(pid, 0) != -1)
{ {
log_err("PID file %s exists and seems to contain a valid PID. If repmgrd is no longer alive remove the file and restart repmgrd.\n", pid_file); log_err("PID file %s exists and seems to contain a valid PID. "
"If repmgrd is no longer alive remove the file and restart repmgrd.\n",
pid_file);
exit(ERR_BAD_CONFIG); exit(ERR_BAD_CONFIG);
} }
} }

View File

@@ -68,9 +68,9 @@ _PG_init(void)
* In order to create our shared memory area, we have to be loaded via * In order to create our shared memory area, we have to be loaded via
* shared_preload_libraries. If not, fall out without hooking into any of * shared_preload_libraries. If not, fall out without hooking into any of
* the main system. (We don't throw error here because it seems useful to * the main system. (We don't throw error here because it seems useful to
* allow the repmgr functions to be created even when the * allow the repmgr functions to be created even when the module isn't
* module isn't active. The functions must protect themselves against * active. The functions must protect themselves against being called
* being called then, however.) * then, however.)
*/ */
if (!process_shared_preload_libraries_in_progress) if (!process_shared_preload_libraries_in_progress)
return; return;

View File

@@ -25,7 +25,9 @@
#include "log.h" #include "log.h"
#include "strutil.h" #include "strutil.h"
static int xvsnprintf(char *str, size_t size, const char *format, va_list ap) __attribute__ ((format (PG_PRINTF_ATTRIBUTE, 3, 0))); static int
xvsnprintf(char *str, size_t size, const char *format, va_list ap)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
/* Add strnlen on platforms that don't have it, like OS X */ /* Add strnlen on platforms that don't have it, like OS X */
#ifndef strnlen #ifndef strnlen
@@ -33,7 +35,8 @@ size_t
strnlen(const char *s, size_t n) strnlen(const char *s, size_t n)
{ {
const char *end = (const char *) memchr(s, '\0', n); const char *end = (const char *) memchr(s, '\0', n);
return(end ? end - s : n);
return (end ? end - s : n);
} }
#endif #endif
@@ -44,7 +47,7 @@ xvsnprintf(char *str, size_t size, const char *format, va_list ap)
retval = vsnprintf(str, size, format, ap); retval = vsnprintf(str, size, format, ap);
if (retval >= (int)size) if (retval >= (int) size)
{ {
log_err(_("Buffer of size not large enough to format entire string '%s'\n"), log_err(_("Buffer of size not large enough to format entire string '%s'\n"),
str); str);
@@ -56,7 +59,7 @@ xvsnprintf(char *str, size_t size, const char *format, va_list ap)
int int
xsnprintf(char *str, size_t size, const char *format, ...) xsnprintf(char *str, size_t size, const char *format,...)
{ {
va_list arglist; va_list arglist;
int retval; int retval;
@@ -70,7 +73,7 @@ xsnprintf(char *str, size_t size, const char *format, ...)
int int
sqlquery_snprintf(char *str, const char *format, ...) sqlquery_snprintf(char *str, const char *format,...)
{ {
va_list arglist; va_list arglist;
int retval; int retval;
@@ -83,7 +86,8 @@ sqlquery_snprintf(char *str, const char *format, ...)
} }
int maxlen_snprintf(char *str, const char *format, ...) int
maxlen_snprintf(char *str, const char *format,...)
{ {
va_list arglist; va_list arglist;
int retval; int retval;

View File

@@ -31,9 +31,17 @@
#define MAXCONNINFO 1024 #define MAXCONNINFO 1024
extern int xsnprintf(char *str, size_t size, const char *format, ...) __attribute__ ((format (PG_PRINTF_ATTRIBUTE, 3, 4))); extern int
extern int sqlquery_snprintf(char *str, const char *format, ...) __attribute__ ((format (PG_PRINTF_ATTRIBUTE, 2, 3))); xsnprintf(char *str, size_t size, const char *format,...)
extern int maxlen_snprintf(char *str, const char *format, ...) __attribute__ ((format (PG_PRINTF_ATTRIBUTE, 2, 3))); __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
extern int
sqlquery_snprintf(char *str, const char *format,...)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
extern int
maxlen_snprintf(char *str, const char *format,...)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
/* Add strnlen on platforms that don't have it, like OS X */ /* Add strnlen on platforms that don't have it, like OS X */
#ifndef strnlen #ifndef strnlen

View File

@@ -2,4 +2,5 @@
#define _VERSION_H_ #define _VERSION_H_
#define REPMGR_VERSION "2.0" #define REPMGR_VERSION "2.0"
#endif #endif