node status: improve output and documentation

In the default text output mode, list inactive slots.

In CSV output mode, list inactive slots as additional information;
add output line with number of missing slots and a list thereof.

Also document --csv output mode.
This commit is contained in:
Ian Barwick
2018-06-22 11:44:56 +09:00
parent 4d70a667fb
commit fcf237fe31
5 changed files with 113 additions and 12 deletions

View File

@@ -2933,8 +2933,7 @@ get_datadir_configuration_files(PGconn *conn, KeyValueList *list)
for (i = 0; i < PQntuples(res); i++) for (i = 0; i < PQntuples(res); i++)
{ {
key_value_list_set( key_value_list_set(list,
list,
PQgetvalue(res, i, 1), PQgetvalue(res, i, 1),
PQgetvalue(res, i, 0)); PQgetvalue(res, i, 0));
} }
@@ -3671,7 +3670,7 @@ get_slot_record(PGconn *conn, char *slot_name, t_replication_slot *record)
int int
get_free_replication_slots(PGconn *conn) get_free_replication_slot_count(PGconn *conn)
{ {
PQExpBufferData query; PQExpBufferData query;
PGresult *res = NULL; PGresult *res = NULL;
@@ -3708,6 +3707,47 @@ get_free_replication_slots(PGconn *conn)
} }
int
get_inactive_replication_slots(PGconn *conn, KeyValueList *list)
{
PQExpBufferData query;
PGresult *res = NULL;
int i, inactive_slots = 0;
initPQExpBuffer(&query);
appendPQExpBuffer(&query,
" SELECT slot_name, slot_type "
" FROM pg_catalog.pg_replication_slots "
" WHERE active IS FALSE "
" ORDER BY slot_name ");
res = PQexec(conn, query.data);
termPQExpBuffer(&query);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
log_error(_("unable to execute replication slot query"));
log_detail("%s", PQerrorMessage(conn));
PQclear(res);
return -1;
}
inactive_slots = PQntuples(res);
for (i = 0; i < inactive_slots; i++)
{
key_value_list_set(list,
PQgetvalue(res, i, 0),
PQgetvalue(res, i, 1));
}
PQclear(res);
return inactive_slots;
}
/* ==================== */ /* ==================== */
/* tablespace functions */ /* tablespace functions */
/* ==================== */ /* ==================== */

View File

@@ -453,7 +453,8 @@ void create_slot_name(char *slot_name, int node_id);
bool create_replication_slot(PGconn *conn, char *slot_name, int server_version_num, PQExpBufferData *error_msg); bool create_replication_slot(PGconn *conn, char *slot_name, int server_version_num, PQExpBufferData *error_msg);
bool drop_replication_slot(PGconn *conn, char *slot_name); bool drop_replication_slot(PGconn *conn, char *slot_name);
RecordStatus get_slot_record(PGconn *conn, char *slot_name, t_replication_slot *record); RecordStatus get_slot_record(PGconn *conn, char *slot_name, t_replication_slot *record);
int get_free_replication_slots(PGconn *conn); int get_free_replication_slot_count(PGconn *conn);
int get_inactive_replication_slots(PGconn *conn, KeyValueList *list);
/* tablespace functions */ /* tablespace functions */
bool get_tablespace_name_by_location(PGconn *conn, const char *location, char *name); bool get_tablespace_name_by_location(PGconn *conn, const char *location, char *name);

View File

@@ -24,7 +24,7 @@
<title>Example</title> <title>Example</title>
<para> <para>
<programlisting> <programlisting>
$ repmgr -f /etc/repmgr.comf node status $ repmgr -f /etc/repmgr.conf node status
Node "node1": Node "node1":
PostgreSQL version: 10beta1 PostgreSQL version: 10beta1
Total data size: 30 MB Total data size: 30 MB
@@ -38,6 +38,20 @@
</para> </para>
</refsect1> </refsect1>
<refsect1>
<title>Output format</title>
<para>
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<simpara>
<literal>--csv</literal>: generate output in CSV format
</simpara>
</listitem>
</itemizedlist>
</para>
</refsect1>
<refsect1> <refsect1>
<title>See also</title> <title>See also</title>
<para> <para>

View File

@@ -71,6 +71,7 @@ do_node_status(void)
KeyValueList node_status = {NULL, NULL}; KeyValueList node_status = {NULL, NULL};
KeyValueListCell *cell = NULL; KeyValueListCell *cell = NULL;
NodeInfoList missing_slots = T_NODE_INFO_LIST_INITIALIZER;
ItemList warnings = {NULL, NULL}; ItemList warnings = {NULL, NULL};
RecoveryType recovery_type = RECTYPE_UNKNOWN; RecoveryType recovery_type = RECTYPE_UNKNOWN;
@@ -265,7 +266,6 @@ do_node_status(void)
else else
{ {
PQExpBufferData slotinfo; PQExpBufferData slotinfo;
NodeInfoList missing_slots = T_NODE_INFO_LIST_INITIALIZER;
/* /*
* check for missing replication slots - we do this regardless of * check for missing replication slots - we do this regardless of
@@ -305,6 +305,11 @@ do_node_status(void)
if (node_info.inactive_replication_slots > 0) if (node_info.inactive_replication_slots > 0)
{ {
KeyValueList inactive_replication_slots = {NULL, NULL};
KeyValueListCell *cell = NULL;
(void) get_inactive_replication_slots(conn, &inactive_replication_slots);
appendPQExpBuffer(&slotinfo, appendPQExpBuffer(&slotinfo,
"; %i inactive", "; %i inactive",
node_info.inactive_replication_slots); node_info.inactive_replication_slots);
@@ -312,6 +317,14 @@ do_node_status(void)
item_list_append_format(&warnings, item_list_append_format(&warnings,
_("- node has %i inactive replication slots"), _("- node has %i inactive replication slots"),
node_info.inactive_replication_slots); node_info.inactive_replication_slots);
for (cell = inactive_replication_slots.head; cell; cell = cell->next)
{
item_list_append_format(&warnings,
" - %s (%s)", cell->key, cell->value);
}
key_value_list_free(&inactive_replication_slots);
} }
key_value_list_set(&node_status, key_value_list_set(&node_status,
@@ -415,10 +428,44 @@ do_node_status(void)
"\"active_replication_slots\",%i\n", "\"active_replication_slots\",%i\n",
node_info.active_replication_slots); node_info.active_replication_slots);
/* output inactive slot information */
appendPQExpBuffer(&output, appendPQExpBuffer(&output,
"\"inactive_replaction_slots\",%i\n", "\"inactive_replication_slots\",%i",
node_info.inactive_replication_slots); node_info.inactive_replication_slots);
if (node_info.inactive_replication_slots)
{
KeyValueList inactive_replication_slots = {NULL, NULL};
KeyValueListCell *cell = NULL;
(void) get_inactive_replication_slots(conn, &inactive_replication_slots);
for (cell = inactive_replication_slots.head; cell; cell = cell->next)
{
appendPQExpBuffer(&output,
",\"%s\"", cell->key);
}
key_value_list_free(&inactive_replication_slots);
}
/* output missing slot information */
appendPQExpBuffer(&output, "\n");
appendPQExpBuffer(&output,
"\"missing_replication_slots\",%i",
missing_slots.node_count);
if (missing_slots.node_count > 0)
{
NodeInfoListCell *missing_slot_cell = NULL;
for (missing_slot_cell = missing_slots.head; missing_slot_cell; missing_slot_cell = missing_slot_cell->next)
{
appendPQExpBuffer(&output,
",\"%s\"", missing_slot_cell->node_info->slot_name);
}
}
} }
else else
{ {
@@ -439,12 +486,11 @@ do_node_status(void)
termPQExpBuffer(&output); termPQExpBuffer(&output);
if (warnings.head != NULL && runtime_options.terse == false) if (runtime_options.output_mode == OM_TEXT && warnings.head != NULL && runtime_options.terse == false)
{ {
log_warning(_("following issue(s) were detected:")); log_warning(_("following issue(s) were detected:"));
print_item_list(&warnings); print_item_list(&warnings);
/* add this when functionality implemented */ log_hint(_("execute \"repmgr node check\" for more details"));
/* log_hint(_("execute \"repmgr node check\" for more details")); */
} }
key_value_list_free(&node_status); key_value_list_free(&node_status);
@@ -1337,7 +1383,7 @@ do_node_check_replication_lag(PGconn *conn, OutputMode mode, t_node_info *node_i
return status; return status;
} }
/* TODO: ensure only runs on streaming replication nodes */
static CheckStatus static CheckStatus
do_node_check_downstream(PGconn *conn, OutputMode mode, CheckStatusList *list_output) do_node_check_downstream(PGconn *conn, OutputMode mode, CheckStatusList *list_output)
{ {

View File

@@ -2257,7 +2257,7 @@ do_standby_follow(void)
if (config_file_options.use_replication_slots) if (config_file_options.use_replication_slots)
{ {
int free_slots = get_free_replication_slots(primary_conn); int free_slots = get_free_replication_slot_count(primary_conn);
if (free_slots < 0) if (free_slots < 0)
{ {
log_error(_("unable to determine number of free replication slots on the primary")); log_error(_("unable to determine number of free replication slots on the primary"));