From 1b785d9a20b282740de3c271b527550ee3f5c8d8 Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Wed, 26 Apr 2017 10:31:56 +0900 Subject: [PATCH] Add simple output for CLUSTER EVENT --- Makefile.in | 2 + dbutils.c | 2 + repmgr-client.c | 100 +++++++++++++++++++++++++++++++++++++++++++++--- repmgr-client.h | 5 +++ strutil.c | 45 ++++++++++++++++++++++ strutil.h | 7 ++++ 6 files changed, 156 insertions(+), 5 deletions(-) diff --git a/Makefile.in b/Makefile.in index 018df0ca..93736bcd 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,6 +29,8 @@ $(info Building against PostgreSQL $(MAJORVERSION)) REPMGR_CLIENT_OBJS = repmgr-client.o config.o log.o strutil.o dbutils.o REPMGRD_OBJS = repmgrd.o +$(REPMGR_CLIENT_OBJS): repmgr-client.h + repmgr4: $(REPMGR_CLIENT_OBJS) $(CC) $(CFLAGS) $(REPMGR_CLIENT_OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) diff --git a/dbutils.c b/dbutils.c index f5d7c8d6..addce570 100644 --- a/dbutils.c +++ b/dbutils.c @@ -710,6 +710,8 @@ get_master_node_id(PGconn *conn) return retval; } + + /* ================ */ /* result functions */ /* ================ */ diff --git a/repmgr-client.c b/repmgr-client.c index 11fcb7b0..3f0f6d97 100644 --- a/repmgr-client.c +++ b/repmgr-client.c @@ -505,6 +505,7 @@ check_cli_parameters(const int action) { case STANDBY_UNREGISTER: case WITNESS_UNREGISTER: + case CLUSTER_EVENT: break; default: item_list_append_format(&cli_warnings, @@ -520,6 +521,7 @@ check_cli_parameters(const int action) { case STANDBY_UNREGISTER: case WITNESS_UNREGISTER: + case CLUSTER_EVENT: if (runtime_options.node_id != UNKNOWN_NODE_ID) { item_list_append(&cli_warnings, @@ -842,15 +844,104 @@ do_standby_clone(void) static void do_cluster_event(void) { - puts("cluster event"); + 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); } /* - * Create the repmgr extension, and grant access to the repmgr + * Create the repmgr extension, and grant access for the repmgr * user if not a superuser. * - * Note: this should be the only place where superuser rights are required + * Note: + * This should be the only place where superuser rights are required. + * We should also consider possible scenarious where a non-superuser + * has sufficient privileges to install the extension. */ static bool create_repmgr_extension(PGconn *conn) @@ -899,8 +990,6 @@ bool create_repmgr_extension(PGconn *conn) return true; } - - PQclear(res); termPQExpBuffer(&query); @@ -932,6 +1021,7 @@ bool create_repmgr_extension(PGconn *conn) return false; } + /* check provided superuser really is superuser */ superuser_status = PQparameterStatus(superuser_conn, "is_superuser"); if (strcmp(superuser_status, "off") == 0) { diff --git a/repmgr-client.h b/repmgr-client.h index 5aadc00b..3b5ebffd 100644 --- a/repmgr-client.h +++ b/repmgr-client.h @@ -80,9 +80,14 @@ static struct option long_options[] = /* connection options */ {"superuser", required_argument, NULL, 'S'}, + + +/* node options */ {"pgdata", required_argument, NULL, 'D'}, /* legacy alias for -D/--pgdata*/ {"data-dir", required_argument, NULL, 'D'}, + {"node-id", required_argument, NULL, OPT_NODE_ID}, + {"node-name", required_argument, NULL, OPT_NODE_NAME}, /* logging options */ {"log-level", required_argument, NULL, 'L'}, diff --git a/strutil.c b/strutil.c index da1ffd25..28055e3c 100644 --- a/strutil.c +++ b/strutil.c @@ -60,6 +60,32 @@ maxlen_snprintf(char *str, const char *format,...) } +void +append_where_clause(PQExpBufferData *where_clause, const char *format, ...) +{ + va_list arglist; + char stringbuf[MAXLEN]; + + va_start(arglist, format); + (void) xvsnprintf(stringbuf, MAXLEN, format, arglist); + va_end(arglist); + + if(where_clause->data[0] == '\0') + { + appendPQExpBuffer(where_clause, + " WHERE "); + } + else + { + appendPQExpBuffer(where_clause, + " AND "); + } + + appendPQExpBuffer(where_clause, + "%s", stringbuf); + +} + void item_list_append(ItemList *item_list, const char *message) { @@ -112,3 +138,22 @@ escape_recovery_conf_value(const char *src) } return result; } + +char * +escape_string(PGconn *conn, const char *string) +{ + char *escaped_string; + int error; + + escaped_string = pg_malloc0(MAXLEN); + + (void) PQescapeStringConn(conn, escaped_string, string, MAXLEN, &error); + + if (error) + { + pfree(escaped_string); + return NULL; + } + + return escaped_string; +} diff --git a/strutil.h b/strutil.h index 6c20fa0e..b9d4a4a2 100644 --- a/strutil.h +++ b/strutil.h @@ -48,5 +48,12 @@ __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3))); extern char * escape_recovery_conf_value(const char *src); +extern char * +escape_string(PGconn *conn, const char *string); + +extern void +append_where_clause(PQExpBufferData *where_clause, const char *clause, ...) +__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3))); + #endif /* _STRUTIL_H_ */