Split "action" functions to individual files

repmgr3's repmgr.c file was not far off 10,000 lines - this will make
it easier to manage individual parts of the code.
This commit is contained in:
Ian Barwick
2017-04-26 22:58:21 +09:00
parent 230eab28a9
commit bcf55b4f72
9 changed files with 426 additions and 345 deletions

View File

@@ -19,25 +19,28 @@
#include "repmgr.h"
#include "repmgr-client.h"
#include "repmgr-client-global.h"
#include "repmgr-action-cluster.h"
#include "repmgr-action-master.h"
/* global configuration structures */
t_runtime_options runtime_options = T_RUNTIME_OPTIONS_INITIALIZER;
t_configuration_options config_file_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
bool config_file_required = true;
char pg_bindir[MAXLEN] = "";
char repmgr_slot_name[MAXLEN] = "";
char *repmgr_slot_name_ptr = NULL;
t_node_info target_node_info = T_NODE_INFO_INITIALIZER;
/* Collate command line errors and warnings here for friendlier reporting */
ItemList cli_errors = { NULL, NULL };
ItemList cli_warnings = { NULL, NULL };
static bool config_file_required = true;
static char pg_bindir[MAXLEN] = "";
static char repmgr_slot_name[MAXLEN] = "";
static char *repmgr_slot_name_ptr = NULL;
static t_node_info target_node_info = T_NODE_INFO_INITIALIZER;
int
main(int argc, char **argv)
{
@@ -743,188 +746,6 @@ do_help(void)
}
static void
do_master_register(void)
{
PGconn *conn = NULL;
PGconn *master_conn = NULL;
int current_master_id = UNKNOWN_NODE_ID;
int ret;
t_node_info node_info = T_NODE_INFO_INITIALIZER;
int record_found;
bool record_created;
PQExpBufferData event_description;
log_info(_("connecting to master database..."));
conn = establish_db_connection(config_file_options.conninfo, true);
log_verbose(LOG_INFO, _("connected to server, checking its state"));
/* verify that node is running a supported server version */
check_server_version(conn, "master", true, NULL);
/* check that node is actually a master */
ret = is_standby(conn);
if (ret)
{
log_error(_(ret == 1 ? "server is in standby mode and cannot be registered as a master" :
"connection to node lost!"));
PQfinish(conn);
exit(ERR_BAD_CONFIG);
}
log_verbose(LOG_INFO, _("server is not in recovery"));
/* create the repmgr extension if it doesn't already exist */
if (!create_repmgr_extension(conn))
{
PQfinish(conn);
exit(ERR_BAD_CONFIG);
}
/* Ensure there isn't another active master already registered */
master_conn = get_master_connection(conn, &current_master_id, NULL);
if (master_conn != NULL)
{
if (current_master_id != config_file_options.node_id)
{
/* it's impossible to add a second master to a streaming replication cluster */
log_error(_("there is already an active registered master (node ID: %i) in this cluster"), current_master_id);
PQfinish(master_conn);
PQfinish(conn);
exit(ERR_BAD_CONFIG);
}
/* we've probably connected to ourselves */
PQfinish(master_conn);
}
begin_transaction(conn);
/*
* Check if a node with a different ID is registered as master. This shouldn't
* happen but could do if an existing master was shut down without being
* unregistered.
*/
current_master_id = get_master_node_id(conn);
if (current_master_id != NODE_NOT_FOUND && current_master_id != config_file_options.node_id)
{
log_error(_("another node with id %i is already registered as master"), current_master_id);
// attempt to connect, add info/hint depending if active...
log_info(_("a streaming replication cluster can have only one master node"));
rollback_transaction(conn);
PQfinish(conn);
exit(ERR_BAD_CONFIG);
}
/*
* Check whether there's an existing record for this node, and
* update it if --force set
*/
record_found = get_node_record(conn, config_file_options.node_id, &node_info);
if (record_found)
{
if (!runtime_options.force)
{
log_error(_("this node is already registered"));
log_hint(_("use -F/--force to overwrite the existing node record"));
rollback_transaction(conn);
PQfinish(conn);
exit(ERR_BAD_CONFIG);
}
}
else
{
node_info.node_id = config_file_options.node_id;
}
/* if upstream_node_id set, warn that it will be ignored */
if (config_file_options.upstream_node_id != NO_UPSTREAM_NODE)
{
log_warning(_("master node %i is configured with \"upstream_node_id\" set to %i"),
node_info.node_id,
config_file_options.upstream_node_id);
log_detail(_("the value set for \"upstream_node_id\" will be ignored"));
}
/* set type to "master", active to "true" and unset upstream_node_id*/
node_info.type = MASTER;
node_info.upstream_node_id = NO_UPSTREAM_NODE;
node_info.active = true;
/* update node record structure with settings from config file */
strncpy(node_info.node_name, config_file_options.node_name, MAXLEN);
strncpy(node_info.conninfo, config_file_options.conninfo, MAXLEN);
strncpy(node_info.slot_name, repmgr_slot_name_ptr, MAXLEN);
node_info.priority = config_file_options.priority;
initPQExpBuffer(&event_description);
if (record_found)
{
record_created = update_node_record(conn,
"master register",
&node_info);
if (record_created == true)
{
appendPQExpBuffer(&event_description,
"existing master record updated");
}
else
{
appendPQExpBuffer(&event_description,
"error encountered while updating master record:\n%s",
PQerrorMessage(conn));
}
}
else
{
record_created = create_node_record(conn,
"master register",
&node_info);
if (record_created == false)
{
appendPQExpBuffer(&event_description,
"error encountered while creating master record:\n%s",
PQerrorMessage(conn));
}
}
/* Log the event */
create_event_record(conn,
&config_file_options,
config_file_options.node_id,
"master_register",
record_created,
event_description.data);
if (record_created == false)
{
rollback_transaction(conn);
PQfinish(conn);
log_notice(_("unable to register master node - see preceding messages"));
exit(ERR_DB_QUERY);
}
commit_transaction(conn);
PQfinish(conn);
log_notice(_("master node record (id: %i) %s"),
config_file_options.node_id,
record_found ? "updated" : "registered");
return;
}
static void
@@ -934,107 +755,6 @@ do_standby_clone(void)
}
/*
* CLUSTER EVENT
*
* Parameters:
* --limit[=20]
* --all
* --node_[id|name]
* --event
* --event-matching
*/
static void
do_cluster_event(void)
{
PGconn *conn;
PQExpBufferData query;
PQExpBufferData where_clause;
PGresult *res;
int i;
conn = establish_db_connection(config_file_options.conninfo, true);
initPQExpBuffer(&query);
initPQExpBuffer(&where_clause);
appendPQExpBuffer(&query,
" SELECT node_id, event, successful, \n"
" TO_CHAR( event_timestamp, 'YYYY-MM-DD HH24:MI:SS') AS timestamp, \n"
" details \n"
" FROM repmgr.events");
if (runtime_options.node_id != UNKNOWN_NODE_ID)
{
append_where_clause(&where_clause,
"node_id=%i", runtime_options.node_id);
}
if (runtime_options.event[0] != '\0')
{
char *escaped = escape_string(conn, runtime_options.event);
if (escaped == NULL)
{
log_error(_("unable to escape value provided for event"));
}
else
{
append_where_clause(&where_clause,
"event='%s'",
escaped);
pfree(escaped);
}
}
appendPQExpBuffer(&query, "\n%s\n",
where_clause.data);
appendPQExpBuffer(&query,
" ORDER BY timestamp DESC");
if (runtime_options.all == false && runtime_options.limit > 0)
{
appendPQExpBuffer(&query, " LIMIT %i",
runtime_options.limit);
}
log_debug("do_cluster_event():\n%s", query.data);
res = PQexec(conn, query.data);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
log_error(_("unable to execute event query:\n %s"),
PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
exit(ERR_DB_QUERY);
}
if (PQntuples(res) == 0) {
printf(_("no matching events found\n"));
PQclear(res);
PQfinish(conn);
return;
}
/* XXX improve formatting */
puts("node_id,event,ok,timestamp,details");
puts("----------------------------------");
for(i = 0; i < PQntuples(res); i++)
{
printf("%s,%s,%s,%s,%s\n",
PQgetvalue(res, i, 0),
PQgetvalue(res, i, 1),
PQgetvalue(res, i, 2),
PQgetvalue(res, i, 3),
PQgetvalue(res, i, 4));
}
PQclear(res);
PQfinish(conn);
}
/*
@@ -1046,8 +766,9 @@ do_cluster_event(void)
* We should also consider possible scenarious where a non-superuser
* has sufficient privileges to install the extension.
*/
static
bool create_repmgr_extension(PGconn *conn)
bool
create_repmgr_extension(PGconn *conn)
{
PQExpBufferData query;
PGresult *res;
@@ -1245,7 +966,7 @@ bool create_repmgr_extension(PGconn *conn)
* passed to get_server_version(), which will place the human-readable
* server version string there (e.g. "9.4.0")
*/
static int
int
check_server_version(PGconn *conn, char *server_type, bool exit_on_error, char *server_version_string)
{
int server_version_num = 0;