From cbe19d5868ced811676eaac2b6caf9a33be5e603 Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Tue, 25 Jul 2017 09:27:21 +0900 Subject: [PATCH] repmgr node status: collate output into list To make output in different formats (e.g. CSV) easier. --- repmgr-action-node.c | 107 +++++++++++++++++++++++-------------------- strutil.c | 61 +++++++++++++++++++++++- strutil.h | 24 ++++++++++ 3 files changed, 140 insertions(+), 52 deletions(-) diff --git a/repmgr-action-node.c b/repmgr-action-node.c index 3e2b323b..58f27d7b 100644 --- a/repmgr-action-node.c +++ b/repmgr-action-node.c @@ -23,6 +23,9 @@ do_node_status(void) char cluster_size[MAXLEN]; PQExpBufferData output; + KeyValueList node_status = { NULL, NULL }; + KeyValueListCell *cell; + ItemList warnings = { NULL, NULL }; RecoveryType recovery_type; @@ -53,32 +56,25 @@ do_node_status(void) get_node_replication_stats(conn, &node_info); - initPQExpBuffer(&output); + key_value_list_set( + &node_status, + "PostgreSQL version", + server_version); - appendPQExpBuffer( - &output, - "Node \"%s\":\n", - node_info.node_name); + key_value_list_set( + &node_status, + "Total data size", + cluster_size); - appendPQExpBuffer( - &output, - "%cPostgreSQL version: %s\n", - '\t', server_version); + key_value_list_set( + &node_status, + "Conninfo", + node_info.conninfo); - appendPQExpBuffer( - &output, - "%cTotal data size: %s\n", - '\t', cluster_size); - - appendPQExpBuffer( - &output, - "%cConninfo: \"%s\"\n", - '\t', node_info.conninfo); - - appendPQExpBuffer( - &output, - "%cRole: \"%s\"\n", - '\t', get_node_type_string(node_info.type)); + key_value_list_set( + &node_status, + "Role", + get_node_type_string(node_info.type)); switch (node_info.type) { @@ -106,35 +102,37 @@ do_node_status(void) if (node_info.max_wal_senders >= 0) { - appendPQExpBuffer( - &output, - "%cReplication connections: %i (of maximal %i)\n", - '\t', + key_value_list_set_format( + &node_status, + "Replication connections", + "%i (of maximal %i)", node_info.attached_wal_receivers, node_info.max_wal_senders); - } else if (node_info.max_wal_senders == 0) { - appendPQExpBuffer( - &output, - "%cReplication connections: disabled\n", - '\t'); + key_value_list_set_format( + &node_status, + "Replication connections", + "disabled"); } if (node_info.max_replication_slots > 0) { + PQExpBufferData slotinfo; + initPQExpBuffer(&slotinfo); + appendPQExpBuffer( - &output, - "%cReplication slots: %i (of maximal %i)", - '\t', + &slotinfo, + "%i (of maximal %i)", node_info.active_replication_slots + node_info.inactive_replication_slots, node_info.max_replication_slots); + if (node_info.inactive_replication_slots > 0) { appendPQExpBuffer( - &output, + &slotinfo, "; %i inactive", node_info.inactive_replication_slots); @@ -143,26 +141,35 @@ do_node_status(void) _("- node has %i inactive replication slots"), node_info.inactive_replication_slots); } + + key_value_list_set( + &node_status, + "Replication slots", + slotinfo.data); + + termPQExpBuffer(&slotinfo); } else if (node_info.max_replication_slots == 0) { - appendPQExpBuffer( - &output, - "%cReplication slots: disabled\n", - '\t'); + key_value_list_set( + &node_status, + "Replication slots", + "disabled"); } -/* - appendPQExpBuffer( - &output, - "%c: \"%s\"\n", - '\t', ); - appendPQExpBuffer( - &output, - "%c: \"%s\"\n", - '\t', node_info.); -*/ + initPQExpBuffer(&output); + appendPQExpBuffer( + &output, + "Node \"%s\":\n", + node_info.node_name); + + for (cell = node_status.head; cell; cell = cell->next) + { + appendPQExpBuffer( + &output, + "\t%s: %s\n", cell->key, cell->value); + } puts(output.data); diff --git a/strutil.c b/strutil.c index a3e0b4b2..6bfb6285 100644 --- a/strutil.c +++ b/strutil.c @@ -48,6 +48,7 @@ maxlen_snprintf(char *str, const char *format,...) return retval; } + int maxpath_snprintf(char *str, const char *format,...) { @@ -61,6 +62,7 @@ maxpath_snprintf(char *str, const char *format,...) return retval; } + void append_where_clause(PQExpBufferData *where_clause, const char *format, ...) { @@ -87,17 +89,19 @@ append_where_clause(PQExpBufferData *where_clause, const char *format, ...) } + void item_list_append(ItemList *item_list, const char *message) { item_list_append_format(item_list, "%s", message); } + void item_list_append_format(ItemList *item_list, const char *format, ...) { ItemListCell *cell; - va_list arglist; + va_list arglist; cell = (ItemListCell *) pg_malloc0(sizeof(ItemListCell)); @@ -123,6 +127,58 @@ item_list_append_format(ItemList *item_list, const char *format, ...) item_list->tail = cell; } + +void +key_value_list_set(KeyValueList *item_list, const char *key, const char *value) +{ + key_value_list_set_format(item_list, key, "%s", value); + return; +} + +void +key_value_list_set_format(KeyValueList *item_list, const char *key, const char *value, ...) +{ + KeyValueListCell *cell; + va_list arglist; + int keylen; + + cell = (KeyValueListCell *) pg_malloc0(sizeof(KeyValueListCell)); + + if (cell == NULL) + { + log_error(_("unable to allocate memory; terminating.")); + exit(ERR_BAD_CONFIG); + } + + keylen = strlen(key); + + cell->key = pg_malloc0(keylen + 1); + cell->value = pg_malloc0(MAXLEN); + + strncpy(cell->key, key, keylen); + + va_start(arglist, value); + (void) xvsnprintf(cell->value, MAXLEN, value, arglist); + va_end(arglist); + + + if (item_list->tail) + item_list->tail->next = cell; + else + item_list->head = cell; + + item_list->tail = cell; + + return; +} + + +const char * +key_value_list_get(KeyValueList *item_list, const char *key) +{ + return NULL; +} + /* * Escape a string for use as a parameter in recovery.conf * Caller must free returned value @@ -140,6 +196,7 @@ escape_recovery_conf_value(const char *src) return result; } + char * escape_string(PGconn *conn, const char *string) { @@ -160,7 +217,6 @@ escape_string(PGconn *conn, const char *string) } - char * string_skip_prefix(const char *prefix, char *string) { @@ -174,6 +230,7 @@ string_skip_prefix(const char *prefix, char *string) return string + n; } + char * string_remove_trailing_newlines(char *string) { diff --git a/strutil.h b/strutil.h index 54e8a6fe..ecd3a4a7 100644 --- a/strutil.h +++ b/strutil.h @@ -31,6 +31,19 @@ typedef struct ItemList ItemListCell *tail; } ItemList; +typedef struct KeyValueListCell +{ + struct KeyValueListCell *next; + char *key; + char *value; +} KeyValueListCell; + +typedef struct KeyValueList +{ + KeyValueListCell *head; + KeyValueListCell *tail; +} KeyValueList; + extern int maxlen_snprintf(char *str, const char *format,...) @@ -47,6 +60,17 @@ extern void item_list_append_format(ItemList *item_list, const char *format, ...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3))); +extern void +key_value_list_set(KeyValueList *item_list, const char *key, const char *value); + +extern void +key_value_list_set_format(KeyValueList *item_list, const char *key, const char *value, ...) +__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4))); + +extern const char * +key_value_list_get(KeyValueList *item_list, const char *key); + + extern char * escape_recovery_conf_value(const char *src);