mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-26 08:36:30 +00:00
Merge remote-tracking branch 'tbrs/master' into heroku
Grab the configuration struct changes. It was expeditious to un-do some of my by-hand line-wrapping that avoids 80 character limit, though. Conflicts: config.c config.h repmgr.c repmgr.h repmgrd.c
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
|||||||
*.o
|
*.o
|
||||||
repmgr
|
repmgr
|
||||||
repmgrd
|
repmgrd
|
||||||
|
README.html
|
||||||
|
|||||||
32
README.rst
32
README.rst
@@ -126,6 +126,35 @@ path either. The following recipe should work::
|
|||||||
|
|
||||||
sudo PATH="/usr/pgsql-9.0/bin:$PATH" make USE_PGXS=1 install
|
sudo PATH="/usr/pgsql-9.0/bin:$PATH" make USE_PGXS=1 install
|
||||||
|
|
||||||
|
Notes on Ubuntu, Debian or other Debian-based Builds
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The Debian packages of PostgreSQL put ``pg_config`` into the development package
|
||||||
|
called ``postgresql-server-dev-$version``.
|
||||||
|
|
||||||
|
When building repmgr against a Debian packages build, you may discover that some
|
||||||
|
development packages are needed as well. You will need the following development
|
||||||
|
packages installed::
|
||||||
|
|
||||||
|
sudo apt-get install libxslt-dev libxml2-dev libpam-dev libedit-dev
|
||||||
|
|
||||||
|
If your using Debian packages for PostgreSQL and are building repmgr with the
|
||||||
|
USE_PGXS option you also need to install the corresponding development package::
|
||||||
|
|
||||||
|
sudo apt-get install postgresql-server-dev-9.0
|
||||||
|
|
||||||
|
If you build and install repmgr manually it will not be on the system path. The
|
||||||
|
binaries will be installed in /usr/lib/postgresql/$version/bin/ which is not on
|
||||||
|
the default path. The reason behind this is that Ubuntu/Debian systems manage
|
||||||
|
multiple installed versions of PostgreSQL on the same system through a wrapper
|
||||||
|
called pg_wrapper and repmgr is not (yet) known to this wrapper.
|
||||||
|
|
||||||
|
You can solve this in many different ways, the most Debian like is to make an
|
||||||
|
alternate for repmgr and repmgrd::
|
||||||
|
|
||||||
|
sudo update-alternatives --install /usr/bin/repmgr repmgr /usr/lib/postgresql/9.0/bin/repmgr 10
|
||||||
|
sudo update-alternatives --install /usr/bin/repmgrd repmgrd /usr/lib/postgresql/9.0/bin/repmgrd 10
|
||||||
|
|
||||||
Confirm software was built correctly
|
Confirm software was built correctly
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@@ -136,8 +165,7 @@ is available by checking its version::
|
|||||||
repmgr --version
|
repmgr --version
|
||||||
repmgrd --version
|
repmgrd --version
|
||||||
|
|
||||||
You may need to include
|
You may need to include the full path of the binary instead, such as this RHEL example::
|
||||||
the full path of the binary instead, such as this RHEL example::
|
|
||||||
|
|
||||||
/usr/pgsql-9.0/bin/repmgr --version
|
/usr/pgsql-9.0/bin/repmgr --version
|
||||||
/usr/pgsql-9.0/bin/repmgrd --version
|
/usr/pgsql-9.0/bin/repmgrd --version
|
||||||
|
|||||||
38
config.c
38
config.c
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
parse_config(const char *config_file, char *cluster_name, int *node,
|
parse_config(const char *config_file, repmgr_config *config)
|
||||||
char *conninfo)
|
char *conninfo)
|
||||||
{
|
{
|
||||||
char *s, buff[MAXLINELENGTH];
|
char *s, buff[MAXLINELENGTH];
|
||||||
@@ -32,8 +32,16 @@ parse_config(const char *config_file, char *cluster_name, int *node,
|
|||||||
|
|
||||||
FILE *fp = fopen (config_file, "r");
|
FILE *fp = fopen (config_file, "r");
|
||||||
|
|
||||||
if (fp == NULL)
|
if (fp == NULL) {
|
||||||
return;
|
fprintf(stderr, _("Could not find configuration file '%s'\n"), config_file);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize */
|
||||||
|
memset(config->cluster_name, 0, sizeof(config->cluster_name));
|
||||||
|
config->node = -1;
|
||||||
|
memset(config->conninfo, 0, sizeof(config->conninfo));
|
||||||
|
memset(config->rsync_options, 0, sizeof(config->rsync_options));
|
||||||
|
|
||||||
/* Read next line */
|
/* Read next line */
|
||||||
while ((s = fgets (buff, sizeof buff, fp)) != NULL)
|
while ((s = fgets (buff, sizeof buff, fp)) != NULL)
|
||||||
@@ -47,18 +55,34 @@ parse_config(const char *config_file, char *cluster_name, int *node,
|
|||||||
|
|
||||||
/* 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 (cluster_name, value, MAXLEN);
|
strncpy (config->cluster_name, value, MAXLEN);
|
||||||
else if (strcmp(name, "node") == 0)
|
else if (strcmp(name, "node") == 0)
|
||||||
*node = atoi(value);
|
config->node = atoi(value);
|
||||||
else if (strcmp(name, "conninfo") == 0)
|
else if (strcmp(name, "conninfo") == 0)
|
||||||
strncpy (conninfo, value, MAXLEN);
|
strncpy (config->conninfo, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "rsync_options") == 0)
|
||||||
|
strncpy (config->rsync_options, value, QUERY_STR_LEN);
|
||||||
else
|
else
|
||||||
printf ("WARNING: %s/%s: Unknown name/value pair!\n", name, value);
|
printf ("WARNING: %s/%s: Unknown name/value pair!\n", name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Close file */
|
/* Close file */
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
|
|
||||||
|
/* Check config settings */
|
||||||
|
if (strnlen(config->cluster_name, MAXLEN)==0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Cluster name is missing. "
|
||||||
|
"Check the configuration file.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->node == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Node information is missing. "
|
||||||
|
"Check the configuration file.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
|
|||||||
11
config.h
11
config.h
@@ -17,7 +17,14 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void parse_config(const char *config_file, char *cluster_name, int *node,
|
typedef struct
|
||||||
char *service);
|
{
|
||||||
|
char cluster_name[MAXLEN];
|
||||||
|
int node;
|
||||||
|
char conninfo[MAXLEN];
|
||||||
|
char rsync_options[QUERY_STR_LEN];
|
||||||
|
} repmgr_config;
|
||||||
|
|
||||||
|
void parse_config(const char *config_file, repmgr_config *config);
|
||||||
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);
|
||||||
|
|||||||
140
repmgr.c
140
repmgr.c
@@ -44,7 +44,6 @@
|
|||||||
#define STANDBY_PROMOTE 4
|
#define STANDBY_PROMOTE 4
|
||||||
#define STANDBY_FOLLOW 5
|
#define STANDBY_FOLLOW 5
|
||||||
|
|
||||||
|
|
||||||
static void help(const char *progname);
|
static void help(const char *progname);
|
||||||
static bool create_recovery_file(const char *data_dir, char *master_conninfo);
|
static bool create_recovery_file(const char *data_dir, char *master_conninfo);
|
||||||
static int copy_remote_files(char *host, char *remote_user, char *remote_path,
|
static int copy_remote_files(char *host, char *remote_user, char *remote_path,
|
||||||
@@ -78,6 +77,7 @@ char *masterport = NULL;
|
|||||||
char *server_mode = NULL;
|
char *server_mode = NULL;
|
||||||
char *server_cmd = NULL;
|
char *server_cmd = NULL;
|
||||||
|
|
||||||
|
repmgr_config config = {};
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
@@ -263,6 +263,17 @@ main(int argc, char **argv)
|
|||||||
dbname = "postgres";
|
dbname = "postgres";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the configuration file: repmgr.conf
|
||||||
|
*/
|
||||||
|
parse_config(config_file, &config);
|
||||||
|
if (config.node == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Node information is missing. "
|
||||||
|
"Check the configuration file.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
keywords[2] = "user";
|
keywords[2] = "user";
|
||||||
values[2] = username;
|
values[2] = username;
|
||||||
keywords[3] = "dbname";
|
keywords[3] = "dbname";
|
||||||
@@ -306,25 +317,10 @@ do_master_register(void)
|
|||||||
PGresult *res;
|
PGresult *res;
|
||||||
char sqlquery[QUERY_STR_LEN];
|
char sqlquery[QUERY_STR_LEN];
|
||||||
|
|
||||||
char myClusterName[MAXLEN];
|
|
||||||
int myLocalId = -1;
|
|
||||||
char conninfo[MAXLEN];
|
|
||||||
|
|
||||||
bool schema_exists = false;
|
bool schema_exists = false;
|
||||||
char master_version[MAXVERSIONSTR];
|
char master_version[MAXVERSIONSTR];
|
||||||
|
|
||||||
/*
|
conn = establishDBConnection(config.conninfo, true);
|
||||||
* Read the configuration file: repmgr.conf
|
|
||||||
*/
|
|
||||||
parse_config(config_file, myClusterName, &myLocalId, conninfo);
|
|
||||||
if (myLocalId == -1)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Node information is missing. "
|
|
||||||
"Check the configuration file.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
conn = establishDBConnection(conninfo, true);
|
|
||||||
|
|
||||||
/* master should be v9 or better */
|
/* master should be v9 or better */
|
||||||
pg_version(conn, master_version);
|
pg_version(conn, master_version);
|
||||||
@@ -345,9 +341,7 @@ do_master_register(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if there is a schema for this cluster */
|
/* Check if there is a schema for this cluster */
|
||||||
sqlquery_snprintf(sqlquery,
|
sqlquery_sprintf(sqlquery, "SELECT 1 FROM pg_namespace WHERE nspname = 'repmgr_%s'", config.cluster_name);
|
||||||
"SELECT 1 FROM pg_namespace WHERE nspname = 'repmgr_%s'",
|
|
||||||
myClusterName);
|
|
||||||
res = PQexec(conn, sqlquery);
|
res = PQexec(conn, sqlquery);
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
{
|
{
|
||||||
@@ -362,7 +356,7 @@ do_master_register(void)
|
|||||||
{
|
{
|
||||||
if (!force) /* and we are not forcing so error */
|
if (!force) /* and we are not forcing so error */
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Schema repmgr_%s already exists.", myClusterName);
|
fprintf(stderr, "Schema repmgr_%s already exists.", config.cluster_name);
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
return;
|
return;
|
||||||
@@ -374,11 +368,11 @@ do_master_register(void)
|
|||||||
if (!schema_exists)
|
if (!schema_exists)
|
||||||
{
|
{
|
||||||
/* ok, create the schema */
|
/* ok, create the schema */
|
||||||
sqlquery_snprintf(sqlquery, "CREATE SCHEMA repmgr_%s", myClusterName);
|
sqlquery_snprintf(sqlquery, "CREATE SCHEMA repmgr_%s", config.cluster_name);
|
||||||
if (!PQexec(conn, sqlquery))
|
if (!PQexec(conn, sqlquery))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Cannot create the schema repmgr_%s: %s\n",
|
fprintf(stderr, "Cannot create the schema repmgr_%s: %s\n",
|
||||||
myClusterName, PQerrorMessage(conn));
|
config.cluster_name, PQerrorMessage(conn));
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -387,12 +381,11 @@ do_master_register(void)
|
|||||||
sqlquery_snprintf(sqlquery, "CREATE TABLE repmgr_%s.repl_nodes ( "
|
sqlquery_snprintf(sqlquery, "CREATE TABLE repmgr_%s.repl_nodes ( "
|
||||||
" id integer primary key, "
|
" id integer primary key, "
|
||||||
" cluster text not null, "
|
" cluster text not null, "
|
||||||
" conninfo text not null)", myClusterName);
|
" conninfo text not null)", config.cluster_name);
|
||||||
if (!PQexec(conn, sqlquery))
|
if (!PQexec(conn, sqlquery))
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Cannot create the table repmgr_%s.repl_nodes: %s\n",
|
config.cluster_name, PQerrorMessage(conn));
|
||||||
myClusterName, PQerrorMessage(conn));
|
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -404,13 +397,12 @@ do_master_register(void)
|
|||||||
" last_wal_primary_location TEXT NOT NULL, "
|
" last_wal_primary_location TEXT NOT NULL, "
|
||||||
" last_wal_standby_location TEXT NOT NULL, "
|
" last_wal_standby_location TEXT NOT NULL, "
|
||||||
" replication_lag BIGINT NOT NULL, "
|
" replication_lag BIGINT NOT NULL, "
|
||||||
" apply_lag BIGINT NOT NULL) ",
|
" apply_lag BIGINT NOT NULL) ", config.cluster_name);
|
||||||
myClusterName);
|
myClusterName);
|
||||||
if (!PQexec(conn, sqlquery))
|
if (!PQexec(conn, sqlquery))
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Cannot create the table repmgr_%s.repl_monitor: %s\n",
|
config.cluster_name, PQerrorMessage(conn));
|
||||||
myClusterName, PQerrorMessage(conn));
|
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -424,12 +416,11 @@ do_master_register(void)
|
|||||||
" last_wal_standby_location, pg_size_pretty(replication_lag) replication_lag, "
|
" 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 "
|
" pg_size_pretty(apply_lag) apply_lag, age(now(), last_monitor_time) AS time_lag "
|
||||||
" FROM monitor_info a "
|
" FROM monitor_info a "
|
||||||
" WHERE row_number = 1", myClusterName, myClusterName);
|
" WHERE row_number = 1", config.cluster_name, config.cluster_name);
|
||||||
if (!PQexec(conn, sqlquery))
|
if (!PQexec(conn, sqlquery))
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Cannot create the view repmgr_%s.repl_status: %s\n",
|
config.cluster_name, PQerrorMessage(conn));
|
||||||
myClusterName, PQerrorMessage(conn));
|
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -440,7 +431,7 @@ do_master_register(void)
|
|||||||
int id;
|
int id;
|
||||||
|
|
||||||
/* Ensure there isn't any other master already registered */
|
/* Ensure there isn't any other master already registered */
|
||||||
master_conn = getMasterConnection(conn, myLocalId, myClusterName, &id,
|
master_conn = getMasterConnection(conn, config.node, config.cluster_name, &id);
|
||||||
NULL);
|
NULL);
|
||||||
if (master_conn != NULL)
|
if (master_conn != NULL)
|
||||||
{
|
{
|
||||||
@@ -455,7 +446,7 @@ do_master_register(void)
|
|||||||
{
|
{
|
||||||
sqlquery_snprintf(sqlquery, "DELETE FROM repmgr_%s.repl_nodes "
|
sqlquery_snprintf(sqlquery, "DELETE FROM repmgr_%s.repl_nodes "
|
||||||
" WHERE id = %d",
|
" WHERE id = %d",
|
||||||
myClusterName, myLocalId);
|
config.cluster_name, config.node);
|
||||||
|
|
||||||
if (!PQexec(conn, sqlquery))
|
if (!PQexec(conn, sqlquery))
|
||||||
{
|
{
|
||||||
@@ -468,7 +459,7 @@ do_master_register(void)
|
|||||||
|
|
||||||
sqlquery_snprintf(sqlquery, "INSERT INTO repmgr_%s.repl_nodes "
|
sqlquery_snprintf(sqlquery, "INSERT INTO repmgr_%s.repl_nodes "
|
||||||
"VALUES (%d, '%s', '%s')",
|
"VALUES (%d, '%s', '%s')",
|
||||||
myClusterName, myLocalId, myClusterName, conninfo);
|
config.cluster_name, config.node, config.cluster_name, config.conninfo);
|
||||||
|
|
||||||
if (!PQexec(conn, sqlquery))
|
if (!PQexec(conn, sqlquery))
|
||||||
{
|
{
|
||||||
@@ -493,25 +484,10 @@ do_standby_register(void)
|
|||||||
PGresult *res;
|
PGresult *res;
|
||||||
char sqlquery[QUERY_STR_LEN];
|
char sqlquery[QUERY_STR_LEN];
|
||||||
|
|
||||||
char myClusterName[MAXLEN];
|
|
||||||
int myLocalId = -1;
|
|
||||||
char conninfo[MAXLEN];
|
|
||||||
|
|
||||||
char master_version[MAXVERSIONSTR];
|
char master_version[MAXVERSIONSTR];
|
||||||
char standby_version[MAXVERSIONSTR];
|
char standby_version[MAXVERSIONSTR];
|
||||||
|
|
||||||
/*
|
conn = establishDBConnection(config.conninfo, true);
|
||||||
* Read the configuration file: repmgr.conf
|
|
||||||
*/
|
|
||||||
parse_config(config_file, myClusterName, &myLocalId, conninfo);
|
|
||||||
if (myLocalId == -1)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Node information is missing. "
|
|
||||||
"Check the configuration file.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
conn = establishDBConnection(conninfo, true);
|
|
||||||
|
|
||||||
/* should be v9 or better */
|
/* should be v9 or better */
|
||||||
pg_version(conn, standby_version);
|
pg_version(conn, standby_version);
|
||||||
@@ -532,7 +508,7 @@ do_standby_register(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if there is a schema for this cluster */
|
/* Check if there is a schema for this cluster */
|
||||||
sqlquery_snprintf(sqlquery,
|
sqlquery_snprintf(sqlquery, "SELECT 1 FROM pg_namespace WHERE nspname = 'repmgr_%s'", config.cluster_name);
|
||||||
"SELECT 1 FROM pg_namespace WHERE nspname = 'repmgr_%s'",
|
"SELECT 1 FROM pg_namespace WHERE nspname = 'repmgr_%s'",
|
||||||
myClusterName);
|
myClusterName);
|
||||||
res = PQexec(conn, sqlquery);
|
res = PQexec(conn, sqlquery);
|
||||||
@@ -547,7 +523,7 @@ do_standby_register(void)
|
|||||||
|
|
||||||
if (PQntuples(res) == 0) /* schema doesn't exists */
|
if (PQntuples(res) == 0) /* schema doesn't exists */
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Schema repmgr_%s doesn't exists.", myClusterName);
|
fprintf(stderr, "Schema repmgr_%s doesn't exists.", config.cluster_name);
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
return;
|
return;
|
||||||
@@ -555,7 +531,7 @@ do_standby_register(void)
|
|||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
/* check if there is a master in this cluster */
|
/* check if there is a master in this cluster */
|
||||||
master_conn = getMasterConnection(conn, myLocalId, myClusterName,
|
master_conn = getMasterConnection(conn, config.node, config.cluster_name, &master_id);
|
||||||
&master_id, NULL);
|
&master_id, NULL);
|
||||||
if (!master_conn)
|
if (!master_conn)
|
||||||
return;
|
return;
|
||||||
@@ -587,7 +563,7 @@ do_standby_register(void)
|
|||||||
{
|
{
|
||||||
sqlquery_snprintf(sqlquery, "DELETE FROM repmgr_%s.repl_nodes "
|
sqlquery_snprintf(sqlquery, "DELETE FROM repmgr_%s.repl_nodes "
|
||||||
" WHERE id = %d",
|
" WHERE id = %d",
|
||||||
myClusterName, myLocalId);
|
config.cluster_name, config.node);
|
||||||
|
|
||||||
if (!PQexec(master_conn, sqlquery))
|
if (!PQexec(master_conn, sqlquery))
|
||||||
{
|
{
|
||||||
@@ -601,7 +577,7 @@ do_standby_register(void)
|
|||||||
|
|
||||||
sqlquery_snprintf(sqlquery, "INSERT INTO repmgr_%s.repl_nodes "
|
sqlquery_snprintf(sqlquery, "INSERT INTO repmgr_%s.repl_nodes "
|
||||||
"VALUES (%d, '%s', '%s')",
|
"VALUES (%d, '%s', '%s')",
|
||||||
myClusterName, myLocalId, myClusterName, conninfo);
|
config.cluster_name, config.node, config.cluster_name, config.conninfo);
|
||||||
|
|
||||||
if (!PQexec(master_conn, sqlquery))
|
if (!PQexec(master_conn, sqlquery))
|
||||||
{
|
{
|
||||||
@@ -749,7 +725,7 @@ do_standby_clone(void)
|
|||||||
if (!guc_setted(conn, "wal_keep_segments", ">=", wal_keep_segments))
|
if (!guc_setted(conn, "wal_keep_segments", ">=", wal_keep_segments))
|
||||||
{
|
{
|
||||||
PQfinish(conn);
|
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"), progname, wal_keep_segments);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!guc_setted(conn, "archive_mode", "=", "on"))
|
if (!guc_setted(conn, "archive_mode", "=", "on"))
|
||||||
@@ -1048,10 +1024,6 @@ do_standby_promote(void)
|
|||||||
char sqlquery[QUERY_STR_LEN];
|
char sqlquery[QUERY_STR_LEN];
|
||||||
char script[MAXLEN];
|
char script[MAXLEN];
|
||||||
|
|
||||||
char myClusterName[MAXLEN];
|
|
||||||
int myLocalId = -1;
|
|
||||||
char conninfo[MAXLEN];
|
|
||||||
|
|
||||||
PGconn *old_master_conn;
|
PGconn *old_master_conn;
|
||||||
int old_master_id;
|
int old_master_id;
|
||||||
|
|
||||||
@@ -1062,19 +1034,8 @@ do_standby_promote(void)
|
|||||||
|
|
||||||
char standby_version[MAXVERSIONSTR];
|
char standby_version[MAXVERSIONSTR];
|
||||||
|
|
||||||
/*
|
|
||||||
* Read the configuration file: repmgr.conf
|
|
||||||
*/
|
|
||||||
parse_config(config_file, myClusterName, &myLocalId, conninfo);
|
|
||||||
if (myLocalId == -1)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Node information is missing. "
|
|
||||||
"Check the configuration file.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We need to connect to check configuration */
|
/* We need to connect to check configuration */
|
||||||
conn = establishDBConnection(conninfo, true);
|
conn = establishDBConnection(config.conninfo, true);
|
||||||
|
|
||||||
/* we need v9 or better */
|
/* we need v9 or better */
|
||||||
pg_version(conn, standby_version);
|
pg_version(conn, standby_version);
|
||||||
@@ -1095,8 +1056,8 @@ do_standby_promote(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* we also need to check if there isn't any master already */
|
/* we also need to check if there isn't any master already */
|
||||||
old_master_conn = getMasterConnection(conn, myLocalId, myClusterName,
|
old_master_conn = getMasterConnection(conn, config.node, config.cluster_name, &old_master_id);
|
||||||
&old_master_id, NULL);
|
|
||||||
if (old_master_conn != NULL)
|
if (old_master_conn != NULL)
|
||||||
{
|
{
|
||||||
PQfinish(old_master_conn);
|
PQfinish(old_master_conn);
|
||||||
@@ -1141,8 +1102,7 @@ do_standby_promote(void)
|
|||||||
/*
|
/*
|
||||||
* XXX i'm removing this because it gives an annoying message saying
|
* XXX i'm removing this because it gives an annoying message saying
|
||||||
* couldn't connect but is just the server starting up
|
* couldn't connect but is just the server starting up
|
||||||
*
|
* conn = establishDBConnection(config.conninfo, true);
|
||||||
* conn = establishDBConnection(conninfo, true);
|
|
||||||
* if (is_standby(conn))
|
* if (is_standby(conn))
|
||||||
* fprintf(stderr, "\n%s: STANDBY PROMOTE failed, this is still a standby node.\n", progname);
|
* fprintf(stderr, "\n%s: STANDBY PROMOTE failed, this is still a standby node.\n", progname);
|
||||||
* else
|
* else
|
||||||
@@ -1162,11 +1122,7 @@ do_standby_follow(void)
|
|||||||
char sqlquery[QUERY_STR_LEN];
|
char sqlquery[QUERY_STR_LEN];
|
||||||
char script[MAXLEN];
|
char script[MAXLEN];
|
||||||
|
|
||||||
char myClusterName[MAXLEN];
|
|
||||||
int myLocalId = -1;
|
|
||||||
char conninfo[MAXLEN];
|
|
||||||
char master_conninfo[MAXLEN];
|
char master_conninfo[MAXLEN];
|
||||||
|
|
||||||
PGconn *master_conn;
|
PGconn *master_conn;
|
||||||
int master_id;
|
int master_id;
|
||||||
|
|
||||||
@@ -1176,17 +1132,8 @@ do_standby_follow(void)
|
|||||||
char master_version[MAXVERSIONSTR];
|
char master_version[MAXVERSIONSTR];
|
||||||
char standby_version[MAXVERSIONSTR];
|
char standby_version[MAXVERSIONSTR];
|
||||||
|
|
||||||
/* Read the configuration file: repmgr.conf */
|
|
||||||
parse_config(config_file, myClusterName, &myLocalId, conninfo);
|
|
||||||
if (myLocalId == -1)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Node information is missing. "
|
|
||||||
"Check the configuration file.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We need to connect to check configuration */
|
/* We need to connect to check configuration */
|
||||||
conn = establishDBConnection(conninfo, true);
|
conn = establishDBConnection(config.conninfo, true);
|
||||||
|
|
||||||
/* Check we are in a standby node */
|
/* Check we are in a standby node */
|
||||||
if (!is_standby(conn))
|
if (!is_standby(conn))
|
||||||
@@ -1205,8 +1152,8 @@ do_standby_follow(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* we also need to check if there is any master in the cluster */
|
/* we also need to check if there is any master in the cluster */
|
||||||
master_conn = getMasterConnection(conn, myLocalId, myClusterName,
|
master_conn = getMasterConnection(conn, config.node, config.cluster_name, &master_id);
|
||||||
&master_id, master_conninfo);
|
|
||||||
if (master_conn == NULL)
|
if (master_conn == NULL)
|
||||||
{
|
{
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
@@ -1419,8 +1366,11 @@ copy_remote_files(char *host, char *remote_user, char *remote_path,
|
|||||||
char host_string[MAXLEN];
|
char host_string[MAXLEN];
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
maxlen_snprintf(options,
|
if (strnlen(config.rsync_options, QUERY_STR_LEN) == 0)
|
||||||
"--archive --checksum --compress --progress --rsh=ssh");
|
sprintf(options, "--archive --checksum --compress --progress --rsh=ssh");
|
||||||
|
else
|
||||||
|
strncpy(options, config.rsync_options, QUERY_STR_LEN);
|
||||||
|
|
||||||
if (force)
|
if (force)
|
||||||
strcat(options, " --delete");
|
strcat(options, " --delete");
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
cluster=test
|
cluster=test
|
||||||
node=2
|
node=2
|
||||||
conninfo='host=192.168.204.104'
|
conninfo='host=192.168.204.104'
|
||||||
|
rsync_options=--archive --checksum --compress --progress --rsh=ssh
|
||||||
|
|||||||
4
repmgr.h
4
repmgr.h
@@ -26,12 +26,14 @@
|
|||||||
#include "libpq-fe.h"
|
#include "libpq-fe.h"
|
||||||
|
|
||||||
#include "dbutils.h"
|
#include "dbutils.h"
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define PRIMARY_MODE 0
|
#define PRIMARY_MODE 0
|
||||||
#define STANDBY_MODE 1
|
#define STANDBY_MODE 1
|
||||||
|
|
||||||
#define CONFIG_FILE "repmgr.conf"
|
#define CONFIG_FILE "repmgr.conf"
|
||||||
|
#define QUERY_STR_LEN 8192
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
36
repmgrd.c
36
repmgrd.c
@@ -32,11 +32,8 @@
|
|||||||
|
|
||||||
#include "libpq/pqsignal.h"
|
#include "libpq/pqsignal.h"
|
||||||
|
|
||||||
char myClusterName[MAXLEN];
|
|
||||||
|
|
||||||
/* Local info */
|
/* Local info */
|
||||||
int myLocalMode = STANDBY_MODE;
|
int myLocalMode = STANDBY_MODE;
|
||||||
int myLocalId = -1;
|
|
||||||
PGconn *myLocalConn = NULL;
|
PGconn *myLocalConn = NULL;
|
||||||
|
|
||||||
/* Primary info */
|
/* Primary info */
|
||||||
@@ -51,6 +48,8 @@ const char *progname;
|
|||||||
char *config_file = NULL;
|
char *config_file = NULL;
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
|
|
||||||
|
// should initialize with {0} to be ANSI complaint ? but this raises error with gcc -Wall
|
||||||
|
repmgr_config config = {};
|
||||||
|
|
||||||
static void help(const char *progname);
|
static void help(const char *progname);
|
||||||
static void checkClusterConfiguration(void);
|
static void checkClusterConfiguration(void);
|
||||||
@@ -96,7 +95,6 @@ main(int argc, char **argv)
|
|||||||
int optindex;
|
int optindex;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
char conninfo[MAXLEN];
|
|
||||||
char standby_version[MAXVERSIONSTR];
|
char standby_version[MAXVERSIONSTR];
|
||||||
|
|
||||||
progname = get_progname(argv[0]);
|
progname = get_progname(argv[0]);
|
||||||
@@ -146,15 +144,15 @@ main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Read the configuration file: repmgr.conf
|
* Read the configuration file: repmgr.conf
|
||||||
*/
|
*/
|
||||||
parse_config(config_file, myClusterName, &myLocalId, conninfo);
|
parse_config(config_file, &config);
|
||||||
if (myLocalId == -1)
|
if (config.node == -1)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Node information is missing. "
|
fprintf(stderr, "Node information is missing. "
|
||||||
"Check the configuration file.\n");
|
"Check the configuration file.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
myLocalConn = establishDBConnection(conninfo, true);
|
myLocalConn = establishDBConnection(config.conninfo, true);
|
||||||
|
|
||||||
/* should be v9 or better */
|
/* should be v9 or better */
|
||||||
pg_version(myLocalConn, standby_version);
|
pg_version(myLocalConn, standby_version);
|
||||||
@@ -173,21 +171,21 @@ main(int argc, char **argv)
|
|||||||
myLocalMode = is_standby(myLocalConn) ? STANDBY_MODE : PRIMARY_MODE;
|
myLocalMode = is_standby(myLocalConn) ? STANDBY_MODE : PRIMARY_MODE;
|
||||||
if (myLocalMode == PRIMARY_MODE)
|
if (myLocalMode == PRIMARY_MODE)
|
||||||
{
|
{
|
||||||
primaryId = myLocalId;
|
primaryId = config.node;
|
||||||
strcpy(primaryConninfo, conninfo);
|
strcpy(primaryConninfo, config.conninfo);
|
||||||
primaryConn = myLocalConn;
|
primaryConn = myLocalConn;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* I need the id of the primary as well as a connection to it */
|
/* I need the id of the primary as well as a connection to it */
|
||||||
primaryConn = getMasterConnection(myLocalConn, myLocalId,
|
primaryConn = getMasterConnection(myLocalConn, config.node, config.cluster_name, &primaryId);
|
||||||
myClusterName, &primaryId, NULL);
|
|
||||||
if (primaryConn == NULL)
|
if (primaryConn == NULL)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkClusterConfiguration();
|
checkClusterConfiguration();
|
||||||
checkNodeConfiguration(conninfo);
|
checkNodeConfiguration(config.conninfo);
|
||||||
if (myLocalMode == STANDBY_MODE)
|
if (myLocalMode == STANDBY_MODE)
|
||||||
{
|
{
|
||||||
MonitorCheck();
|
MonitorCheck();
|
||||||
@@ -251,8 +249,8 @@ MonitorExecute(void)
|
|||||||
for (connection_retries = 0; connection_retries < 6;
|
for (connection_retries = 0; connection_retries < 6;
|
||||||
connection_retries++)
|
connection_retries++)
|
||||||
{
|
{
|
||||||
primaryConn = getMasterConnection(myLocalConn, myLocalId,
|
primaryConn = getMasterConnection(myLocalConn, config.node, config.cluster_name, &primaryId);
|
||||||
myClusterName, &primaryId, NULL);
|
|
||||||
if (PQstatus(primaryConn) == CONNECTION_OK)
|
if (PQstatus(primaryConn) == CONNECTION_OK)
|
||||||
{
|
{
|
||||||
/* Connected, we can continue the process so break the loop */
|
/* Connected, we can continue the process so break the loop */
|
||||||
@@ -336,8 +334,8 @@ MonitorExecute(void)
|
|||||||
"INSERT INTO repmgr_%s.repl_monitor "
|
"INSERT INTO repmgr_%s.repl_monitor "
|
||||||
"VALUES(%d, %d, '%s'::timestamp with time zone, "
|
"VALUES(%d, %d, '%s'::timestamp with time zone, "
|
||||||
" '%s', '%s', "
|
" '%s', '%s', "
|
||||||
" %lld, %lld)", myClusterName,
|
" %lld, %lld)", config.cluster_name,
|
||||||
primaryId, myLocalId, monitor_standby_timestamp,
|
primaryId, config.node, monitor_standby_timestamp,
|
||||||
last_wal_primary_location,
|
last_wal_primary_location,
|
||||||
last_wal_standby_received,
|
last_wal_standby_received,
|
||||||
(lsn_primary - lsn_standby_received),
|
(lsn_primary - lsn_standby_received),
|
||||||
@@ -360,7 +358,7 @@ checkClusterConfiguration(void)
|
|||||||
|
|
||||||
sqlquery_snprintf(sqlquery, "SELECT oid FROM pg_class "
|
sqlquery_snprintf(sqlquery, "SELECT oid FROM pg_class "
|
||||||
" WHERE oid = 'repmgr_%s.repl_nodes'::regclass",
|
" WHERE oid = 'repmgr_%s.repl_nodes'::regclass",
|
||||||
myClusterName);
|
config.cluster_name);
|
||||||
res = PQexec(myLocalConn, sqlquery);
|
res = PQexec(myLocalConn, sqlquery);
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
{
|
{
|
||||||
@@ -398,7 +396,7 @@ checkNodeConfiguration(char *conninfo)
|
|||||||
/* Check if we have my node information in repl_nodes */
|
/* Check if we have my node information in repl_nodes */
|
||||||
sqlquery_snprintf(sqlquery, "SELECT * FROM repmgr_%s.repl_nodes "
|
sqlquery_snprintf(sqlquery, "SELECT * FROM repmgr_%s.repl_nodes "
|
||||||
" WHERE id = %d AND cluster = '%s' ",
|
" WHERE id = %d AND cluster = '%s' ",
|
||||||
myClusterName, myLocalId, myClusterName);
|
config.cluster_name, config.node, config.cluster_name);
|
||||||
|
|
||||||
res = PQexec(myLocalConn, sqlquery);
|
res = PQexec(myLocalConn, sqlquery);
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
@@ -421,7 +419,7 @@ checkNodeConfiguration(char *conninfo)
|
|||||||
/* Adding the node */
|
/* Adding the node */
|
||||||
sqlquery_snprintf(sqlquery, "INSERT INTO repmgr_%s.repl_nodes "
|
sqlquery_snprintf(sqlquery, "INSERT INTO repmgr_%s.repl_nodes "
|
||||||
"VALUES (%d, '%s', '%s')",
|
"VALUES (%d, '%s', '%s')",
|
||||||
myClusterName, myLocalId, myClusterName, conninfo);
|
config.cluster_name, config.node, config.cluster_name, conninfo);
|
||||||
|
|
||||||
if (!PQexec(primaryConn, sqlquery))
|
if (!PQexec(primaryConn, sqlquery))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user