diff --git a/check_dir.c b/check_dir.c index 94e66c0b..26b07331 100644 --- a/check_dir.c +++ b/check_dir.c @@ -6,15 +6,15 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ #include @@ -43,63 +43,63 @@ static int mkdir_p(char *path, mode_t omode); int check_dir(char *dir) { - DIR *chkdir; - struct dirent *file; - int result = 1; + DIR *chkdir; + struct dirent *file; + int result = 1; - errno = 0; + errno = 0; - chkdir = opendir(dir); + chkdir = opendir(dir); - if (!chkdir) - return (errno == ENOENT) ? 0 : -1; + if (!chkdir) + return (errno == ENOENT) ? 0 : -1; - while ((file = readdir(chkdir)) != NULL) - { - if (strcmp(".", file->d_name) == 0 || - strcmp("..", file->d_name) == 0) - { - /* skip this and parent directory */ - continue; - } - else - { - result = 2; /* not empty */ - break; - } - } + while ((file = readdir(chkdir)) != NULL) + { + if (strcmp(".", file->d_name) == 0 || + strcmp("..", file->d_name) == 0) + { + /* skip this and parent directory */ + continue; + } + else + { + result = 2; /* not empty */ + break; + } + } #ifdef WIN32 - /* - * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in - * released version - */ - if (GetLastError() == ERROR_NO_MORE_FILES) - errno = 0; + /* + * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in + * released version + */ + if (GetLastError() == ERROR_NO_MORE_FILES) + errno = 0; #endif - closedir(chkdir); + closedir(chkdir); - if (errno != 0) - return -1; /* some kind of I/O error? */ + if (errno != 0) + return -1; /* some kind of I/O error? */ return result; } /* - * Create directory + * Create directory */ bool create_directory(char *dir) { - if (mkdir_p(dir, 0700) == 0) - return true; + if (mkdir_p(dir, 0700) == 0) + return true; - fprintf(stderr, _("Could not create directory \"%s\": %s\n"), - dir, strerror(errno)); + fprintf(stderr, _("Could not create directory \"%s\": %s\n"), + dir, strerror(errno)); - return false; + return false; } bool @@ -126,10 +126,10 @@ mkdir_p(char *path, mode_t omode) { struct stat sb; mode_t numask, - oumask; + oumask; int first, - last, - retval; + last, + retval; char *p; p = path; @@ -148,8 +148,8 @@ mkdir_p(char *path, mode_t omode) return 1; } else if (p[1] == ':' && - ((p[0] >= 'a' && p[0] <= 'z') || - (p[0] >= 'A' && p[0] <= 'Z'))) + ((p[0] >= 'a' && p[0] <= 'z') || + (p[0] >= 'A' && p[0] <= 'Z'))) { /* local drive */ p += 2; @@ -224,5 +224,5 @@ is_pg_dir(char *dir) sprintf(path, "%s/PG_VERSION", dir); - return (stat(path, &sb) == 0) ? true : false; + return (stat(path, &sb) == 0) ? true : false; } diff --git a/check_dir.h b/check_dir.h index e42c92fd..9acac474 100644 --- a/check_dir.h +++ b/check_dir.h @@ -1,7 +1,7 @@ /* * check_dir.h * Copyright (c) 2ndQuadrant, 2010 - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or diff --git a/config.c b/config.c index d7512483..4499509f 100644 --- a/config.c +++ b/config.c @@ -6,15 +6,15 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ #include "repmgr.h" @@ -55,28 +55,28 @@ parse_config(const char *config_file, char *cluster_name, int *node, char *conni } - /* Close file */ - fclose (fp); + /* Close file */ + fclose (fp); } char * trim (char *s) { - /* Initialize start, end pointers */ - char *s1 = s, *s2 = &s[strlen (s) - 1]; + /* Initialize start, end pointers */ + char *s1 = s, *s2 = &s[strlen (s) - 1]; - /* Trim and delimit right side */ - while ( (isspace (*s2)) && (s2 >= s1) ) - --s2; - *(s2+1) = '\0'; + /* Trim and delimit right side */ + while ( (isspace (*s2)) && (s2 >= s1) ) + --s2; + *(s2+1) = '\0'; - /* Trim left side */ - while ( (isspace (*s1)) && (s1 < s2) ) - ++s1; + /* Trim left side */ + while ( (isspace (*s1)) && (s1 < s2) ) + ++s1; - /* Copy finished string */ - strcpy (s, s1); - return s; + /* Copy finished string */ + strcpy (s, s1); + return s; } void @@ -99,7 +99,7 @@ parse_line(char *buff, char *name, char *value) /* * Now the value - */ + */ j = 0; for ( ++i ; i < MAXLEN; ++i) if (buff[i] == '\'') diff --git a/config.h b/config.h index 70a66472..9b2ea3fc 100644 --- a/config.h +++ b/config.h @@ -1,7 +1,7 @@ /* * config.h * Copyright (c) 2ndQuadrant, 2010 - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or diff --git a/dbutils.c b/dbutils.c index 3749b9f0..38b8c05f 100644 --- a/dbutils.c +++ b/dbutils.c @@ -6,15 +6,15 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ #include "repmgr.h" @@ -31,8 +31,8 @@ establishDBConnection(const char *conninfo, const bool exit_on_error) /* Check to see that the backend connection was successfully made */ if ((PQstatus(conn) != CONNECTION_OK)) { - fprintf(stderr, "Connection to database failed: %s", - PQerrorMessage(conn)); + fprintf(stderr, "Connection to database failed: %s", + PQerrorMessage(conn)); if (exit_on_error) { PQfinish(conn); @@ -63,14 +63,14 @@ is_standby(PGconn *conn) if (strcmp(PQgetvalue(res, 0, 0), "f") == 0) result = false; else - result = true; + result = true; PQclear(res); return result; } -/* +/* * If postgreSQL version is 9 or superior returns the major version * if 8 or inferior returns an empty string */ @@ -82,18 +82,18 @@ pg_version(PGconn *conn, char* major_version) int major_version1; char *major_version2; - res = PQexec(conn, "WITH pg_version(ver) AS (SELECT split_part(version(), ' ', 2)) " - "SELECT split_part(ver, '.', 1), split_part(ver, '.', 2) FROM pg_version"); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { + res = PQexec(conn, "WITH pg_version(ver) AS (SELECT split_part(version(), ' ', 2)) " + "SELECT split_part(ver, '.', 1), split_part(ver, '.', 2) FROM pg_version"); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { fprintf(stderr, "PQexec failed: %s", PQerrorMessage(conn)); - PQclear(res); + PQclear(res); PQfinish(conn); exit(1); - } - major_version1 = atoi(PQgetvalue(res, 0, 0)); - major_version2 = PQgetvalue(res, 0, 1); - PQclear(res); + } + major_version1 = atoi(PQgetvalue(res, 0, 0)); + major_version2 = PQgetvalue(res, 0, 1); + PQclear(res); if (major_version1 >= 9) { @@ -114,21 +114,21 @@ guc_setted(PGconn *conn, const char *parameter, const char *op, const char *valu char sqlquery[MAXQUERY]; sprintf(sqlquery, "SELECT true FROM pg_settings " - " WHERE name = '%s' AND setting %s '%s'", - parameter, op, value); + " WHERE name = '%s' AND setting %s '%s'", + parameter, op, value); - res = PQexec(conn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { + res = PQexec(conn, sqlquery); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { fprintf(stderr, "PQexec failed: %s", PQerrorMessage(conn)); - PQclear(res); + PQclear(res); PQfinish(conn); exit(1); - } + } if (PQntuples(res) == 0) { PQclear(res); - return false; + return false; } PQclear(res); @@ -144,51 +144,51 @@ get_cluster_size(PGconn *conn) char sqlquery[MAXQUERY]; sprintf(sqlquery, "SELECT pg_size_pretty(SUM(pg_database_size(oid))::bigint) " - " FROM pg_database "); + " FROM pg_database "); - res = PQexec(conn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { + res = PQexec(conn, sqlquery); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { fprintf(stderr, "PQexec failed: %s", PQerrorMessage(conn)); - PQclear(res); + PQclear(res); PQfinish(conn); exit(1); - } - size = PQgetvalue(res, 0, 0); + } + size = PQgetvalue(res, 0, 0); PQclear(res); return size; } /* - * get a connection to master by reading repl_nodes, creating a connection + * get a connection to master by reading repl_nodes, creating a connection * to each node (one at a time) and finding if it is a master or a standby */ PGconn * getMasterConnection(PGconn *standby_conn, int id, char *cluster, int *master_id) { PGconn *master_conn = NULL; - PGresult *res1; - PGresult *res2; + PGresult *res1; + PGresult *res2; char sqlquery[MAXQUERY]; char master_conninfo[MAXCONNINFO]; int i; /* find all nodes belonging to this cluster */ sprintf(sqlquery, "SELECT * FROM repmgr_%s.repl_nodes " - " WHERE cluster = '%s' and id <> %d", - cluster, cluster, id); + " WHERE cluster = '%s' and id <> %d", + cluster, cluster, id); - res1 = PQexec(standby_conn, sqlquery); - if (PQresultStatus(res1) != PGRES_TUPLES_OK) - { - fprintf(stderr, "Can't get nodes info: %s\n", PQerrorMessage(standby_conn)); - PQclear(res1); + res1 = PQexec(standby_conn, sqlquery); + if (PQresultStatus(res1) != PGRES_TUPLES_OK) + { + fprintf(stderr, "Can't get nodes info: %s\n", PQerrorMessage(standby_conn)); + PQclear(res1); PQfinish(standby_conn); exit(1); - } + } for (i = 0; i < PQntuples(res1); i++) - { + { /* initialize with the values of the current node being processed */ *master_id = atoi(PQgetvalue(res1, i, 0)); strncpy(master_conninfo, PQgetvalue(res1, i, 2), MAXCONNINFO); @@ -196,19 +196,19 @@ getMasterConnection(PGconn *standby_conn, int id, char *cluster, int *master_id) if (PQstatus(master_conn) != CONNECTION_OK) continue; - /* - * I can't use the is_standby() function here because on error that - * function closes the connection i pass and exit, but i still need to close + /* + * I can't use the is_standby() function here because on error that + * function closes the connection i pass and exit, but i still need to close * standby_conn */ - res2 = PQexec(master_conn, "SELECT pg_is_in_recovery()"); - if (PQresultStatus(res2) != PGRES_TUPLES_OK) - { - fprintf(stderr, "Can't get recovery state from this node: %s\n", PQerrorMessage(master_conn)); - PQclear(res2); + res2 = PQexec(master_conn, "SELECT pg_is_in_recovery()"); + if (PQresultStatus(res2) != PGRES_TUPLES_OK) + { + fprintf(stderr, "Can't get recovery state from this node: %s\n", PQerrorMessage(master_conn)); + PQclear(res2); PQfinish(master_conn); continue; - } + } /* if false, this is the master */ if (strcmp(PQgetvalue(res2, 0, 0), "f") == 0) @@ -224,16 +224,16 @@ getMasterConnection(PGconn *standby_conn, int id, char *cluster, int *master_id) PQfinish(master_conn); *master_id = -1; } - } + } /* If we finish this loop without finding a master then - * we doesn't have the info or the master has failed (or we - * reached max_connections or superuser_reserved_connections, - * anything else i'm missing?), - * Probably we will need to check the error to know if we need - * to start failover procedure or just fix some situation on the - * standby. - */ + * we doesn't have the info or the master has failed (or we + * reached max_connections or superuser_reserved_connections, + * anything else i'm missing?), + * Probably we will need to check the error to know if we need + * to start failover procedure or just fix some situation on the + * standby. + */ PQclear(res1); return NULL; } diff --git a/dbutils.h b/dbutils.h index 32666cf7..cc5830d9 100644 --- a/dbutils.h +++ b/dbutils.h @@ -1,7 +1,7 @@ /* * dbutils.h * Copyright (c) 2ndQuadrant, 2010 - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or diff --git a/repmgr.c b/repmgr.c index 70103f87..8e2ce895 100644 --- a/repmgr.c +++ b/repmgr.c @@ -4,24 +4,24 @@ * * This module is a command-line utility to easily setup a cluster of * hot standby servers for an HA environment - * + * * Commands implemented are. - * MASTER REGISTER, STANDBY REGISTER, STANDBY CLONE, STANDBY FOLLOW, + * MASTER REGISTER, STANDBY REGISTER, STANDBY CLONE, STANDBY FOLLOW, * STANDBY PROMOTE - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ #include "repmgr.h" @@ -67,7 +67,7 @@ char *username = NULL; char *dest_dir = NULL; char *config_file = NULL; char *remote_user = NULL; -char *wal_keep_segments = NULL; +char *wal_keep_segments = NULL; bool verbose = false; bool force = false; @@ -81,7 +81,8 @@ char *server_cmd = NULL; int main(int argc, char **argv) { - static struct option long_options[] = { + static struct option long_options[] = + { {"dbname", required_argument, NULL, 'd'}, {"host", required_argument, NULL, 'h'}, {"port", required_argument, NULL, 'p'}, @@ -120,112 +121,112 @@ main(int argc, char **argv) { switch (c) { - case 'd': - dbname = optarg; - break; - case 'h': - host = optarg; - break; - case 'p': - masterport = optarg; - break; - case 'U': - username = optarg; - break; - case 'D': - dest_dir = optarg; - break; - case 'f': - config_file = optarg; - break; - case 'R': - remote_user = optarg; - break; - case 'w': - wal_keep_segments = optarg; - break; - case 'F': - force = true; - break; - case 'v': - verbose = true; - break; - default: - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - exit(1); + case 'd': + dbname = optarg; + break; + case 'h': + host = optarg; + break; + case 'p': + masterport = optarg; + break; + case 'U': + username = optarg; + break; + case 'D': + dest_dir = optarg; + break; + case 'f': + config_file = optarg; + break; + case 'R': + remote_user = optarg; + break; + case 'w': + wal_keep_segments = optarg; + break; + case 'F': + force = true; + break; + case 'v': + verbose = true; + break; + default: + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + exit(1); } } - /* + /* * Now we need to obtain the action, this comes in one of these forms: - * MASTER REGISTER | - * STANDBY {REGISTER | CLONE [node] | PROMOTE | FOLLOW [node]} - * - * the node part is optional, if we receive it then we shouldn't - * have received a -h option - */ - if (optind < argc) + * MASTER REGISTER | + * STANDBY {REGISTER | CLONE [node] | PROMOTE | FOLLOW [node]} + * + * the node part is optional, if we receive it then we shouldn't + * have received a -h option + */ + if (optind < argc) { - server_mode = argv[optind++]; + server_mode = argv[optind++]; if (strcasecmp(server_mode, "STANDBY") != 0 && strcasecmp(server_mode, "MASTER") != 0) { fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); - } + } } - if (optind < argc) + if (optind < argc) { - server_cmd = argv[optind++]; - if (strcasecmp(server_cmd, "REGISTER") == 0) + server_cmd = argv[optind++]; + if (strcasecmp(server_cmd, "REGISTER") == 0) { - /* - * we don't use this info in any other place so i will - * just execute the compare again instead of having an - * additional variable to hold a value that we will use - * no more - */ + /* + * we don't use this info in any other place so i will + * just execute the compare again instead of having an + * additional variable to hold a value that we will use + * no more + */ if (strcasecmp(server_mode, "MASTER") == 0) action = MASTER_REGISTER; - else if (strcasecmp(server_mode, "STANDBY") == 0) + else if (strcasecmp(server_mode, "STANDBY") == 0) action = STANDBY_REGISTER; } - else if (strcasecmp(server_cmd, "CLONE") == 0) + else if (strcasecmp(server_cmd, "CLONE") == 0) action = STANDBY_CLONE; - else if (strcasecmp(server_cmd, "PROMOTE") == 0) + else if (strcasecmp(server_cmd, "PROMOTE") == 0) action = STANDBY_PROMOTE; - else if (strcasecmp(server_cmd, "FOLLOW") == 0) + else if (strcasecmp(server_cmd, "FOLLOW") == 0) action = STANDBY_FOLLOW; else { fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); - } + } } /* For some actions we still can receive a last argument */ if (action == STANDBY_CLONE) { - if (optind < argc) + if (optind < argc) { if (host != NULL) { fprintf(stderr, _("Conflicting parameters you can't use -h while providing a node separately. Try \"%s --help\" for more information.\n"), progname); exit(1); - } - host = argv[optind++]; + } + host = argv[optind++]; } } switch (optind < argc) { - case 0: - break; - default: - fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"), - progname, argv[optind + 1]); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - exit(1); + case 0: + break; + default: + fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"), + progname, argv[optind + 1]); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + exit(1); } if (!check_parameters_for_action(action)) @@ -243,52 +244,52 @@ main(int argc, char **argv) strcpy(wal_keep_segments, "5000"); } - if (dbname == NULL) - { - if (getenv("PGDATABASE")) - dbname = getenv("PGDATABASE"); - else if (getenv("PGUSER")) - dbname = getenv("PGUSER"); - else - dbname = "postgres"; - } + if (dbname == NULL) + { + if (getenv("PGDATABASE")) + dbname = getenv("PGDATABASE"); + else if (getenv("PGUSER")) + dbname = getenv("PGUSER"); + else + dbname = "postgres"; + } - keywords[2] = "user"; - values[2] = username; - keywords[3] = "dbname"; - values[3] = dbname; - keywords[4] = "application_name"; - values[4] = (char *) progname; - keywords[5] = NULL; - values[5] = NULL; + keywords[2] = "user"; + values[2] = username; + keywords[3] = "dbname"; + values[3] = dbname; + keywords[4] = "application_name"; + values[4] = (char *) progname; + keywords[5] = NULL; + values[5] = NULL; switch (action) { - case MASTER_REGISTER: - do_master_register(); - break; - case STANDBY_REGISTER: - do_standby_register(); - break; - case STANDBY_CLONE: - do_standby_clone(); - break; - case STANDBY_PROMOTE: - do_standby_promote(); - break; - case STANDBY_FOLLOW: - do_standby_follow(); - break; - default: - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - exit(1); + case MASTER_REGISTER: + do_master_register(); + break; + case STANDBY_REGISTER: + do_standby_register(); + break; + case STANDBY_CLONE: + do_standby_clone(); + break; + case STANDBY_PROMOTE: + do_standby_promote(); + break; + case STANDBY_FOLLOW: + do_standby_follow(); + break; + default: + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + exit(1); } - - return 0; + + return 0; } -static void +static void do_master_register(void) { PGconn *conn; @@ -297,30 +298,30 @@ do_master_register(void) char myClusterName[MAXLEN]; int myLocalId = -1; - char conninfo[MAXLEN]; + char conninfo[MAXLEN]; bool schema_exists = false; char master_version[MAXVERSIONSTR]; /* * Read the configuration file: repmgr.conf - */ + */ parse_config(config_file, myClusterName, &myLocalId, conninfo); - if (myLocalId == -1) + if (myLocalId == -1) { fprintf(stderr, "Node information is missing. " - "Check the configuration file.\n"); + "Check the configuration file.\n"); exit(1); } - conn = establishDBConnection(conninfo, true); + conn = establishDBConnection(conninfo, true); /* master should be v9 or better */ pg_version(conn, master_version); if (strcmp(master_version, "") == 0) { PQfinish(conn); - fprintf(stderr, _("%s needs master to be PostgreSQL 9.0 or better\n"), progname); + fprintf(stderr, _("%s needs master to be PostgreSQL 9.0 or better\n"), progname); return; } @@ -335,83 +336,83 @@ do_master_register(void) /* Check if there is a schema for this cluster */ sprintf(sqlquery, "SELECT 1 FROM pg_namespace WHERE nspname = 'repmgr_%s'", myClusterName); res = PQexec(conn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) + if (PQresultStatus(res) != PGRES_TUPLES_OK) { - fprintf(stderr, "Can't get info about schemas: %s\n", PQerrorMessage(conn)); - PQclear(res); - PQfinish(conn); - return; + fprintf(stderr, "Can't get info about schemas: %s\n", PQerrorMessage(conn)); + PQclear(res); + PQfinish(conn); + return; } - + if (PQntuples(res) > 0) /* schema exists */ { if (!force) /* and we are not forcing so error */ { - fprintf(stderr, "Schema repmgr_%s already exists.", myClusterName); - PQclear(res); - PQfinish(conn); + fprintf(stderr, "Schema repmgr_%s already exists.", myClusterName); + PQclear(res); + PQfinish(conn); return; } schema_exists = true; } PQclear(res); - + if (!schema_exists) { /* ok, create the schema */ sprintf(sqlquery, "CREATE SCHEMA repmgr_%s", myClusterName); - if (!PQexec(conn, sqlquery)) + if (!PQexec(conn, sqlquery)) { fprintf(stderr, "Cannot create the schema repmgr_%s: %s\n", - myClusterName, PQerrorMessage(conn)); - PQfinish(conn); - return; - } - - /* ... the tables */ - sprintf(sqlquery, "CREATE TABLE repmgr_%s.repl_nodes ( " - " id integer primary key, " - " cluster text not null, " - " conninfo text not null)", myClusterName); - if (!PQexec(conn, sqlquery)) - { - fprintf(stderr, "Cannot create the table repmgr_%s.repl_nodes: %s\n", - myClusterName, PQerrorMessage(conn)); - PQfinish(conn); - return; - } - - sprintf(sqlquery, "CREATE TABLE repmgr_%s.repl_monitor ( " - " primary_node INTEGER NOT NULL, " - " standby_node INTEGER NOT NULL, " - " last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL, " - " last_wal_primary_location TEXT NOT NULL, " - " last_wal_standby_location TEXT NOT NULL, " - " replication_lag BIGINT NOT NULL, " - " apply_lag BIGINT NOT NULL) ", myClusterName); - if (!PQexec(conn, sqlquery)) - { - fprintf(stderr, "Cannot create the table repmgr_%s.repl_monitor: %s\n", - myClusterName, PQerrorMessage(conn)); - PQfinish(conn); + myClusterName, PQerrorMessage(conn)); + PQfinish(conn); return; } - /* and the view */ + /* ... the tables */ + sprintf(sqlquery, "CREATE TABLE repmgr_%s.repl_nodes ( " + " id integer primary key, " + " cluster text not null, " + " conninfo text not null)", myClusterName); + if (!PQexec(conn, sqlquery)) + { + fprintf(stderr, "Cannot create the table repmgr_%s.repl_nodes: %s\n", + myClusterName, PQerrorMessage(conn)); + PQfinish(conn); + return; + } + + sprintf(sqlquery, "CREATE TABLE repmgr_%s.repl_monitor ( " + " primary_node INTEGER NOT NULL, " + " standby_node INTEGER NOT NULL, " + " last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL, " + " last_wal_primary_location TEXT NOT NULL, " + " last_wal_standby_location TEXT NOT NULL, " + " replication_lag BIGINT NOT NULL, " + " apply_lag BIGINT NOT NULL) ", myClusterName); + if (!PQexec(conn, sqlquery)) + { + fprintf(stderr, "Cannot create the table repmgr_%s.repl_monitor: %s\n", + myClusterName, PQerrorMessage(conn)); + PQfinish(conn); + return; + } + + /* and the view */ sprintf(sqlquery, "CREATE VIEW repmgr_%s.repl_status AS " - " WITH monitor_info AS (SELECT *, ROW_NUMBER() OVER (PARTITION BY primary_node, standby_node " - " ORDER BY last_monitor_time desc) " - " FROM repmgr_%s.repl_monitor) " - " SELECT primary_node, standby_node, last_monitor_time, last_wal_primary_location, " - " last_wal_standby_location, pg_size_pretty(replication_lag) replication_lag, " - " pg_size_pretty(apply_lag) apply_lag, age(now(), last_monitor_time) AS time_lag " - " FROM monitor_info a " - " WHERE row_number = 1", myClusterName, myClusterName); - if (!PQexec(conn, sqlquery)) + " WITH monitor_info AS (SELECT *, ROW_NUMBER() OVER (PARTITION BY primary_node, standby_node " + " ORDER BY last_monitor_time desc) " + " FROM repmgr_%s.repl_monitor) " + " SELECT primary_node, standby_node, last_monitor_time, last_wal_primary_location, " + " last_wal_standby_location, pg_size_pretty(replication_lag) replication_lag, " + " pg_size_pretty(apply_lag) apply_lag, age(now(), last_monitor_time) AS time_lag " + " FROM monitor_info a " + " WHERE row_number = 1", myClusterName, myClusterName); + if (!PQexec(conn, sqlquery)) { fprintf(stderr, "Cannot create the view repmgr_%s.repl_status: %s\n", - myClusterName, PQerrorMessage(conn)); - PQfinish(conn); + myClusterName, PQerrorMessage(conn)); + PQfinish(conn); return; } } @@ -421,7 +422,7 @@ do_master_register(void) int id; /* Ensure there isn't any other master already registered */ - master_conn = getMasterConnection(conn, myLocalId, myClusterName, &id); + master_conn = getMasterConnection(conn, myLocalId, myClusterName, &id); if (master_conn != NULL) { PQfinish(master_conn); @@ -433,37 +434,37 @@ do_master_register(void) /* Now register the master */ if (force) { - sprintf(sqlquery, "DELETE FROM repmgr_%s.repl_nodes " - " WHERE id = %d", - myClusterName, myLocalId); + sprintf(sqlquery, "DELETE FROM repmgr_%s.repl_nodes " + " WHERE id = %d", + myClusterName, myLocalId); - if (!PQexec(conn, sqlquery)) - { - fprintf(stderr, "Cannot delete node details, %s\n", - PQerrorMessage(conn)); - PQfinish(conn); + if (!PQexec(conn, sqlquery)) + { + fprintf(stderr, "Cannot delete node details, %s\n", + PQerrorMessage(conn)); + PQfinish(conn); return; - } + } } - sprintf(sqlquery, "INSERT INTO repmgr_%s.repl_nodes " - "VALUES (%d, '%s', '%s')", - myClusterName, myLocalId, myClusterName, conninfo); - - if (!PQexec(conn, sqlquery)) - { - fprintf(stderr, "Cannot insert node details, %s\n", - PQerrorMessage(conn)); - PQfinish(conn); + sprintf(sqlquery, "INSERT INTO repmgr_%s.repl_nodes " + "VALUES (%d, '%s', '%s')", + myClusterName, myLocalId, myClusterName, conninfo); + + if (!PQexec(conn, sqlquery)) + { + fprintf(stderr, "Cannot insert node details, %s\n", + PQerrorMessage(conn)); + PQfinish(conn); return; - } + } PQfinish(conn); return; } -static void +static void do_standby_register(void) { PGconn *conn; @@ -475,30 +476,30 @@ do_standby_register(void) char myClusterName[MAXLEN]; int myLocalId = -1; - char conninfo[MAXLEN]; + char conninfo[MAXLEN]; char master_version[MAXVERSIONSTR]; char standby_version[MAXVERSIONSTR]; /* * Read the configuration file: repmgr.conf - */ + */ parse_config(config_file, myClusterName, &myLocalId, conninfo); - if (myLocalId == -1) + if (myLocalId == -1) { fprintf(stderr, "Node information is missing. " - "Check the configuration file.\n"); + "Check the configuration file.\n"); exit(1); } - conn = establishDBConnection(conninfo, true); + conn = establishDBConnection(conninfo, true); /* should be v9 or better */ pg_version(conn, standby_version); if (strcmp(standby_version, "") == 0) { PQfinish(conn); - fprintf(stderr, _("%s needs standby to be PostgreSQL 9.0 or better\n"), progname); + fprintf(stderr, _("%s needs standby to be PostgreSQL 9.0 or better\n"), progname); return; } @@ -513,23 +514,23 @@ do_standby_register(void) /* Check if there is a schema for this cluster */ sprintf(sqlquery, "SELECT 1 FROM pg_namespace WHERE nspname = 'repmgr_%s'", myClusterName); res = PQexec(conn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) + if (PQresultStatus(res) != PGRES_TUPLES_OK) { - fprintf(stderr, "Can't get info about tablespaces: %s\n", PQerrorMessage(conn)); - PQclear(res); - PQfinish(conn); - return; + fprintf(stderr, "Can't get info about tablespaces: %s\n", PQerrorMessage(conn)); + PQclear(res); + PQfinish(conn); + return; } - + if (PQntuples(res) == 0) /* schema doesn't exists */ { - fprintf(stderr, "Schema repmgr_%s doesn't exists.", myClusterName); - PQclear(res); - PQfinish(conn); + fprintf(stderr, "Schema repmgr_%s doesn't exists.", myClusterName); + PQclear(res); + PQfinish(conn); return; } PQclear(res); - + /* check if there is a master in this cluster */ master_conn = getMasterConnection(conn, myLocalId, myClusterName, &master_id); if (!master_conn) @@ -541,7 +542,7 @@ do_standby_register(void) { PQfinish(conn); PQfinish(master_conn); - fprintf(stderr, _("%s needs master to be PostgreSQL 9.0 or better\n"), progname); + fprintf(stderr, _("%s needs master to be PostgreSQL 9.0 or better\n"), progname); return; } @@ -550,8 +551,8 @@ do_standby_register(void) { PQfinish(conn); PQfinish(master_conn); - fprintf(stderr, _("%s needs versions of both master (%s) and standby (%s) to match.\n"), - progname, master_version, standby_version); + fprintf(stderr, _("%s needs versions of both master (%s) and standby (%s) to match.\n"), + progname, master_version, standby_version); return; } @@ -559,32 +560,32 @@ do_standby_register(void) /* Now register the standby */ if (force) { - sprintf(sqlquery, "DELETE FROM repmgr_%s.repl_nodes " - " WHERE id = %d", - myClusterName, myLocalId); + sprintf(sqlquery, "DELETE FROM repmgr_%s.repl_nodes " + " WHERE id = %d", + myClusterName, myLocalId); - if (!PQexec(master_conn, sqlquery)) - { - fprintf(stderr, "Cannot delete node details, %s\n", - PQerrorMessage(master_conn)); - PQfinish(master_conn); - PQfinish(conn); + if (!PQexec(master_conn, sqlquery)) + { + fprintf(stderr, "Cannot delete node details, %s\n", + PQerrorMessage(master_conn)); + PQfinish(master_conn); + PQfinish(conn); return; - } + } } - sprintf(sqlquery, "INSERT INTO repmgr_%s.repl_nodes " - "VALUES (%d, '%s', '%s')", - myClusterName, myLocalId, myClusterName, conninfo); - - if (!PQexec(master_conn, sqlquery)) - { - fprintf(stderr, "Cannot insert node details, %s\n", - PQerrorMessage(master_conn)); - PQfinish(master_conn); - PQfinish(conn); + sprintf(sqlquery, "INSERT INTO repmgr_%s.repl_nodes " + "VALUES (%d, '%s', '%s')", + myClusterName, myLocalId, myClusterName, conninfo); + + if (!PQexec(master_conn, sqlquery)) + { + fprintf(stderr, "Cannot insert node details, %s\n", + PQerrorMessage(master_conn)); + PQfinish(master_conn); + PQfinish(conn); return; - } + } PQfinish(master_conn); PQfinish(conn); @@ -592,7 +593,7 @@ do_standby_register(void) } -static void +static void do_standby_clone(void) { PGconn *conn; @@ -610,8 +611,8 @@ do_standby_clone(void) char master_control_file[MAXLEN]; char local_control_file[MAXLEN]; - const char *first_wal_segment = NULL; - const char *last_wal_segment = NULL; + const char *first_wal_segment = NULL; + const char *last_wal_segment = NULL; char master_version[MAXVERSIONSTR]; @@ -623,84 +624,84 @@ do_standby_clone(void) } /* Check this directory could be used as a PGDATA dir */ - switch (check_dir(dest_dir)) - { - case 0: - /* dest_dir not there, must create it */ - if (verbose) - printf(_("creating directory %s ... "), dest_dir); - fflush(stdout); + switch (check_dir(dest_dir)) + { + case 0: + /* dest_dir not there, must create it */ + if (verbose) + printf(_("creating directory %s ... "), dest_dir); + fflush(stdout); - if (!create_directory(dest_dir)) - { - fprintf(stderr, _("%s: couldn't create directory %s ... "), - progname, dest_dir); - return; - } - break; - case 1: - /* Present but empty, fix permissions and use it */ - if (verbose) - printf(_("fixing permissions on existing directory %s ... "), - dest_dir); - fflush(stdout); + if (!create_directory(dest_dir)) + { + fprintf(stderr, _("%s: couldn't create directory %s ... "), + progname, dest_dir); + return; + } + break; + case 1: + /* Present but empty, fix permissions and use it */ + if (verbose) + printf(_("fixing permissions on existing directory %s ... "), + dest_dir); + fflush(stdout); - if (!set_directory_permissions(dest_dir)) - { - fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"), - progname, dest_dir, strerror(errno)); - return; - } - break; - case 2: - /* Present and not empty */ - fprintf(stderr, - _("%s: directory \"%s\" exists but is not empty\n"), - progname, dest_dir); + if (!set_directory_permissions(dest_dir)) + { + fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"), + progname, dest_dir, strerror(errno)); + return; + } + break; + case 2: + /* Present and not empty */ + fprintf(stderr, + _("%s: directory \"%s\" exists but is not empty\n"), + progname, dest_dir); pg_dir = is_pg_dir(dest_dir); - if (pg_dir && !force) - { - fprintf(stderr, _("\nThis looks like a PostgreSQL directroy.\n" - "If you are sure you want to clone here, " - "please check there is no PostgreSQL server " - "running and use the --force option\n")); - return; - } - else if (pg_dir && force) - { - /* Let it continue */ - break; - } - else - return; - default: - /* Trouble accessing directory */ - fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"), - progname, dest_dir, strerror(errno)); - } + if (pg_dir && !force) + { + fprintf(stderr, _("\nThis looks like a PostgreSQL directroy.\n" + "If you are sure you want to clone here, " + "please check there is no PostgreSQL server " + "running and use the --force option\n")); + return; + } + else if (pg_dir && force) + { + /* Let it continue */ + break; + } + else + return; + default: + /* Trouble accessing directory */ + fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"), + progname, dest_dir, strerror(errno)); + } - /* Connection parameters for master only */ - keywords[0] = "host"; - values[0] = host; - keywords[1] = "port"; - values[1] = masterport; + /* Connection parameters for master only */ + keywords[0] = "host"; + values[0] = host; + keywords[1] = "port"; + values[1] = masterport; /* We need to connect to check configuration and start a backup */ - conn = PQconnectdbParams(keywords, values, true); - if (!conn) - { - fprintf(stderr, _("%s: could not connect to master\n"), - progname); - return; - } + conn = PQconnectdbParams(keywords, values, true); + if (!conn) + { + fprintf(stderr, _("%s: could not connect to master\n"), + progname); + return; + } /* primary should be v9 or better */ pg_version(conn, master_version); if (strcmp(master_version, "") == 0) { PQfinish(conn); - fprintf(stderr, _("%s needs master to be PostgreSQL 9.0 or better\n"), progname); + fprintf(stderr, _("%s needs master to be PostgreSQL 9.0 or better\n"), progname); return; } @@ -716,19 +717,19 @@ do_standby_clone(void) if (!guc_setted(conn, "wal_level", "=", "hot_standby")) { PQfinish(conn); - fprintf(stderr, _("%s needs parameter 'wal_level' to be set to 'hot_standby'\n"), progname); + fprintf(stderr, _("%s needs parameter 'wal_level' to be set to 'hot_standby'\n"), progname); return; } if (!guc_setted(conn, "wal_keep_segments", ">=", wal_keep_segments)) { PQfinish(conn); - fprintf(stderr, _("%s needs parameter 'wal_keep_segments' to be set to %s or greater\n"), wal_keep_segments, progname); + fprintf(stderr, _("%s needs parameter 'wal_keep_segments' to be set to %s or greater\n"), wal_keep_segments, progname); return; } if (!guc_setted(conn, "archive_mode", "=", "on")) { PQfinish(conn); - fprintf(stderr, _("%s needs parameter 'archive_mode' to be set to 'on'\n"), progname); + fprintf(stderr, _("%s needs parameter 'archive_mode' to be set to 'on'\n"), progname); return; } @@ -737,13 +738,13 @@ do_standby_clone(void) /* Check if the tablespace locations exists and that we can write to them */ sprintf(sqlquery, "select spclocation from pg_tablespace where spcname not in ('pg_default', 'pg_global')"); - res = PQexec(conn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) + res = PQexec(conn, sqlquery); + if (PQresultStatus(res) != PGRES_TUPLES_OK) { - fprintf(stderr, "Can't get info about tablespaces: %s\n", PQerrorMessage(conn)); - PQclear(res); - PQfinish(conn); - return; + fprintf(stderr, "Can't get info about tablespaces: %s\n", PQerrorMessage(conn)); + PQclear(res); + PQfinish(conn); + return; } for (i = 0; i < PQntuples(res); i++) { @@ -751,74 +752,74 @@ do_standby_clone(void) strcpy(tblspc_dir, PQgetvalue(res, i, 0)); /* Check this directory could be used as a PGDATA dir */ - switch (check_dir(tblspc_dir)) - { - case 0: - /* tblspc_dir not there, must create it */ - if (verbose) - printf(_("creating directory \"%s\"... "), tblspc_dir); - fflush(stdout); - - if (!create_directory(tblspc_dir)) - { - fprintf(stderr, _("%s: couldn't create directory \"%s\"... "), - progname, tblspc_dir); - PQclear(res); - PQfinish(conn); - return; - } - break; - case 1: - /* Present but empty, fix permissions and use it */ - if (verbose) - printf(_("fixing permissions on existing directory \"%s\"... "), - tblspc_dir); - fflush(stdout); - - if (!set_directory_permissions(tblspc_dir)) - { - fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"), - progname, tblspc_dir, strerror(errno)); - PQclear(res); - PQfinish(conn); - return; - } - break; - case 2: - /* Present and not empty */ + switch (check_dir(tblspc_dir)) + { + case 0: + /* tblspc_dir not there, must create it */ + if (verbose) + printf(_("creating directory \"%s\"... "), tblspc_dir); + fflush(stdout); + + if (!create_directory(tblspc_dir)) + { + fprintf(stderr, _("%s: couldn't create directory \"%s\"... "), + progname, tblspc_dir); + PQclear(res); + PQfinish(conn); + return; + } + break; + case 1: + /* Present but empty, fix permissions and use it */ + if (verbose) + printf(_("fixing permissions on existing directory \"%s\"... "), + tblspc_dir); + fflush(stdout); + + if (!set_directory_permissions(tblspc_dir)) + { + fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"), + progname, tblspc_dir, strerror(errno)); + PQclear(res); + PQfinish(conn); + return; + } + break; + case 2: + /* Present and not empty */ if (!force) { fprintf(stderr, - _("%s: directory \"%s\" exists but is not empty\n"), - progname, tblspc_dir); + _("%s: directory \"%s\" exists but is not empty\n"), + progname, tblspc_dir); PQclear(res); PQfinish(conn); - return; + return; } - default: - /* Trouble accessing directory */ - fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"), - progname, tblspc_dir, strerror(errno)); + default: + /* Trouble accessing directory */ + fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"), + progname, tblspc_dir, strerror(errno)); PQclear(res); PQfinish(conn); return; } } - + fprintf(stderr, "Starting backup...\n"); - + /* Get the data directory full path and the configuration files location */ sprintf(sqlquery, "SELECT name, setting " - " FROM pg_settings " - " WHERE name IN ('data_directory', 'config_file', 'hba_file', 'ident_file')"); - res = PQexec(conn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - fprintf(stderr, "Can't get info about data directory and configuration files: %s\n", PQerrorMessage(conn)); - PQclear(res); - PQfinish(conn); - return; - } + " FROM pg_settings " + " WHERE name IN ('data_directory', 'config_file', 'hba_file', 'ident_file')"); + res = PQexec(conn, sqlquery); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + fprintf(stderr, "Can't get info about data directory and configuration files: %s\n", PQerrorMessage(conn)); + PQclear(res); + PQfinish(conn); + return; + } for (i = 0; i < PQntuples(res); i++) { if (strcmp(PQgetvalue(res, i, 0), "data_directory") == 0) @@ -832,32 +833,32 @@ do_standby_clone(void) else fprintf(stderr, _("uknown parameter: %s"), PQgetvalue(res, i, 0)); } - PQclear(res); + PQclear(res); - /* - * inform the master we will start a backup and get the first XLog filename + /* + * inform the master we will start a backup and get the first XLog filename * so we can say to the user we need those files - */ + */ sprintf(sqlquery, "SELECT pg_xlogfile_name(pg_start_backup('repmgr_standby_clone_%ld'))", time(NULL)); - res = PQexec(conn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - fprintf(stderr, "Can't start backup: %s\n", PQerrorMessage(conn)); - PQclear(res); - PQfinish(conn); - return; - } + res = PQexec(conn, sqlquery); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + fprintf(stderr, "Can't start backup: %s\n", PQerrorMessage(conn)); + PQclear(res); + PQfinish(conn); + return; + } first_wal_segment = PQgetvalue(res, 0, 0); PQclear(res); /* - * 1) first move global/pg_control + * 1) first move global/pg_control * * 2) then move data_directory ommiting the files we have already moved and pg_xlog * content * * 3) finally We need to backup configuration files (that could be on other directories, debian - * like systems likes to do that), so look at config_file, hba_file and ident_file but we + * like systems likes to do that), so look at config_file, hba_file and ident_file but we * can omit external_pid_file ;) * * On error we need to return but before that execute pg_stop_backup() @@ -867,90 +868,90 @@ do_standby_clone(void) sprintf(master_control_file, "%s/global/pg_control", master_data_directory); sprintf(local_control_file, "%s/global", dest_dir); if (!create_directory(local_control_file)) - { - fprintf(stderr, _("%s: couldn't create directory %s ... "), - progname, dest_dir); + { + fprintf(stderr, _("%s: couldn't create directory %s ... "), + progname, dest_dir); goto stop_backup; } - r = copy_remote_files(host, remote_user, master_control_file, local_control_file, false); + r = copy_remote_files(host, remote_user, master_control_file, local_control_file, false); if (r != 0) goto stop_backup; - r = copy_remote_files(host, remote_user, master_data_directory, dest_dir, true); + r = copy_remote_files(host, remote_user, master_data_directory, dest_dir, true); if (r != 0) goto stop_backup; - /* + /* * Copy tablespace locations, i'm doing this separately because i couldn't find and appropiate - * rsync option but besides we could someday make all these rsync happen concurrently - */ - sprintf(sqlquery, "select spclocation from pg_tablespace where spcname not in ('pg_default', 'pg_global')"); - res = PQexec(conn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - fprintf(stderr, "Can't get info about tablespaces: %s\n", PQerrorMessage(conn)); - PQclear(res); - goto stop_backup; - } - for (i = 0; i < PQntuples(res); i++) + * rsync option but besides we could someday make all these rsync happen concurrently + */ + sprintf(sqlquery, "select spclocation from pg_tablespace where spcname not in ('pg_default', 'pg_global')"); + res = PQexec(conn, sqlquery); + if (PQresultStatus(res) != PGRES_TUPLES_OK) { - r = copy_remote_files(host, remote_user, PQgetvalue(res, i, 0), PQgetvalue(res, i, 0), true); + fprintf(stderr, "Can't get info about tablespaces: %s\n", PQerrorMessage(conn)); + PQclear(res); + goto stop_backup; + } + for (i = 0; i < PQntuples(res); i++) + { + r = copy_remote_files(host, remote_user, PQgetvalue(res, i, 0), PQgetvalue(res, i, 0), true); if (r != 0) goto stop_backup; } - r = copy_remote_files(host, remote_user, master_config_file, dest_dir, false); + r = copy_remote_files(host, remote_user, master_config_file, dest_dir, false); if (r != 0) goto stop_backup; - r = copy_remote_files(host, remote_user, master_hba_file, dest_dir, false); + r = copy_remote_files(host, remote_user, master_hba_file, dest_dir, false); if (r != 0) goto stop_backup; - r = copy_remote_files(host, remote_user, master_ident_file, dest_dir, false); + r = copy_remote_files(host, remote_user, master_ident_file, dest_dir, false); if (r != 0) goto stop_backup; stop_backup: - /* inform the master that we have finished the backup */ - conn = PQconnectdbParams(keywords, values, true); - if (!conn) - { - fprintf(stderr, _("%s: could not connect to master\n"), - progname); - return; - } + /* inform the master that we have finished the backup */ + conn = PQconnectdbParams(keywords, values, true); + if (!conn) + { + fprintf(stderr, _("%s: could not connect to master\n"), + progname); + return; + } - fprintf(stderr, "Finishing backup...\n"); + fprintf(stderr, "Finishing backup...\n"); sprintf(sqlquery, "SELECT pg_xlogfile_name(pg_stop_backup())"); - res = PQexec(conn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - fprintf(stderr, "Can't stop backup: %s\n", PQerrorMessage(conn)); - PQclear(res); - PQfinish(conn); - return; - } + res = PQexec(conn, sqlquery); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + fprintf(stderr, "Can't stop backup: %s\n", PQerrorMessage(conn)); + PQclear(res); + PQfinish(conn); + return; + } last_wal_segment = PQgetvalue(res, 0, 0); - PQclear(res); - PQfinish(conn); + PQclear(res); + PQfinish(conn); /* Now, if the rsync failed then exit */ if (r != 0) return; if (verbose) - printf(_("%s requires primary to keep WAL files %s until at least %s\n"), - progname, first_wal_segment, last_wal_segment); + printf(_("%s requires primary to keep WAL files %s until at least %s\n"), + progname, first_wal_segment, last_wal_segment); /* we need to create the pg_xlog sub directory too, i'm reusing a variable here */ sprintf(local_control_file, "%s/pg_xlog", dest_dir); if (!create_directory(local_control_file)) - { - fprintf(stderr, _("%s: couldn't create directory %s, you will need to do it manually...\n"), - progname, dest_dir); + { + fprintf(stderr, _("%s: couldn't create directory %s, you will need to do it manually...\n"), + progname, dest_dir); } /* Finally, write the recovery.conf file */ @@ -961,7 +962,7 @@ stop_backup: } -static void +static void do_standby_promote(void) { PGconn *conn; @@ -971,7 +972,7 @@ do_standby_promote(void) char myClusterName[MAXLEN]; int myLocalId = -1; - char conninfo[MAXLEN]; + char conninfo[MAXLEN]; PGconn *old_master_conn; int old_master_id; @@ -985,24 +986,24 @@ do_standby_promote(void) /* * Read the configuration file: repmgr.conf - */ + */ parse_config(config_file, myClusterName, &myLocalId, conninfo); - if (myLocalId == -1) + if (myLocalId == -1) { fprintf(stderr, "Node information is missing. " - "Check the configuration file.\n"); + "Check the configuration file.\n"); exit(1); } /* We need to connect to check configuration */ - conn = establishDBConnection(conninfo, true); + conn = establishDBConnection(conninfo, true); /* we need v9 or better */ pg_version(conn, standby_version); if (strcmp(standby_version, "") == 0) { PQfinish(conn); - fprintf(stderr, _("%s needs standby to be PostgreSQL 9.0 or better\n"), progname); + fprintf(stderr, _("%s needs standby to be PostgreSQL 9.0 or better\n"), progname); return; } @@ -1014,7 +1015,7 @@ do_standby_promote(void) } /* we also need to check if there isn't any master already */ - old_master_conn = getMasterConnection(conn, myLocalId, myClusterName, &old_master_id); + old_master_conn = getMasterConnection(conn, myLocalId, myClusterName, &old_master_id); if (old_master_conn != NULL) { PQfinish(old_master_conn); @@ -1024,21 +1025,21 @@ do_standby_promote(void) if (verbose) printf(_("\n%s: Promoting standby...\n"), progname); - + /* Get the data directory full path and the last subdirectory */ sprintf(sqlquery, "SELECT setting " - " FROM pg_settings WHERE name = 'data_directory'"); - res = PQexec(conn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - fprintf(stderr, "Can't get info about data directory: %s\n", PQerrorMessage(conn)); - PQclear(res); - PQfinish(conn); - return; - } + " FROM pg_settings WHERE name = 'data_directory'"); + res = PQexec(conn, sqlquery); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + fprintf(stderr, "Can't get info about data directory: %s\n", PQerrorMessage(conn)); + PQclear(res); + PQfinish(conn); + return; + } strcpy(data_dir, PQgetvalue(res, 0, 0)); - PQclear(res); - PQfinish(conn); + PQclear(res); + PQfinish(conn); sprintf(recovery_file_path, "%s/%s", data_dir, RECOVERY_FILE); sprintf(recovery_done_path, "%s/%s", data_dir, RECOVERY_DONE_FILE); @@ -1047,29 +1048,29 @@ do_standby_promote(void) /* We assume the pg_ctl script is in the PATH */ sprintf(script, "pg_ctl -D %s -m fast restart", data_dir); r = system(script); - if (r != 0) - { - fprintf(stderr, "Can't restart service\n"); + if (r != 0) + { + fprintf(stderr, "Can't restart service\n"); return; - } + } /* reconnect to check we got promoted */ - /* - * XXX i'm removing this because it gives an annoying message saying couldn't connect - * but is just the server starting up -* conn = establishDBConnection(conninfo, true); -* if (is_standby(conn)) -* fprintf(stderr, "\n%s: STANDBY PROMOTE failed, this is still a standby node.\n", progname); -* else -* fprintf(stderr, "\n%s: you should REINDEX any hash indexes you have.\n", progname); -* PQfinish(conn); + /* + * XXX i'm removing this because it gives an annoying message saying couldn't connect + * but is just the server starting up + * conn = establishDBConnection(conninfo, true); + * if (is_standby(conn)) + * fprintf(stderr, "\n%s: STANDBY PROMOTE failed, this is still a standby node.\n", progname); + * else + * fprintf(stderr, "\n%s: you should REINDEX any hash indexes you have.\n", progname); + * PQfinish(conn); */ return; } -static void +static void do_standby_follow(void) { PGconn *conn; @@ -1079,7 +1080,7 @@ do_standby_follow(void) char myClusterName[MAXLEN]; int myLocalId = -1; - char conninfo[MAXLEN]; + char conninfo[MAXLEN]; PGconn *master_conn; int master_id; @@ -1092,17 +1093,17 @@ do_standby_follow(void) /* * Read the configuration file: repmgr.conf - */ + */ parse_config(config_file, myClusterName, &myLocalId, conninfo); - if (myLocalId == -1) + if (myLocalId == -1) { fprintf(stderr, "Node information is missing. " - "Check the configuration file.\n"); + "Check the configuration file.\n"); exit(1); } /* We need to connect to check configuration */ - conn = establishDBConnection(conninfo, true); + conn = establishDBConnection(conninfo, true); /* Check we are in a standby node */ if (!is_standby(conn)) @@ -1116,12 +1117,12 @@ do_standby_follow(void) if (strcmp(standby_version, "") == 0) { PQfinish(conn); - fprintf(stderr, _("\n%s needs standby to be PostgreSQL 9.0 or better\n"), progname); + fprintf(stderr, _("\n%s needs standby to be PostgreSQL 9.0 or better\n"), progname); return; } /* we also need to check if there is any master in the cluster */ - master_conn = getMasterConnection(conn, myLocalId, myClusterName, &master_id); + master_conn = getMasterConnection(conn, myLocalId, myClusterName, &master_id); if (master_conn == NULL) { PQfinish(conn); @@ -1143,7 +1144,7 @@ do_standby_follow(void) { PQfinish(conn); PQfinish(master_conn); - fprintf(stderr, _("%s needs master to be PostgreSQL 9.0 or better\n"), progname); + fprintf(stderr, _("%s needs master to be PostgreSQL 9.0 or better\n"), progname); return; } @@ -1152,14 +1153,14 @@ do_standby_follow(void) { PQfinish(conn); PQfinish(master_conn); - fprintf(stderr, _("%s needs versions of both master (%s) and standby (%s) to match.\n"), - progname, master_version, standby_version); + fprintf(stderr, _("%s needs versions of both master (%s) and standby (%s) to match.\n"), + progname, master_version, standby_version); return; } - /* - * set the host and masterport variables with the master ones - * before closing the connection because we will need them to + /* + * set the host and masterport variables with the master ones + * before closing the connection because we will need them to * recreate the recovery.conf file */ host = malloc(20); @@ -1170,48 +1171,48 @@ do_standby_follow(void) if (verbose) printf(_("\n%s: Changing standby's master...\n"), progname); - + /* Get the data directory full path */ sprintf(sqlquery, "SELECT setting " - " FROM pg_settings WHERE name = 'data_directory'"); - res = PQexec(conn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - fprintf(stderr, "Can't get info about data directory: %s\n", PQerrorMessage(conn)); - PQclear(res); - PQfinish(conn); - return; - } + " FROM pg_settings WHERE name = 'data_directory'"); + res = PQexec(conn, sqlquery); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + fprintf(stderr, "Can't get info about data directory: %s\n", PQerrorMessage(conn)); + PQclear(res); + PQfinish(conn); + return; + } strcpy(data_dir, PQgetvalue(res, 0, 0)); - PQclear(res); - PQfinish(conn); + PQclear(res); + PQfinish(conn); /* write the recovery.conf file */ if (!create_recovery_file(data_dir)) - return; + return; /* Finally, restart the service */ /* We assume the pg_ctl script is in the PATH */ sprintf(script, "pg_ctl -D %s -m fast restart", data_dir); r = system(script); - if (r != 0) - { - fprintf(stderr, "Can't restart service\n"); + if (r != 0) + { + fprintf(stderr, "Can't restart service\n"); return; - } + } return; } -static void +static void help(const char *progname) { - printf(_("\n%s: Replicator manager \n"), progname); - printf(_("Usage:\n")); - printf(_(" %s [OPTIONS] master {register}\n"), progname); - printf(_(" %s [OPTIONS] standby {register|clone|promote|follow}\n"), progname); - printf(_("\nGeneral options:\n")); + printf(_("\n%s: Replicator manager \n"), progname); + printf(_("Usage:\n")); + printf(_(" %s [OPTIONS] master {register}\n"), progname); + printf(_(" %s [OPTIONS] standby {register|clone|promote|follow}\n"), progname); + printf(_("\nGeneral options:\n")); printf(_(" --help show this help, then exit\n")); printf(_(" --version output version information, then exit\n")); printf(_(" --verbose output verbose activity information\n")); @@ -1226,16 +1227,16 @@ help(const char *progname) printf(_(" -R, --remote-user=USERNAME database server username for rsync\n")); printf(_(" -w, --wal-keep-segments=VALUE minimum value for the GUC wal_keep_segments (default: 5000)\n")); printf(_(" -F, --force force potentially dangerous operations to happen\n")); - + printf(_("\n%s performs some tasks like clone a node, promote it "), progname); - printf(_("or making follow another node and then exits.\n")); - printf(_("COMMANDS:\n")); - printf(_(" master register - registers the master in a cluster\n")); - printf(_(" standby register - registers a standby in a cluster\n")); - printf(_(" standby clone [node] - allows creation of a new standby\n")); - printf(_(" standby promote - allows manual promotion of a specific standby into a ")); - printf(_("new master in the event of a failover\n")); - printf(_(" standby follow - allows the standby to re-point itself to a new master\n")); + printf(_("or making follow another node and then exits.\n")); + printf(_("COMMANDS:\n")); + printf(_(" master register - registers the master in a cluster\n")); + printf(_(" standby register - registers a standby in a cluster\n")); + printf(_(" standby clone [node] - allows creation of a new standby\n")); + printf(_(" standby promote - allows manual promotion of a specific standby into a ")); + printf(_("new master in the event of a failover\n")); + printf(_(" standby follow - allows the standby to re-point itself to a new master\n")); } @@ -1248,31 +1249,31 @@ create_recovery_file(const char *data_dir) sprintf(recovery_file_path, "%s/%s", data_dir, RECOVERY_FILE); - recovery_file = fopen(recovery_file_path, "w"); - if (recovery_file == NULL) - { - fprintf(stderr, "could not create recovery.conf file, it could be necesary to create it manually\n"); + recovery_file = fopen(recovery_file_path, "w"); + if (recovery_file == NULL) + { + fprintf(stderr, "could not create recovery.conf file, it could be necesary to create it manually\n"); return false; - } + } sprintf(line, "standby_mode = 'on'\n"); if (fputs(line, recovery_file) == EOF) - { - fprintf(stderr, "recovery file could not be written, it could be necesary to create it manually\n"); - fclose(recovery_file); + { + fprintf(stderr, "recovery file could not be written, it could be necesary to create it manually\n"); + fclose(recovery_file); return false; - } + } sprintf(line, "primary_conninfo = 'host=%s port=%s'\n", host, ((masterport==NULL) ? "5432" : masterport)); if (fputs(line, recovery_file) == EOF) - { - fprintf(stderr, "recovery file could not be written, it could be necesary to create it manually\n"); - fclose(recovery_file); + { + fprintf(stderr, "recovery file could not be written, it could be necesary to create it manually\n"); + fclose(recovery_file); return false; - } + } - /*FreeFile(recovery_file);*/ - fclose(recovery_file); + /*FreeFile(recovery_file);*/ + fclose(recovery_file); return true; } @@ -1286,7 +1287,7 @@ copy_remote_files(char *host, char *remote_user, char *remote_path, char *local_ char host_string[QUERY_STR_LEN]; int r; - sprintf(options, "--archive --checksum --compress --progress --rsh=ssh"); + sprintf(options, "--archive --checksum --compress --progress --rsh=ssh"); if (force) strcat(options, " --delete"); @@ -1302,23 +1303,23 @@ copy_remote_files(char *host, char *remote_user, char *remote_path, char *local_ if (is_directory) { strcat(options, " --exclude=pg_xlog* --exclude=pg_control --exclude=*.pid"); - sprintf(script, "rsync %s %s:%s/* %s", - options, host_string, remote_path, local_path); + sprintf(script, "rsync %s %s:%s/* %s", + options, host_string, remote_path, local_path); } else { - sprintf(script, "rsync %s %s:%s %s/.", - options, host_string, remote_path, local_path); + sprintf(script, "rsync %s %s:%s %s/.", + options, host_string, remote_path, local_path); } if (verbose) printf("rsync command line: '%s'\n",script); r = system(script); - - if (r != 0) - fprintf(stderr, _("Can't rsync from remote file or directory (%s:%s)\n"), - host_string, remote_path); + + if (r != 0) + fprintf(stderr, _("Can't rsync from remote file or directory (%s:%s)\n"), + host_string, remote_path); return r; } @@ -1334,96 +1335,101 @@ check_parameters_for_action(const int action) switch (action) { - case MASTER_REGISTER: - /* - * To register a master we only need the repmgr.conf - * all other parameters are at least useless and could be - * confusing so reject them - */ - if ((host != NULL) || (masterport != NULL) || (username != NULL) || - (dbname != NULL)) - { - fprintf(stderr, "\nYou can't use connection parameters to the master when issuing a MASTER REGISTER command."); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - ok = false; - } - if (dest_dir != NULL) { - fprintf(stderr, "\nYou don't need a destination directory for MASTER REGISTER command"); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - ok = false; - } - break; - case STANDBY_REGISTER: - /* - * To register a standby we only need the repmgr.conf - * we don't need connection parameters to the master - * because we can detect the master in repl_nodes - */ - if ((host != NULL) || (masterport != NULL) || (username != NULL) || - (dbname != NULL)) - { - fprintf(stderr, "\nYou can't use connection parameters to the master when issuing a STANDBY REGISTER command."); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - ok = false; - } - if (dest_dir != NULL) { - fprintf(stderr, "\nYou don't need a destination directory for STANDBY REGISTER command"); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - ok = false; - } - break; - case STANDBY_PROMOTE: - /* - * To promote a standby we only need the repmgr.conf - * we don't want connection parameters to the master - * because we will try to detect the master in repl_nodes - * if we can't find it then the promote action will be cancelled - */ - if ((host != NULL) || (masterport != NULL) || (username != NULL) || - (dbname != NULL)) - { - fprintf(stderr, "\nYou can't use connection parameters to the master when issuing a STANDBY PROMOTE command."); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - ok = false; - } - if (dest_dir != NULL) { - fprintf(stderr, "\nYou don't need a destination directory for STANDBY PROMOTE command"); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - ok = false; - } - break; - case STANDBY_FOLLOW: - /* - * To make a standby follow a master we only need the repmgr.conf - * we don't want connection parameters to the new master - * because we will try to detect the master in repl_nodes - * if we can't find it then the follow action will be cancelled - */ - if ((host != NULL) || (masterport != NULL) || (username != NULL) || - (dbname != NULL)) - { - fprintf(stderr, "\nYou can't use connection parameters to the master when issuing a STANDBY FOLLOW command."); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - ok = false; - } - if (dest_dir != NULL) { - fprintf(stderr, "\nYou don't need a destination directory for STANDBY FOLLOW command"); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - ok = false; - } - break; - case STANDBY_CLONE: - /* - * To clone a master into a standby we need connection parameters - * repmgr.conf is useless because we don't have a server running - * in the standby - */ - if (config_file != NULL) { - fprintf(stderr, "\nYou need to use connection parameters to the master when issuing a STANDBY CLONE command."); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - ok = false; - } - break; + case MASTER_REGISTER: + /* + * To register a master we only need the repmgr.conf + * all other parameters are at least useless and could be + * confusing so reject them + */ + if ((host != NULL) || (masterport != NULL) || (username != NULL) || + (dbname != NULL)) + { + fprintf(stderr, "\nYou can't use connection parameters to the master when issuing a MASTER REGISTER command."); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + ok = false; + } + if (dest_dir != NULL) + { + fprintf(stderr, "\nYou don't need a destination directory for MASTER REGISTER command"); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + ok = false; + } + break; + case STANDBY_REGISTER: + /* + * To register a standby we only need the repmgr.conf + * we don't need connection parameters to the master + * because we can detect the master in repl_nodes + */ + if ((host != NULL) || (masterport != NULL) || (username != NULL) || + (dbname != NULL)) + { + fprintf(stderr, "\nYou can't use connection parameters to the master when issuing a STANDBY REGISTER command."); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + ok = false; + } + if (dest_dir != NULL) + { + fprintf(stderr, "\nYou don't need a destination directory for STANDBY REGISTER command"); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + ok = false; + } + break; + case STANDBY_PROMOTE: + /* + * To promote a standby we only need the repmgr.conf + * we don't want connection parameters to the master + * because we will try to detect the master in repl_nodes + * if we can't find it then the promote action will be cancelled + */ + if ((host != NULL) || (masterport != NULL) || (username != NULL) || + (dbname != NULL)) + { + fprintf(stderr, "\nYou can't use connection parameters to the master when issuing a STANDBY PROMOTE command."); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + ok = false; + } + if (dest_dir != NULL) + { + fprintf(stderr, "\nYou don't need a destination directory for STANDBY PROMOTE command"); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + ok = false; + } + break; + case STANDBY_FOLLOW: + /* + * To make a standby follow a master we only need the repmgr.conf + * we don't want connection parameters to the new master + * because we will try to detect the master in repl_nodes + * if we can't find it then the follow action will be cancelled + */ + if ((host != NULL) || (masterport != NULL) || (username != NULL) || + (dbname != NULL)) + { + fprintf(stderr, "\nYou can't use connection parameters to the master when issuing a STANDBY FOLLOW command."); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + ok = false; + } + if (dest_dir != NULL) + { + fprintf(stderr, "\nYou don't need a destination directory for STANDBY FOLLOW command"); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + ok = false; + } + break; + case STANDBY_CLONE: + /* + * To clone a master into a standby we need connection parameters + * repmgr.conf is useless because we don't have a server running + * in the standby + */ + if (config_file != NULL) + { + fprintf(stderr, "\nYou need to use connection parameters to the master when issuing a STANDBY CLONE command."); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + ok = false; + } + break; } return ok; diff --git a/repmgr.h b/repmgr.h index e099f62c..ec32b995 100644 --- a/repmgr.h +++ b/repmgr.h @@ -1,7 +1,7 @@ /* * repmgr.h * Copyright (c) 2ndQuadrant, 2010 - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or diff --git a/repmgrd.c b/repmgrd.c index ee646a87..b7e0d1b5 100644 --- a/repmgrd.c +++ b/repmgrd.c @@ -3,8 +3,8 @@ * Copyright (C) 2ndQuadrant, 2010 * * This module connects to the nodes of a replication cluster and monitors - * how far are they from master - * + * how far are they from master + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -78,13 +78,14 @@ static void setup_cancel_handler(void); { \ MonitorExecute(); \ sleep(3); \ - } + } int main(int argc, char **argv) { - static struct option long_options[] = { + static struct option long_options[] = + { {"config", required_argument, NULL, 'f'}, {"verbose", no_argument, NULL, 'v'}, {NULL, 0, NULL, 0} @@ -93,7 +94,7 @@ main(int argc, char **argv) int optindex; int c; - char conninfo[MAXLEN]; + char conninfo[MAXLEN]; char standby_version[MAXVERSIONSTR]; progname = get_progname(argv[0]); @@ -117,20 +118,20 @@ main(int argc, char **argv) { switch (c) { - case 'f': - config_file = optarg; - break; - case 'v': - verbose = true; - break; - default: - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - exit(1); + case 'f': + config_file = optarg; + break; + case 'v': + verbose = true; + break; + default: + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + exit(1); } } setup_cancel_handler(); - + if (config_file == NULL) { config_file = malloc(5 + sizeof(CONFIG_FILE)); @@ -139,30 +140,30 @@ main(int argc, char **argv) /* * Read the configuration file: repmgr.conf - */ + */ parse_config(config_file, myClusterName, &myLocalId, conninfo); - if (myLocalId == -1) + if (myLocalId == -1) { fprintf(stderr, "Node information is missing. " - "Check the configuration file.\n"); + "Check the configuration file.\n"); exit(1); } - myLocalConn = establishDBConnection(conninfo, true); + myLocalConn = establishDBConnection(conninfo, true); /* should be v9 or better */ pg_version(myLocalConn, standby_version); if (strcmp(standby_version, "") == 0) { PQfinish(myLocalConn); - fprintf(stderr, _("%s needs standby to be PostgreSQL 9.0 or better\n"), progname); + fprintf(stderr, _("%s needs standby to be PostgreSQL 9.0 or better\n"), progname); exit(1); } - /* - * Set my server mode, establish a connection to primary + /* + * Set my server mode, establish a connection to primary * and start monitor - */ + */ myLocalMode = is_standby(myLocalConn) ? STANDBY_MODE : PRIMARY_MODE; if (myLocalMode == PRIMARY_MODE) { @@ -182,13 +183,13 @@ main(int argc, char **argv) checkNodeConfiguration(conninfo); if (myLocalMode == STANDBY_MODE) { - MonitorCheck(); + MonitorCheck(); } - /* close the connection to the database and cleanup */ - CloseConnections(); + /* close the connection to the database and cleanup */ + CloseConnections(); - return 0; + return 0; } @@ -200,7 +201,7 @@ main(int argc, char **argv) static void MonitorExecute(void) { - PGresult *res; + PGresult *res; char monitor_standby_timestamp[MAXLEN]; char last_wal_primary_location[MAXLEN]; char last_wal_standby_received[MAXLEN]; @@ -212,9 +213,9 @@ MonitorExecute(void) int connection_retries; - /* - * Check if the master is still available, if after 5 minutes of retries - * we cannot reconnect, try to get a new master. + /* + * Check if the master is still available, if after 5 minutes of retries + * we cannot reconnect, try to get a new master. */ for (connection_retries = 0; connection_retries < 15; connection_retries++) { @@ -225,7 +226,7 @@ MonitorExecute(void) sleep(20); PQreset(primaryConn); - } + } else { fprintf(stderr, "\n%s: Connection to master has been restored, continue monitoring.\n", progname); @@ -261,53 +262,53 @@ MonitorExecute(void) /* Check if we still are a standby, we could have been promoted */ if (!is_standby(myLocalConn)) - { - fprintf(stderr, "\n%s: seems like we have been promoted, so exit from monitoring...\n", - progname); + { + fprintf(stderr, "\n%s: seems like we have been promoted, so exit from monitoring...\n", + progname); CloseConnections(); exit(1); } - /* + /* * first check if there is a command being executed, * and if that is the case, cancel the query so i can - * insert the current record - */ + * insert the current record + */ if (PQisBusy(primaryConn) == 1) CancelQuery(); /* Get local xlog info */ - sprintf(sqlquery, - "SELECT CURRENT_TIMESTAMP, pg_last_xlog_receive_location(), " - "pg_last_xlog_replay_location()"); + sprintf(sqlquery, + "SELECT CURRENT_TIMESTAMP, pg_last_xlog_receive_location(), " + "pg_last_xlog_replay_location()"); - res = PQexec(myLocalConn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - fprintf(stderr, "PQexec failed: %s\n", PQerrorMessage(myLocalConn)); - PQclear(res); + res = PQexec(myLocalConn, sqlquery); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + fprintf(stderr, "PQexec failed: %s\n", PQerrorMessage(myLocalConn)); + PQclear(res); /* if there is any error just let it be and retry in next loop */ - return; - } + return; + } - strcpy(monitor_standby_timestamp, PQgetvalue(res, 0, 0)); - strcpy(last_wal_standby_received , PQgetvalue(res, 0, 1)); - strcpy(last_wal_standby_applied , PQgetvalue(res, 0, 2)); - PQclear(res); + strcpy(monitor_standby_timestamp, PQgetvalue(res, 0, 0)); + strcpy(last_wal_standby_received , PQgetvalue(res, 0, 1)); + strcpy(last_wal_standby_applied , PQgetvalue(res, 0, 2)); + PQclear(res); /* Get primary xlog info */ - sprintf(sqlquery, "SELECT pg_current_xlog_location() "); + sprintf(sqlquery, "SELECT pg_current_xlog_location() "); - res = PQexec(primaryConn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - fprintf(stderr, "PQexec failed: %s\n", PQerrorMessage(primaryConn)); - PQclear(res); - return; - } + res = PQexec(primaryConn, sqlquery); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + fprintf(stderr, "PQexec failed: %s\n", PQerrorMessage(primaryConn)); + PQclear(res); + return; + } - strcpy(last_wal_primary_location, PQgetvalue(res, 0, 0)); - PQclear(res); + strcpy(last_wal_primary_location, PQgetvalue(res, 0, 0)); + PQclear(res); /* Calculate the lag */ lsn_primary = walLocationToBytes(last_wal_primary_location); @@ -318,15 +319,15 @@ MonitorExecute(void) * Build the SQL to execute on primary */ sprintf(sqlquery, - "INSERT INTO repmgr_%s.repl_monitor " - "VALUES(%d, %d, '%s'::timestamp with time zone, " - " '%s', '%s', " - " %lld, %lld)", myClusterName, - primaryId, myLocalId, monitor_standby_timestamp, - last_wal_primary_location, - last_wal_standby_received, - (lsn_primary - lsn_standby_received), - (lsn_standby_received - lsn_standby_applied)); + "INSERT INTO repmgr_%s.repl_monitor " + "VALUES(%d, %d, '%s'::timestamp with time zone, " + " '%s', '%s', " + " %lld, %lld)", myClusterName, + primaryId, myLocalId, monitor_standby_timestamp, + last_wal_primary_location, + last_wal_standby_received, + (lsn_primary - lsn_standby_received), + (lsn_standby_received - lsn_standby_applied)); /* * Execute the query asynchronously, but don't check for a result. We @@ -334,27 +335,27 @@ MonitorExecute(void) */ if (PQsendQuery(primaryConn, sqlquery) == 0) fprintf(stderr, "Query could not be sent to primary. %s\n", - PQerrorMessage(primaryConn)); + PQerrorMessage(primaryConn)); } static void checkClusterConfiguration(void) { - PGresult *res; + PGresult *res; sprintf(sqlquery, "SELECT oid FROM pg_class " - " WHERE oid = 'repmgr_%s.repl_nodes'::regclass", - myClusterName); - res = PQexec(myLocalConn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - fprintf(stderr, "PQexec failed: %s\n", PQerrorMessage(myLocalConn)); - PQclear(res); - PQfinish(myLocalConn); - PQfinish(primaryConn); + " WHERE oid = 'repmgr_%s.repl_nodes'::regclass", + myClusterName); + res = PQexec(myLocalConn, sqlquery); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + fprintf(stderr, "PQexec failed: %s\n", PQerrorMessage(myLocalConn)); + PQclear(res); + PQfinish(myLocalConn); + PQfinish(primaryConn); exit(1); - } + } /* * If there isn't any results then we have not configured a primary node yet @@ -363,10 +364,10 @@ checkClusterConfiguration(void) */ if (PQntuples(res) == 0) { - fprintf(stderr, "The replication cluster is not configured\n"); - PQclear(res); - PQfinish(myLocalConn); - PQfinish(primaryConn); + fprintf(stderr, "The replication cluster is not configured\n"); + PQclear(res); + PQfinish(myLocalConn); + PQfinish(primaryConn); exit(1); } PQclear(res); @@ -376,41 +377,41 @@ checkClusterConfiguration(void) static void checkNodeConfiguration(char *conninfo) { - PGresult *res; + PGresult *res; /* * Check if we have my node information in repl_nodes */ sprintf(sqlquery, "SELECT * FROM repmgr_%s.repl_nodes " - " WHERE id = %d AND cluster = '%s' ", - myClusterName, myLocalId, myClusterName); + " WHERE id = %d AND cluster = '%s' ", + myClusterName, myLocalId, myClusterName); - res = PQexec(myLocalConn, sqlquery); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - fprintf(stderr, "PQexec failed: %s\n", PQerrorMessage(myLocalConn)); - PQclear(res); - PQfinish(myLocalConn); - PQfinish(primaryConn); + res = PQexec(myLocalConn, sqlquery); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + fprintf(stderr, "PQexec failed: %s\n", PQerrorMessage(myLocalConn)); + PQclear(res); + PQfinish(myLocalConn); + PQfinish(primaryConn); exit(1); - } + } /* * If there isn't any results then we have not configured this node yet - * in repmgr, if that is the case we will insert the node to the cluster + * in repmgr, if that is the case we will insert the node to the cluster */ if (PQntuples(res) == 0) { - PQclear(res); + PQclear(res); /* Adding the node */ sprintf(sqlquery, "INSERT INTO repmgr_%s.repl_nodes " - "VALUES (%d, '%s', '%s')", - myClusterName, myLocalId, myClusterName, conninfo); + "VALUES (%d, '%s', '%s')", + myClusterName, myLocalId, myClusterName, conninfo); - if (!PQexec(primaryConn, sqlquery)) + if (!PQexec(primaryConn, sqlquery)) { fprintf(stderr, "Cannot insert node details, %s\n", - PQerrorMessage(primaryConn)); + PQerrorMessage(primaryConn)); PQfinish(myLocalConn); PQfinish(primaryConn); exit(1); @@ -420,33 +421,33 @@ checkNodeConfiguration(char *conninfo) } -static unsigned long long int +static unsigned long long int walLocationToBytes(char *wal_location) { - unsigned int xlogid; - unsigned int xrecoff; + unsigned int xlogid; + unsigned int xrecoff; - if (sscanf(wal_location, "%X/%X", &xlogid, &xrecoff) != 2) - { - fprintf(stderr, "wrong log location format: %s\n", wal_location); - return 0; - } - return ((xlogid * 16 * 1024 * 1024 * 255) + xrecoff); + if (sscanf(wal_location, "%X/%X", &xlogid, &xrecoff) != 2) + { + fprintf(stderr, "wrong log location format: %s\n", wal_location); + return 0; + } + return ((xlogid * 16 * 1024 * 1024 * 255) + xrecoff); } -static void +static void help(const char *progname) { - printf(_("\n%s: Replicator manager daemon \n"), progname); - printf(_("Usage:\n")); - printf(_(" %s [OPTIONS]\n"), progname); - printf(_("\nOptions:\n")); + printf(_("\n%s: Replicator manager daemon \n"), progname); + printf(_("Usage:\n")); + printf(_(" %s [OPTIONS]\n"), progname); + printf(_("\nOptions:\n")); printf(_(" --help show this help, then exit\n")); printf(_(" --version output version information, then exit\n")); printf(_(" --verbose output verbose activity information\n")); printf(_(" -f, --config_file=PATH database to connect to\n")); - printf(_("\n%s monitors a cluster of servers.\n"), progname); + printf(_("\n%s monitors a cluster of servers.\n"), progname); } @@ -455,13 +456,13 @@ help(const char *progname) static void handle_sigint(SIGNAL_ARGS) { - CloseConnections(); + CloseConnections(); } static void setup_cancel_handler(void) { - pqsignal(SIGINT, handle_sigint); + pqsignal(SIGINT, handle_sigint); } #endif @@ -469,13 +470,13 @@ setup_cancel_handler(void) static void CancelQuery(void) { - char errbuf[256]; - PGcancel *pgcancel; + char errbuf[256]; + PGcancel *pgcancel; - pgcancel = PQgetCancel(primaryConn); + pgcancel = PQgetCancel(primaryConn); - if (!pgcancel || PQcancel(pgcancel, errbuf, 256) == 0) - fprintf(stderr, "Can't stop current query: %s", errbuf); + if (!pgcancel || PQcancel(pgcancel, errbuf, 256) == 0) + fprintf(stderr, "Can't stop current query: %s", errbuf); - PQfreeCancel(pgcancel); + PQfreeCancel(pgcancel); }