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:
Dan Farina
2011-02-04 18:35:56 -08:00
8 changed files with 138 additions and 127 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@
*.o
repmgr
repmgrd
README.html

View File

@@ -126,6 +126,35 @@ path either. The following recipe should work::
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -136,8 +165,7 @@ is available by checking its version::
repmgr --version
repmgrd --version
You may need to include
the full path of the binary instead, such as this RHEL example::
You may need to include the full path of the binary instead, such as this RHEL example::
/usr/pgsql-9.0/bin/repmgr --version
/usr/pgsql-9.0/bin/repmgrd --version

View File

@@ -23,7 +23,7 @@
void
parse_config(const char *config_file, char *cluster_name, int *node,
parse_config(const char *config_file, repmgr_config *config)
char *conninfo)
{
char *s, buff[MAXLINELENGTH];
@@ -32,9 +32,17 @@ parse_config(const char *config_file, char *cluster_name, int *node,
FILE *fp = fopen (config_file, "r");
if (fp == NULL)
return;
if (fp == NULL) {
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 */
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 */
if (strcmp(name, "cluster") == 0)
strncpy (cluster_name, value, MAXLEN);
strncpy (config->cluster_name, value, MAXLEN);
else if (strcmp(name, "node") == 0)
*node = atoi(value);
config->node = atoi(value);
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
printf ("WARNING: %s/%s: Unknown name/value pair!\n", name, value);
}
/* Close file */
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 *

View File

@@ -17,7 +17,14 @@
*
*/
void parse_config(const char *config_file, char *cluster_name, int *node,
char *service);
typedef struct
{
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);
char *trim(char *s);

140
repmgr.c
View File

@@ -44,7 +44,6 @@
#define STANDBY_PROMOTE 4
#define STANDBY_FOLLOW 5
static void help(const char *progname);
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,
@@ -78,6 +77,7 @@ char *masterport = NULL;
char *server_mode = NULL;
char *server_cmd = NULL;
repmgr_config config = {};
int
main(int argc, char **argv)
@@ -262,6 +262,17 @@ main(int argc, char **argv)
else
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";
values[2] = username;
@@ -306,25 +317,10 @@ do_master_register(void)
PGresult *res;
char sqlquery[QUERY_STR_LEN];
char myClusterName[MAXLEN];
int myLocalId = -1;
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)
{
fprintf(stderr, "Node information is missing. "
"Check the configuration file.\n");
exit(1);
}
conn = establishDBConnection(conninfo, true);
conn = establishDBConnection(config.conninfo, true);
/* master should be v9 or better */
pg_version(conn, master_version);
@@ -345,9 +341,7 @@ do_master_register(void)
}
/* Check if there is a schema for this cluster */
sqlquery_snprintf(sqlquery,
"SELECT 1 FROM pg_namespace WHERE nspname = 'repmgr_%s'",
myClusterName);
sqlquery_sprintf(sqlquery, "SELECT 1 FROM pg_namespace WHERE nspname = 'repmgr_%s'", config.cluster_name);
res = PQexec(conn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
@@ -362,7 +356,7 @@ do_master_register(void)
{
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);
PQfinish(conn);
return;
@@ -374,11 +368,11 @@ do_master_register(void)
if (!schema_exists)
{
/* 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))
{
fprintf(stderr, "Cannot create the schema repmgr_%s: %s\n",
myClusterName, PQerrorMessage(conn));
config.cluster_name, PQerrorMessage(conn));
PQfinish(conn);
return;
}
@@ -387,12 +381,11 @@ do_master_register(void)
sqlquery_snprintf(sqlquery, "CREATE TABLE repmgr_%s.repl_nodes ( "
" id integer primary key, "
" cluster text not null, "
" conninfo text not null)", myClusterName);
" conninfo text not null)", config.cluster_name);
if (!PQexec(conn, sqlquery))
{
fprintf(stderr,
"Cannot create the table repmgr_%s.repl_nodes: %s\n",
myClusterName, PQerrorMessage(conn));
config.cluster_name, PQerrorMessage(conn));
PQfinish(conn);
return;
}
@@ -404,13 +397,12 @@ do_master_register(void)
" last_wal_primary_location TEXT NOT NULL, "
" last_wal_standby_location TEXT NOT NULL, "
" replication_lag BIGINT NOT NULL, "
" apply_lag BIGINT NOT NULL) ",
" apply_lag BIGINT NOT NULL) ", config.cluster_name);
myClusterName);
if (!PQexec(conn, sqlquery))
{
fprintf(stderr,
"Cannot create the table repmgr_%s.repl_monitor: %s\n",
myClusterName, PQerrorMessage(conn));
config.cluster_name, PQerrorMessage(conn));
PQfinish(conn);
return;
}
@@ -424,12 +416,11 @@ do_master_register(void)
" 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);
" WHERE row_number = 1", config.cluster_name, config.cluster_name);
if (!PQexec(conn, sqlquery))
{
fprintf(stderr,
"Cannot create the view repmgr_%s.repl_status: %s\n",
myClusterName, PQerrorMessage(conn));
config.cluster_name, PQerrorMessage(conn));
PQfinish(conn);
return;
}
@@ -440,7 +431,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, config.node, config.cluster_name, &id);
NULL);
if (master_conn != NULL)
{
@@ -455,7 +446,7 @@ do_master_register(void)
{
sqlquery_snprintf(sqlquery, "DELETE FROM repmgr_%s.repl_nodes "
" WHERE id = %d",
myClusterName, myLocalId);
config.cluster_name, config.node);
if (!PQexec(conn, sqlquery))
{
@@ -468,7 +459,7 @@ do_master_register(void)
sqlquery_snprintf(sqlquery, "INSERT INTO repmgr_%s.repl_nodes "
"VALUES (%d, '%s', '%s')",
myClusterName, myLocalId, myClusterName, conninfo);
config.cluster_name, config.node, config.cluster_name, config.conninfo);
if (!PQexec(conn, sqlquery))
{
@@ -493,25 +484,10 @@ do_standby_register(void)
PGresult *res;
char sqlquery[QUERY_STR_LEN];
char myClusterName[MAXLEN];
int myLocalId = -1;
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)
{
fprintf(stderr, "Node information is missing. "
"Check the configuration file.\n");
exit(1);
}
conn = establishDBConnection(conninfo, true);
conn = establishDBConnection(config.conninfo, true);
/* should be v9 or better */
pg_version(conn, standby_version);
@@ -532,7 +508,7 @@ do_standby_register(void)
}
/* 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'",
myClusterName);
res = PQexec(conn, sqlquery);
@@ -547,7 +523,7 @@ do_standby_register(void)
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);
PQfinish(conn);
return;
@@ -555,7 +531,7 @@ do_standby_register(void)
PQclear(res);
/* 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);
if (!master_conn)
return;
@@ -587,7 +563,7 @@ do_standby_register(void)
{
sqlquery_snprintf(sqlquery, "DELETE FROM repmgr_%s.repl_nodes "
" WHERE id = %d",
myClusterName, myLocalId);
config.cluster_name, config.node);
if (!PQexec(master_conn, sqlquery))
{
@@ -601,7 +577,7 @@ do_standby_register(void)
sqlquery_snprintf(sqlquery, "INSERT INTO repmgr_%s.repl_nodes "
"VALUES (%d, '%s', '%s')",
myClusterName, myLocalId, myClusterName, conninfo);
config.cluster_name, config.node, config.cluster_name, config.conninfo);
if (!PQexec(master_conn, sqlquery))
{
@@ -749,7 +725,7 @@ do_standby_clone(void)
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"), progname, wal_keep_segments);
return;
}
if (!guc_setted(conn, "archive_mode", "=", "on"))
@@ -1048,10 +1024,6 @@ do_standby_promote(void)
char sqlquery[QUERY_STR_LEN];
char script[MAXLEN];
char myClusterName[MAXLEN];
int myLocalId = -1;
char conninfo[MAXLEN];
PGconn *old_master_conn;
int old_master_id;
@@ -1062,19 +1034,8 @@ do_standby_promote(void)
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 */
conn = establishDBConnection(conninfo, true);
conn = establishDBConnection(config.conninfo, true);
/* we need v9 or better */
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 */
old_master_conn = getMasterConnection(conn, myLocalId, myClusterName,
&old_master_id, NULL);
old_master_conn = getMasterConnection(conn, config.node, config.cluster_name, &old_master_id);
if (old_master_conn != NULL)
{
PQfinish(old_master_conn);
@@ -1141,8 +1102,7 @@ do_standby_promote(void)
/*
* 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);
* conn = establishDBConnection(config.conninfo, true);
* if (is_standby(conn))
* fprintf(stderr, "\n%s: STANDBY PROMOTE failed, this is still a standby node.\n", progname);
* else
@@ -1162,11 +1122,7 @@ do_standby_follow(void)
char sqlquery[QUERY_STR_LEN];
char script[MAXLEN];
char myClusterName[MAXLEN];
int myLocalId = -1;
char conninfo[MAXLEN];
char master_conninfo[MAXLEN];
PGconn *master_conn;
int master_id;
@@ -1176,17 +1132,8 @@ do_standby_follow(void)
char master_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 */
conn = establishDBConnection(conninfo, true);
conn = establishDBConnection(config.conninfo, true);
/* Check we are in a standby node */
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 */
master_conn = getMasterConnection(conn, myLocalId, myClusterName,
&master_id, master_conninfo);
master_conn = getMasterConnection(conn, config.node, config.cluster_name, &master_id);
if (master_conn == NULL)
{
PQfinish(conn);
@@ -1419,8 +1366,11 @@ copy_remote_files(char *host, char *remote_user, char *remote_path,
char host_string[MAXLEN];
int r;
maxlen_snprintf(options,
"--archive --checksum --compress --progress --rsh=ssh");
if (strnlen(config.rsync_options, QUERY_STR_LEN) == 0)
sprintf(options, "--archive --checksum --compress --progress --rsh=ssh");
else
strncpy(options, config.rsync_options, QUERY_STR_LEN);
if (force)
strcat(options, " --delete");

View File

@@ -1,3 +1,4 @@
cluster=test
node=2
conninfo='host=192.168.204.104'
rsync_options=--archive --checksum --compress --progress --rsh=ssh

View File

@@ -26,12 +26,14 @@
#include "libpq-fe.h"
#include "dbutils.h"
#include "config.h"
#define PRIMARY_MODE 0
#define STANDBY_MODE 1
#define CONFIG_FILE "repmgr.conf"
#define QUERY_STR_LEN 8192
#include "config.h"
#endif

View File

@@ -32,11 +32,8 @@
#include "libpq/pqsignal.h"
char myClusterName[MAXLEN];
/* Local info */
int myLocalMode = STANDBY_MODE;
int myLocalId = -1;
PGconn *myLocalConn = NULL;
/* Primary info */
@@ -51,6 +48,8 @@ const char *progname;
char *config_file = NULL;
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 checkClusterConfiguration(void);
@@ -96,7 +95,6 @@ main(int argc, char **argv)
int optindex;
int c;
char conninfo[MAXLEN];
char standby_version[MAXVERSIONSTR];
progname = get_progname(argv[0]);
@@ -146,15 +144,15 @@ main(int argc, char **argv)
/*
* Read the configuration file: repmgr.conf
*/
parse_config(config_file, myClusterName, &myLocalId, conninfo);
if (myLocalId == -1)
parse_config(config_file, &config);
if (config.node == -1)
{
fprintf(stderr, "Node information is missing. "
"Check the configuration file.\n");
exit(1);
}
myLocalConn = establishDBConnection(conninfo, true);
myLocalConn = establishDBConnection(config.conninfo, true);
/* should be v9 or better */
pg_version(myLocalConn, standby_version);
@@ -173,21 +171,21 @@ main(int argc, char **argv)
myLocalMode = is_standby(myLocalConn) ? STANDBY_MODE : PRIMARY_MODE;
if (myLocalMode == PRIMARY_MODE)
{
primaryId = myLocalId;
strcpy(primaryConninfo, conninfo);
primaryId = config.node;
strcpy(primaryConninfo, config.conninfo);
primaryConn = myLocalConn;
}
else
{
/* I need the id of the primary as well as a connection to it */
primaryConn = getMasterConnection(myLocalConn, myLocalId,
myClusterName, &primaryId, NULL);
primaryConn = getMasterConnection(myLocalConn, config.node, config.cluster_name, &primaryId);
if (primaryConn == NULL)
exit(1);
}
checkClusterConfiguration();
checkNodeConfiguration(conninfo);
checkNodeConfiguration(config.conninfo);
if (myLocalMode == STANDBY_MODE)
{
MonitorCheck();
@@ -251,8 +249,8 @@ MonitorExecute(void)
for (connection_retries = 0; connection_retries < 6;
connection_retries++)
{
primaryConn = getMasterConnection(myLocalConn, myLocalId,
myClusterName, &primaryId, NULL);
primaryConn = getMasterConnection(myLocalConn, config.node, config.cluster_name, &primaryId);
if (PQstatus(primaryConn) == CONNECTION_OK)
{
/* Connected, we can continue the process so break the loop */
@@ -336,8 +334,8 @@ MonitorExecute(void)
"INSERT INTO repmgr_%s.repl_monitor "
"VALUES(%d, %d, '%s'::timestamp with time zone, "
" '%s', '%s', "
" %lld, %lld)", myClusterName,
primaryId, myLocalId, monitor_standby_timestamp,
" %lld, %lld)", config.cluster_name,
primaryId, config.node, monitor_standby_timestamp,
last_wal_primary_location,
last_wal_standby_received,
(lsn_primary - lsn_standby_received),
@@ -360,7 +358,7 @@ checkClusterConfiguration(void)
sqlquery_snprintf(sqlquery, "SELECT oid FROM pg_class "
" WHERE oid = 'repmgr_%s.repl_nodes'::regclass",
myClusterName);
config.cluster_name);
res = PQexec(myLocalConn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
@@ -398,7 +396,7 @@ checkNodeConfiguration(char *conninfo)
/* Check if we have my node information in repl_nodes */
sqlquery_snprintf(sqlquery, "SELECT * FROM repmgr_%s.repl_nodes "
" WHERE id = %d AND cluster = '%s' ",
myClusterName, myLocalId, myClusterName);
config.cluster_name, config.node, config.cluster_name);
res = PQexec(myLocalConn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
@@ -421,7 +419,7 @@ checkNodeConfiguration(char *conninfo)
/* Adding the node */
sqlquery_snprintf(sqlquery, "INSERT INTO repmgr_%s.repl_nodes "
"VALUES (%d, '%s', '%s')",
myClusterName, myLocalId, myClusterName, conninfo);
config.cluster_name, config.node, config.cluster_name, conninfo);
if (!PQexec(primaryConn, sqlquery))
{