Skip to content

Commit

Permalink
Add monitor parameters to enable multiple stanbys (#89)
Browse files Browse the repository at this point in the history
This work introduces multi-standby configuration variables

formation.number_sync_standbys : integer, number of nodes in write quorum
node.candidate_priority : integer(1-100), priority of the candidate to be promoted, 0 if the node is never meant to be primary
node.replication_quorum : boolean, true if the node joins in write quorum
register_node and create_formation methods have those parameters to set them during creation time. I have also added set_formation_number_sync_standbys, set_node_candidate_priority,, and set_node_replication_quorum` UDFs with their corresponding get functions

node_active now also return candidate_priority and replication_quorum parameters.
  • Loading branch information
mtuncer committed Nov 15, 2019
1 parent 90485e1 commit e0d4e82
Show file tree
Hide file tree
Showing 35 changed files with 2,440 additions and 170 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,5 @@ lib*.pc

# Exclude generated SQL files
pgautofailover--?.?.sql
!pgautofailover--1.0.sql

37 changes: 37 additions & 0 deletions src/bin/pg_autoctl/cli_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "log.h"
#include "monitor.h"
#include "monitor_config.h"
#include "parsing.h"
#include "pgsetup.h"
#include "pgsql.h"
#include "state.h"
Expand Down Expand Up @@ -54,6 +55,8 @@ bool allowRemovingPgdata = false;
* { "verbose", no_argument, NULL, 'v' },
* { "quiet", no_argument, NULL, 'q' },
* { "help", no_argument, NULL, 'h' },
* { "candidate-priority", required_argument, NULL, 'P'},
* { "replication-quorum", required_argument, NULL, 'r'},
* { NULL, 0, NULL, 0 }
* };
*
Expand All @@ -75,6 +78,9 @@ cli_create_node_getopts(int argc, char **argv,
LocalOptionConfig.prepare_promotion_walreceiver = -1;
LocalOptionConfig.postgresql_restart_failure_timeout = -1;
LocalOptionConfig.postgresql_restart_failure_max_retries = -1;
LocalOptionConfig.pgSetup.settings.candidatePriority = FAILOVER_NODE_CANDIDATE_PRIORITY;
LocalOptionConfig.pgSetup.settings.replicationQuorum = FAILOVER_NODE_REPLICATION_QUORUM;


optind = 0;

Expand Down Expand Up @@ -223,6 +229,37 @@ cli_create_node_getopts(int argc, char **argv,
log_trace("--allow-removing-pgdata");
break;
}
case 'P':
{
/* { "candidate-priority", required_argument, NULL, 'P'} */
int candidatePriority = strtol(optarg, NULL, 10);
if (errno == EINVAL || candidatePriority < 0 || candidatePriority > 100)
{
log_fatal("--candidate-priority argument is not valid."
" Valid values are integers from 0 to 100. ");
exit(EXIT_CODE_BAD_ARGS);
}

LocalOptionConfig.pgSetup.settings.candidatePriority = candidatePriority;
log_trace("--candidate-priority %d", candidatePriority);
break;
}
case 'r':
{
/* { "replication-quorum", required_argument, NULL, 'r'} */
bool replicationQuorum = false;

if (!parse_bool(optarg, &replicationQuorum))
{
log_fatal("--replication-quorum argument is not valid."
" Valid values are \"true\" or \"false\".");
exit(EXIT_CODE_BAD_ARGS);
}

LocalOptionConfig.pgSetup.settings.replicationQuorum = replicationQuorum;
log_trace("--replication-quorum %s", boolToString(replicationQuorum));
break;
}

case 'V':
{
Expand Down
4 changes: 4 additions & 0 deletions src/bin/pg_autoctl/cli_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ extern CommandLine create_monitor_command;
extern CommandLine create_postgres_command;
extern CommandLine drop_node_command;

/* cli_get_set_properties.c */
extern CommandLine get_command;
extern CommandLine set_command;

/* cli_enable_disable.c */
extern CommandLine enable_commands;
extern CommandLine disable_commands;
Expand Down
28 changes: 16 additions & 12 deletions src/bin/pg_autoctl/cli_create_drop_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,19 @@ CommandLine create_postgres_command =
make_command("postgres",
"Initialize a pg_auto_failover standalone postgres node",
"",
" --pgctl path to pg_ctl\n"
" --pgdata path to data director\n"
" --pghost PostgreSQL's hostname\n"
" --pgport PostgreSQL's port number\n"
" --listen PostgreSQL's listen_addresses\n"
" --username PostgreSQL's username\n"
" --dbname PostgreSQL's database name\n"
" --nodename pg_auto_failover node\n"
" --formation pg_auto_failover formation\n"
" --monitor pg_auto_failover Monitor Postgres URL\n"
" --auth authentication method for connections from monitor\n"
" --pgctl path to pg_ctl\n"
" --pgdata path to data director\n"
" --pghost PostgreSQL's hostname\n"
" --pgport PostgreSQL's port number\n"
" --listen PostgreSQL's listen_addresses\n"
" --username PostgreSQL's username\n"
" --dbname PostgreSQL's database name\n"
" --nodename pg_auto_failover node\n"
" --formation pg_auto_failover formation\n"
" --monitor pg_auto_failover Monitor Postgres URL\n"
" --auth authentication method for connections from monitor\n"
" --candidate-priority priority of the node to be promoted to become primary\n"
" --replication-quorum true if node participates in write quorum\n"
KEEPER_CLI_ALLOW_RM_PGDATA_OPTION,
cli_create_postgres_getopts,
cli_create_postgres);
Expand Down Expand Up @@ -207,12 +209,14 @@ cli_create_postgres_getopts(int argc, char **argv)
{ "verbose", no_argument, NULL, 'v' },
{ "quiet", no_argument, NULL, 'q' },
{ "help", no_argument, NULL, 'h' },
{ "candidate-priority", required_argument, NULL, 'P'},
{ "replication-quorum", required_argument, NULL, 'r'},
{ NULL, 0, NULL, 0 }
};

int optind =
cli_create_node_getopts(argc, argv,
long_options, "C:D:H:p:l:U:A:d:n:f:m:RVvqh",
long_options, "C:D:H:p:l:U:A:d:n:f:m:RVvqhP:r:",
&options);

/* publish our option parsing in the global variable */
Expand Down
5 changes: 3 additions & 2 deletions src/bin/pg_autoctl/cli_do_root.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ keeper_cli_keeper_setup_getopts(int argc, char **argv)
{ "verbose", no_argument, NULL, 'v' },
{ "quiet", no_argument, NULL, 'q' },
{ "help", no_argument, NULL, 'h' },
{ "candidate-priority", required_argument, NULL, 'P'},
{ "replication-quorum", required_argument, NULL, 'r'},
{ NULL, 0, NULL, 0 }
};

Expand All @@ -263,8 +265,7 @@ keeper_cli_keeper_setup_getopts(int argc, char **argv)
unsetenv("POSIXLY_CORRECT");

optind = cli_create_node_getopts(argc, argv,
long_options,
"C:D:H:p:l:y:U:A:d:n:f:g:m:RVvqh",
long_options, "C:D:H:p:l:y:U:A:d:n:f:g:m:RVvqhP:r:",
&options);

/* publish our option parsing in the global variable */
Expand Down
37 changes: 28 additions & 9 deletions src/bin/pg_autoctl/cli_formation.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ CommandLine create_formation_command =
"Create a new formation on the pg_auto_failover monitor",
" [ --pgdata --formation --kind --dbname --with-secondary " \
"--without-secondary ] ",
" --pgdata path to data directory \n" \
" --formation name of the formation to create \n" \
" --kind formation kind, either \"pgsql\" or \"citus\" \n" \
" --dbname name for postgres database to use in this formation \n" \
" --enable-secondary create a formation that has multiple nodes that can be \n" \
" used for fail over when others have issues \n" \
" --disable-secondary create a citus formation without nodes to fail over to \n",
" --pgdata path to data directory \n" \
" --formation name of the formation to create \n" \
" --kind formation kind, either \"pgsql\" or \"citus\" \n" \
" --dbname name for postgres database to use in this formation \n" \
" --enable-secondary create a formation that has multiple nodes that can be \n" \
" used for fail over when others have issues \n" \
" --disable-secondary create a citus formation without nodes to fail over to \n" \
" --number-sync-standbys minimum number of standbys to confirm write \n",
keeper_cli_formation_create_getopts,
keeper_cli_formation_create);

Expand Down Expand Up @@ -199,6 +200,7 @@ keeper_cli_formation_create_getopts(int argc, char **argv)
{ "verbose", no_argument, NULL, 'v' },
{ "quiet", no_argument, NULL, 'q' },
{ "help", no_argument, NULL, 'h' },
{ "number-sync-stanbys", required_argument, NULL, 'n' },
{ NULL, 0, NULL, 0 }
};

Expand All @@ -207,7 +209,7 @@ keeper_cli_formation_create_getopts(int argc, char **argv)
/* set defaults for formations */
options.formationHasSecondary = true;

while ((c = getopt_long(argc, argv, "D:f:k:sSVvqh",
while ((c = getopt_long(argc, argv, "D:f:k:sSVvqhn:",
long_options, &option_index)) != -1)
{
switch (c)
Expand Down Expand Up @@ -294,6 +296,22 @@ keeper_cli_formation_create_getopts(int argc, char **argv)
break;
}

case 'n':
{
/* { "number-sync-stanbys", required_argument, NULL, 'n'} */
int numberSyncStanbys = strtol(optarg, NULL, 10);

if (errno == EINVAL|| numberSyncStanbys < 0)
{
log_fatal("--number-sync-stanbys argument is not valid."
" Use a non-negative integer value.");
exit(EXIT_CODE_BAD_ARGS);
}
options.numberSyncStandbys = numberSyncStanbys;
log_trace("--number-sync-stanbys %d", numberSyncStanbys);
break;
}

default:
{
/* getopt_long already wrote an error message */
Expand Down Expand Up @@ -365,7 +383,8 @@ keeper_cli_formation_create(int argc, char **argv)
config.formation,
config.formationKind,
config.dbname,
config.formationHasSecondary))
config.formationHasSecondary,
config.numberSyncStandbys))
{
/* errors have already been logged */
exit(EXIT_CODE_MONITOR);
Expand Down

0 comments on commit e0d4e82

Please sign in to comment.