mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-22 22:56:29 +00:00
Add simple output for CLUSTER EVENT
This commit is contained in:
@@ -29,6 +29,8 @@ $(info Building against PostgreSQL $(MAJORVERSION))
|
|||||||
REPMGR_CLIENT_OBJS = repmgr-client.o config.o log.o strutil.o dbutils.o
|
REPMGR_CLIENT_OBJS = repmgr-client.o config.o log.o strutil.o dbutils.o
|
||||||
REPMGRD_OBJS = repmgrd.o
|
REPMGRD_OBJS = repmgrd.o
|
||||||
|
|
||||||
|
$(REPMGR_CLIENT_OBJS): repmgr-client.h
|
||||||
|
|
||||||
repmgr4: $(REPMGR_CLIENT_OBJS)
|
repmgr4: $(REPMGR_CLIENT_OBJS)
|
||||||
$(CC) $(CFLAGS) $(REPMGR_CLIENT_OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
|
$(CC) $(CFLAGS) $(REPMGR_CLIENT_OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
|
||||||
|
|
||||||
|
|||||||
@@ -710,6 +710,8 @@ get_master_node_id(PGconn *conn)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ================ */
|
/* ================ */
|
||||||
/* result functions */
|
/* result functions */
|
||||||
/* ================ */
|
/* ================ */
|
||||||
|
|||||||
100
repmgr-client.c
100
repmgr-client.c
@@ -505,6 +505,7 @@ check_cli_parameters(const int action)
|
|||||||
{
|
{
|
||||||
case STANDBY_UNREGISTER:
|
case STANDBY_UNREGISTER:
|
||||||
case WITNESS_UNREGISTER:
|
case WITNESS_UNREGISTER:
|
||||||
|
case CLUSTER_EVENT:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
item_list_append_format(&cli_warnings,
|
item_list_append_format(&cli_warnings,
|
||||||
@@ -520,6 +521,7 @@ check_cli_parameters(const int action)
|
|||||||
{
|
{
|
||||||
case STANDBY_UNREGISTER:
|
case STANDBY_UNREGISTER:
|
||||||
case WITNESS_UNREGISTER:
|
case WITNESS_UNREGISTER:
|
||||||
|
case CLUSTER_EVENT:
|
||||||
if (runtime_options.node_id != UNKNOWN_NODE_ID)
|
if (runtime_options.node_id != UNKNOWN_NODE_ID)
|
||||||
{
|
{
|
||||||
item_list_append(&cli_warnings,
|
item_list_append(&cli_warnings,
|
||||||
@@ -842,15 +844,104 @@ do_standby_clone(void)
|
|||||||
static void
|
static void
|
||||||
do_cluster_event(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.
|
* 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
|
static
|
||||||
bool create_repmgr_extension(PGconn *conn)
|
bool create_repmgr_extension(PGconn *conn)
|
||||||
@@ -899,8 +990,6 @@ bool create_repmgr_extension(PGconn *conn)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
termPQExpBuffer(&query);
|
termPQExpBuffer(&query);
|
||||||
|
|
||||||
@@ -932,6 +1021,7 @@ bool create_repmgr_extension(PGconn *conn)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check provided superuser really is superuser */
|
||||||
superuser_status = PQparameterStatus(superuser_conn, "is_superuser");
|
superuser_status = PQparameterStatus(superuser_conn, "is_superuser");
|
||||||
if (strcmp(superuser_status, "off") == 0)
|
if (strcmp(superuser_status, "off") == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -80,9 +80,14 @@ static struct option long_options[] =
|
|||||||
|
|
||||||
/* connection options */
|
/* connection options */
|
||||||
{"superuser", required_argument, NULL, 'S'},
|
{"superuser", required_argument, NULL, 'S'},
|
||||||
|
|
||||||
|
|
||||||
|
/* node options */
|
||||||
{"pgdata", required_argument, NULL, 'D'},
|
{"pgdata", required_argument, NULL, 'D'},
|
||||||
/* legacy alias for -D/--pgdata*/
|
/* legacy alias for -D/--pgdata*/
|
||||||
{"data-dir", required_argument, NULL, 'D'},
|
{"data-dir", required_argument, NULL, 'D'},
|
||||||
|
{"node-id", required_argument, NULL, OPT_NODE_ID},
|
||||||
|
{"node-name", required_argument, NULL, OPT_NODE_NAME},
|
||||||
|
|
||||||
/* logging options */
|
/* logging options */
|
||||||
{"log-level", required_argument, NULL, 'L'},
|
{"log-level", required_argument, NULL, 'L'},
|
||||||
|
|||||||
45
strutil.c
45
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
|
void
|
||||||
item_list_append(ItemList *item_list, const char *message)
|
item_list_append(ItemList *item_list, const char *message)
|
||||||
{
|
{
|
||||||
@@ -112,3 +138,22 @@ escape_recovery_conf_value(const char *src)
|
|||||||
}
|
}
|
||||||
return result;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,5 +48,12 @@ __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
|
|||||||
extern char *
|
extern char *
|
||||||
escape_recovery_conf_value(const char *src);
|
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_ */
|
#endif /* _STRUTIL_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user