mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-23 15:16:29 +00:00
Compare commits
64 Commits
v5.3.1
...
REL5_2_STA
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
922b8de46b | ||
|
|
92cd8c30b5 | ||
|
|
fa234919fb | ||
|
|
03c5220e87 | ||
|
|
65bd0878fa | ||
|
|
f1592f009a | ||
|
|
490e51fd7b | ||
|
|
f5c555a7f5 | ||
|
|
de51df9759 | ||
|
|
b094d7b407 | ||
|
|
44cdb7d001 | ||
|
|
f5f8db8ca1 | ||
|
|
0c568da254 | ||
|
|
46042298f7 | ||
|
|
01e89c3ca9 | ||
|
|
7b97a8f04d | ||
|
|
c362d6d03f | ||
|
|
75a2e2a8b4 | ||
|
|
65d59db6d1 | ||
|
|
10cd15bedc | ||
|
|
cae2255d58 | ||
|
|
bc0bc2696e | ||
|
|
7db9afdc10 | ||
|
|
5eb8bccd33 | ||
|
|
4760c11937 | ||
|
|
cb6501aa48 | ||
|
|
6100007a32 | ||
|
|
a415d85530 | ||
|
|
45a9a784e3 | ||
|
|
8ce212327c | ||
|
|
54851e8df1 | ||
|
|
a2166d0024 | ||
|
|
abe55e60e6 | ||
|
|
220bcbd620 | ||
|
|
e824dfd499 | ||
|
|
9fb9decf13 | ||
|
|
ad6dde4218 | ||
|
|
7cbaec6469 | ||
|
|
9d2c5921ee | ||
|
|
21f94e6de3 | ||
|
|
7418c7b8f0 | ||
|
|
7cee09dd95 | ||
|
|
53774d6998 | ||
|
|
5a251ef268 | ||
|
|
b83ce6b147 | ||
|
|
5f9f1f65ae | ||
|
|
9d7eebef1b | ||
|
|
5cff7fab64 | ||
|
|
2a8ac36aec | ||
|
|
a5a5b506f9 | ||
|
|
bd6871817d | ||
|
|
bd35e503ec | ||
|
|
15801b8f9e | ||
|
|
4d3262d306 | ||
|
|
36a8dfcf4f | ||
|
|
94612a336a | ||
|
|
de567d584f | ||
|
|
0fb3432398 | ||
|
|
5e59e543d6 | ||
|
|
4f6b642320 | ||
|
|
c1973438f7 | ||
|
|
fe5904e04e | ||
|
|
2cb1f4f728 | ||
|
|
5b90842c55 |
10
HISTORY
10
HISTORY
@@ -1,12 +1,4 @@
|
|||||||
5.3.1 2022-??-??
|
5.2.2. 2021-??-??
|
||||||
repmgrd: fixes for potential connection leaks (hslightdb)
|
|
||||||
|
|
||||||
5.3.0 2021-10-12
|
|
||||||
standby switchover: improve handling of node rejoin failure (Ian)
|
|
||||||
repmgrd: prefix all shared library functions with "repmgr_" to
|
|
||||||
minimize the risk of clashes with other shared libraries (Ian)
|
|
||||||
repmgrd: at startup, if node record is marked as "inactive", attempt
|
|
||||||
to set it to "active" (Ian)
|
|
||||||
standby clone: set "slot_name" in node record if required (Ian)
|
standby clone: set "slot_name" in node record if required (Ian)
|
||||||
node rejoin: emit rejoin target note information as NOTICE (Ian)
|
node rejoin: emit rejoin target note information as NOTICE (Ian)
|
||||||
repmgrd: ensure short option "-s" is accepted (Ian)
|
repmgrd: ensure short option "-s" is accepted (Ian)
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ DATA = \
|
|||||||
repmgr--unpackaged--4.0.sql \
|
repmgr--unpackaged--4.0.sql \
|
||||||
repmgr--unpackaged--5.1.sql \
|
repmgr--unpackaged--5.1.sql \
|
||||||
repmgr--unpackaged--5.2.sql \
|
repmgr--unpackaged--5.2.sql \
|
||||||
repmgr--unpackaged--5.3.sql \
|
|
||||||
repmgr--4.0.sql \
|
repmgr--4.0.sql \
|
||||||
repmgr--4.0--4.1.sql \
|
repmgr--4.0--4.1.sql \
|
||||||
repmgr--4.1.sql \
|
repmgr--4.1.sql \
|
||||||
@@ -28,9 +27,7 @@ DATA = \
|
|||||||
repmgr--5.0--5.1.sql \
|
repmgr--5.0--5.1.sql \
|
||||||
repmgr--5.1.sql \
|
repmgr--5.1.sql \
|
||||||
repmgr--5.1--5.2.sql \
|
repmgr--5.1--5.2.sql \
|
||||||
repmgr--5.2.sql \
|
repmgr--5.2.sql
|
||||||
repmgr--5.2--5.3.sql \
|
|
||||||
repmgr--5.3.sql
|
|
||||||
|
|
||||||
REGRESS = repmgr_extension
|
REGRESS = repmgr_extension
|
||||||
|
|
||||||
|
|||||||
@@ -90,4 +90,3 @@ Further reading
|
|||||||
* [repmgr documentation](https://repmgr.org/docs/current/index.html)
|
* [repmgr documentation](https://repmgr.org/docs/current/index.html)
|
||||||
* [How to Automate PostgreSQL 12 Replication and Failover with repmgr - Part 1](https://www.2ndquadrant.com/en/blog/how-to-automate-postgresql-12-replication-and-failover-with-repmgr-part-1/)
|
* [How to Automate PostgreSQL 12 Replication and Failover with repmgr - Part 1](https://www.2ndquadrant.com/en/blog/how-to-automate-postgresql-12-replication-and-failover-with-repmgr-part-1/)
|
||||||
* [How to Automate PostgreSQL 12 Replication and Failover with repmgr - Part 2](https://www.2ndquadrant.com/en/blog/how-to-automate-postgresql-12-replication-and-failover-with-repmgr-part-2/)
|
* [How to Automate PostgreSQL 12 Replication and Failover with repmgr - Part 2](https://www.2ndquadrant.com/en/blog/how-to-automate-postgresql-12-replication-and-failover-with-repmgr-part-2/)
|
||||||
* [How to implement repmgr for PostgreSQL automatic failover](https://www.enterprisedb.com/postgres-tutorials/how-implement-repmgr-postgresql-automatic-failover)
|
|
||||||
|
|||||||
10
configdata.c
10
configdata.c
@@ -581,16 +581,6 @@ struct ConfigFileSetting config_file_settings[] =
|
|||||||
{ .strmaxlen = sizeof(config_file_options.repmgrd_pid_file) },
|
{ .strmaxlen = sizeof(config_file_options.repmgrd_pid_file) },
|
||||||
{ .postprocess_func = &repmgr_canonicalize_path }
|
{ .postprocess_func = &repmgr_canonicalize_path }
|
||||||
},
|
},
|
||||||
/* repmgrd_exit_on_inactive_node */
|
|
||||||
{
|
|
||||||
"repmgrd_exit_on_inactive_node",
|
|
||||||
CONFIG_BOOL,
|
|
||||||
{ .boolptr = &config_file_options.repmgrd_exit_on_inactive_node},
|
|
||||||
{ .booldefault = DEFAULT_REPMGRD_EXIT_ON_INACTIVE_NODE },
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{}
|
|
||||||
},
|
|
||||||
/* standby_disconnect_on_failover */
|
/* standby_disconnect_on_failover */
|
||||||
{
|
{
|
||||||
"standby_disconnect_on_failover",
|
"standby_disconnect_on_failover",
|
||||||
|
|||||||
@@ -206,7 +206,6 @@ typedef struct
|
|||||||
int primary_notification_timeout;
|
int primary_notification_timeout;
|
||||||
int repmgrd_standby_startup_timeout;
|
int repmgrd_standby_startup_timeout;
|
||||||
char repmgrd_pid_file[MAXPGPATH];
|
char repmgrd_pid_file[MAXPGPATH];
|
||||||
bool repmgrd_exit_on_inactive_node;
|
|
||||||
bool standby_disconnect_on_failover;
|
bool standby_disconnect_on_failover;
|
||||||
int sibling_nodes_disconnect_timeout;
|
int sibling_nodes_disconnect_timeout;
|
||||||
ConnectionCheckType connection_check_type;
|
ConnectionCheckType connection_check_type;
|
||||||
|
|||||||
24
configure
vendored
24
configure
vendored
@@ -1,6 +1,6 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.69 for repmgr 5.3.0.
|
# Generated by GNU Autoconf 2.69 for repmgr 5.2.1.
|
||||||
#
|
#
|
||||||
# Report bugs to <repmgr@googlegroups.com>.
|
# Report bugs to <repmgr@googlegroups.com>.
|
||||||
#
|
#
|
||||||
@@ -582,8 +582,8 @@ MAKEFLAGS=
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='repmgr'
|
PACKAGE_NAME='repmgr'
|
||||||
PACKAGE_TARNAME='repmgr'
|
PACKAGE_TARNAME='repmgr'
|
||||||
PACKAGE_VERSION='5.3.0'
|
PACKAGE_VERSION='5.2.1'
|
||||||
PACKAGE_STRING='repmgr 5.3.0'
|
PACKAGE_STRING='repmgr 5.2.1'
|
||||||
PACKAGE_BUGREPORT='repmgr@googlegroups.com'
|
PACKAGE_BUGREPORT='repmgr@googlegroups.com'
|
||||||
PACKAGE_URL='https://repmgr.org/'
|
PACKAGE_URL='https://repmgr.org/'
|
||||||
|
|
||||||
@@ -1181,7 +1181,7 @@ if test "$ac_init_help" = "long"; then
|
|||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures repmgr 5.3.0 to adapt to many kinds of systems.
|
\`configure' configures repmgr 5.2.1 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@@ -1242,7 +1242,7 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of repmgr 5.3.0:";;
|
short | recursive ) echo "Configuration of repmgr 5.2.1:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@@ -1316,7 +1316,7 @@ fi
|
|||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
repmgr configure 5.3.0
|
repmgr configure 5.2.1
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
@@ -1335,7 +1335,7 @@ cat >config.log <<_ACEOF
|
|||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by repmgr $as_me 5.3.0, which was
|
It was created by repmgr $as_me 5.2.1, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@@ -1811,11 +1811,11 @@ fi
|
|||||||
pgac_pg_config_version=$($PG_CONFIG --version 2>/dev/null)
|
pgac_pg_config_version=$($PG_CONFIG --version 2>/dev/null)
|
||||||
|
|
||||||
major_version_num=$(echo "$pgac_pg_config_version"|
|
major_version_num=$(echo "$pgac_pg_config_version"|
|
||||||
$SED -e 's/^[^0-9]\+ \([0-9]\{1,2\}\).*$/\1/')
|
$SED -e 's/^PostgreSQL \([0-9]\{1,2\}\).*$/\1/')
|
||||||
|
|
||||||
if test "$major_version_num" -lt '10'; then
|
if test "$major_version_num" -lt '10'; then
|
||||||
version_num=$(echo "$pgac_pg_config_version"|
|
version_num=$(echo "$pgac_pg_config_version"|
|
||||||
$SED -e 's/^[^0-9]\+ \([0-9]*\)\.\([0-9]*\)\([a-zA-Z0-9.]*\)$/\1.\2/')
|
$SED -e 's/^PostgreSQL \([0-9]*\)\.\([0-9]*\)\([a-zA-Z0-9.]*\)$/\1.\2/')
|
||||||
|
|
||||||
if test -z "$version_num"; then
|
if test -z "$version_num"; then
|
||||||
as_fn_error $? "could not detect the PostgreSQL version, wrong or broken pg_config?" "$LINENO" 5
|
as_fn_error $? "could not detect the PostgreSQL version, wrong or broken pg_config?" "$LINENO" 5
|
||||||
@@ -1829,7 +1829,7 @@ if test "$major_version_num" -lt '10'; then
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
version_num=$(echo "$pgac_pg_config_version"|
|
version_num=$(echo "$pgac_pg_config_version"|
|
||||||
$SED -e 's/^[^0-9]\+ \(.\+\)$/\1/')
|
$SED -e 's/^PostgreSQL \(.\+\)$/\1/')
|
||||||
|
|
||||||
if test -z "$version_num"; then
|
if test -z "$version_num"; then
|
||||||
as_fn_error $? "could not detect the PostgreSQL version, wrong or broken pg_config?" "$LINENO" 5
|
as_fn_error $? "could not detect the PostgreSQL version, wrong or broken pg_config?" "$LINENO" 5
|
||||||
@@ -2487,7 +2487,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by repmgr $as_me 5.3.0, which was
|
This file was extended by repmgr $as_me 5.2.1, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@@ -2550,7 +2550,7 @@ _ACEOF
|
|||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
repmgr config.status 5.3.0
|
repmgr config.status 5.2.1
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT([repmgr], [5.3.1], [repmgr@googlegroups.com], [repmgr], [https://repmgr.org/])
|
AC_INIT([repmgr], [5.2.1], [repmgr@googlegroups.com], [repmgr], [https://repmgr.org/])
|
||||||
|
|
||||||
AC_COPYRIGHT([Copyright (c) 2010-2021, EnterpriseDB Corporation])
|
AC_COPYRIGHT([Copyright (c) 2010-2021, EnterpriseDB Corporation])
|
||||||
|
|
||||||
@@ -19,11 +19,11 @@ fi
|
|||||||
pgac_pg_config_version=$($PG_CONFIG --version 2>/dev/null)
|
pgac_pg_config_version=$($PG_CONFIG --version 2>/dev/null)
|
||||||
|
|
||||||
major_version_num=$(echo "$pgac_pg_config_version"|
|
major_version_num=$(echo "$pgac_pg_config_version"|
|
||||||
$SED -e 's/^[[^0-9]]\+ \([[0-9]]\{1,2\}\).*$/\1/')
|
$SED -e 's/^PostgreSQL \([[0-9]]\{1,2\}\).*$/\1/')
|
||||||
|
|
||||||
if test "$major_version_num" -lt '10'; then
|
if test "$major_version_num" -lt '10'; then
|
||||||
version_num=$(echo "$pgac_pg_config_version"|
|
version_num=$(echo "$pgac_pg_config_version"|
|
||||||
$SED -e 's/^[[^0-9]]\+ \([[0-9]]*\)\.\([[0-9]]*\)\([[a-zA-Z0-9.]]*\)$/\1.\2/')
|
$SED -e 's/^PostgreSQL \([[0-9]]*\)\.\([[0-9]]*\)\([[a-zA-Z0-9.]]*\)$/\1.\2/')
|
||||||
|
|
||||||
if test -z "$version_num"; then
|
if test -z "$version_num"; then
|
||||||
AC_MSG_ERROR([could not detect the PostgreSQL version, wrong or broken pg_config?])
|
AC_MSG_ERROR([could not detect the PostgreSQL version, wrong or broken pg_config?])
|
||||||
@@ -37,7 +37,7 @@ if test "$major_version_num" -lt '10'; then
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
version_num=$(echo "$pgac_pg_config_version"|
|
version_num=$(echo "$pgac_pg_config_version"|
|
||||||
$SED -e 's/^[[^0-9]]\+ \(.\+\)$/\1/')
|
$SED -e 's/^PostgreSQL \(.\+\)$/\1/')
|
||||||
|
|
||||||
if test -z "$version_num"; then
|
if test -z "$version_num"; then
|
||||||
AC_MSG_ERROR([could not detect the PostgreSQL version, wrong or broken pg_config?])
|
AC_MSG_ERROR([could not detect the PostgreSQL version, wrong or broken pg_config?])
|
||||||
|
|||||||
39
dbutils.c
39
dbutils.c
@@ -4242,7 +4242,7 @@ _create_event(PGconn *conn, t_configuration_options *options, int node_id, char
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
/* %p: primary id ("standby_switchover"/"repmgrd_failover_promote": former primary id) */
|
/* %p: primary id ("standby_switchover": former primary id) */
|
||||||
src_ptr++;
|
src_ptr++;
|
||||||
if (event_info->node_id != UNKNOWN_NODE_ID)
|
if (event_info->node_id != UNKNOWN_NODE_ID)
|
||||||
{
|
{
|
||||||
@@ -6008,43 +6008,6 @@ is_wal_replay_paused(PGconn *conn, bool check_pending_wal)
|
|||||||
return is_paused;
|
return is_paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* repmgrd status functions */
|
|
||||||
|
|
||||||
CheckStatus
|
|
||||||
get_repmgrd_status(PGconn *conn)
|
|
||||||
{
|
|
||||||
PQExpBufferData query;
|
|
||||||
PGresult *res = NULL;
|
|
||||||
CheckStatus repmgrd_status = CHECK_STATUS_CRITICAL;
|
|
||||||
|
|
||||||
initPQExpBuffer(&query);
|
|
||||||
|
|
||||||
appendPQExpBufferStr(&query,
|
|
||||||
" SELECT "
|
|
||||||
" CASE "
|
|
||||||
" WHEN repmgr.repmgrd_is_running() "
|
|
||||||
" THEN "
|
|
||||||
" CASE "
|
|
||||||
" WHEN repmgr.repmgrd_is_paused() THEN 1 ELSE 0 "
|
|
||||||
" END "
|
|
||||||
" ELSE 2 "
|
|
||||||
" END AS repmgrd_status");
|
|
||||||
res = PQexec(conn, query.data);
|
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
|
||||||
{
|
|
||||||
log_db_error(conn, query.data, _("unable to execute repmgrd status query"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
repmgrd_status = atoi(PQgetvalue(res, 0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
termPQExpBuffer(&query);
|
|
||||||
PQclear(res);
|
|
||||||
return repmgrd_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* miscellaneous debugging functions */
|
/* miscellaneous debugging functions */
|
||||||
|
|
||||||
|
|||||||
@@ -602,9 +602,6 @@ int get_upstream_last_seen(PGconn *conn, t_server_type node_type);
|
|||||||
|
|
||||||
bool is_wal_replay_paused(PGconn *conn, bool check_pending_wal);
|
bool is_wal_replay_paused(PGconn *conn, bool check_pending_wal);
|
||||||
|
|
||||||
/* repmgrd status functions */
|
|
||||||
CheckStatus get_repmgrd_status(PGconn *conn);
|
|
||||||
|
|
||||||
/* miscellaneous debugging functions */
|
/* miscellaneous debugging functions */
|
||||||
const char *print_node_status(NodeStatus node_status);
|
const char *print_node_status(NodeStatus node_status);
|
||||||
const char *print_pqping_status(PGPing ping_status);
|
const char *print_pqping_status(PGPing ping_status);
|
||||||
|
|||||||
@@ -16,114 +16,17 @@
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<!-- remember to update the release date in ../repmgr_version.h.in -->
|
<!-- remember to update the release date in ../repmgr_version.h.in -->
|
||||||
<sect1 id="release-5.3.1">
|
<sect1 id="release-5.2.2">
|
||||||
<title id="release-current">Release 5.3.1</title>
|
<title id="release-current">Release 5.2.2</title>
|
||||||
<para><emphasis>Tue 15 February, 2022</emphasis></para>
|
<para><emphasis>??? ? ???, 2021</emphasis></para>
|
||||||
<para>
|
<para>
|
||||||
&repmgr; 5.3.1 is a minor release.
|
&repmgr; 5.2.2 is a minor release.
|
||||||
</para>
|
</para>
|
||||||
<sect2>
|
<sect2>
|
||||||
<title>Bug fixes</title>
|
<title>Bug fixes</title>
|
||||||
<para>
|
<para>
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Fix upgrade path from &repmgr; 4.2 and 4.3 to &repmgr; 5.3.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
&repmgrd;: ensure potentially open connections are closed.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In some cases, when recovering from degraded state in local node monitoring,
|
|
||||||
new connection was opened to the local node without closing
|
|
||||||
the old one, which will result in memory leakage.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
|
||||||
|
|
||||||
<sect1 id="release-5.3.0">
|
<itemizedlist>
|
||||||
<title>Release 5.3.0</title>
|
|
||||||
<para><emphasis>Tue 12 October, 2021</emphasis></para>
|
|
||||||
<para>
|
|
||||||
&repmgr; 5.3.0 is a major release.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This release provides support for <ulink url="https://www.postgresql.org/docs/14/release-14.html">PostgreSQL 14</ulink>,
|
|
||||||
released in September 2021.
|
|
||||||
</para>
|
|
||||||
<sect2>
|
|
||||||
<title>Improvements</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<link linkend="repmgr-standby-switchover"><command>repmgr standby switchover</command></link>:
|
|
||||||
Improve handling of node rejoin failure on the demotion candidate.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Previously &repmgr; did not check whether <command>repmgr node rejoin</command> actually
|
|
||||||
succeeded on the demotion candidate, and would always wait up to <varname>node_rejoin_timeout</varname>
|
|
||||||
seconds for it to attach to the promotion candidate, even if this would never happen.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This makes it easier to identify unexpected events during a switchover operation, such as
|
|
||||||
the demotion candidate being unexpectedly restarted by an external process.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Note that the output of the <link linkend="repmgr-node-rejoin"><command>repmgr node rejoin</command></link>
|
|
||||||
operation on the demotion candidate will now be logged to a temporary file on that node;
|
|
||||||
the location of the file will be reported in the error message, if one is emitted.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
&repmgrd;: at startup, if node record is marked as "inactive", attempt
|
|
||||||
to set it to "active".
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This behaviour can be overridden by setting the configuration parameter
|
|
||||||
<varname>repmgrd_exit_on_inactive_node</varname> to <literal>true</literal>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<command><link linkend="repmgr-node-rejoin">repmgr node rejoin</link></command>:
|
|
||||||
emit rejoin target note information as <literal>NOTICE</literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This makes it clearer what &repmgr; is trying to do.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<link linkend="repmgr-node-check">repmgr node check</link>:
|
|
||||||
option <option>--repmgrd</option> added to check &repmgrd;
|
|
||||||
status.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Add <literal>%p</literal> <link linkend="event-notifications">event notification parameter</link>
|
|
||||||
providing the node ID of the former primary for the <literal>repmgrd_failover_promote</literal> event.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2>
|
|
||||||
<title>Bug fixes</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<command><link linkend="repmgr-standby-clone">repmgr standby clone</link></command>:
|
<command><link linkend="repmgr-standby-clone">repmgr standby clone</link></command>:
|
||||||
@@ -135,24 +38,22 @@
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
&repmgrd;: rename internal shared library functions to minimize the
|
<command><link linkend="repmgr-node-rejoin">repmgr node rejoin</link></command>:
|
||||||
risk of clashes with other shared libraries.
|
emit rejoin target note information as <literal>NOTICE</literal>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
This does not affect user-facing SQL functions. However an upgrade
|
This makes it clearer what &repmgr; is trying to do.
|
||||||
of the installed extension version is required.
|
</para>
|
||||||
</para>
|
</listitem>
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
&repmgrd;: ensure short option <option>-s</option> is accepted.
|
&repmgrd;: ensure short option <option>-s</option> is accepted.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
|
||||||
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ conninfo='host=node1 user=repmgr dbname=repmgr connect_timeout=2'</programlistin
|
|||||||
|
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>repmgr.conf</primary>
|
<primary>repmgr.conf</primary>
|
||||||
<secondary>PostgreSQL major version upgrades</secondary>
|
<secondary>ostgreSQL major version upgrades</secondary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -95,8 +95,7 @@
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The following parameters are provided for a subset of event notifications; their meaning may
|
The following parameters are provided for a subset of event notifications:
|
||||||
change according to context:
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
@@ -109,9 +108,6 @@
|
|||||||
<para>
|
<para>
|
||||||
node ID of the demoted primary (<xref linkend="repmgr-standby-switchover"/> only)
|
node ID of the demoted primary (<xref linkend="repmgr-standby-switchover"/> only)
|
||||||
</para>
|
</para>
|
||||||
<para>
|
|
||||||
node ID of the former primary (<literal>repmgrd_failover_promote</literal> only)
|
|
||||||
</para>
|
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
@@ -137,7 +133,7 @@
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
The values provided for <literal>%c</literal> and <literal>%a</literal>
|
The values provided for <literal>%c</literal> and <literal>%a</literal>
|
||||||
may contain spaces, so should always be quoted.
|
will probably contain spaces, so should always be quoted.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -112,30 +112,16 @@
|
|||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
|
||||||
<entry>
|
|
||||||
&repmgr; 5.3
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
YES
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
<link linkend="release-current">&repmgrversion;</link> (&releasedate;)
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
9.4, 9.5, 9.6, 10, 11, 12, 13, 14
|
|
||||||
</entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<entry>
|
||||||
&repmgr; 5.2
|
&repmgr; 5.2
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
<entry>
|
||||||
NO
|
YES
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
<entry>
|
||||||
<link linkend="release-5.2.1">5.2.1</link> (2020-12-07)
|
<link linkend="release-current">&repmgrversion;</link> (&releasedate;)
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
<entry>
|
||||||
9.4, 9.5, 9.6, 10, 11, 12, 13
|
9.4, 9.5, 9.6, 10, 11, 12, 13
|
||||||
|
|||||||
@@ -125,29 +125,12 @@
|
|||||||
is correctly configured.
|
is correctly configured.
|
||||||
</simpara>
|
</simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>repmgrd</title>
|
|
||||||
<para>
|
|
||||||
A separate check is available to verify whether &repmgrd; is running,
|
|
||||||
This is not included in the general output, as this does not
|
|
||||||
per-se constitute a check of the node's replication status.
|
|
||||||
</para>
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<option>--repmgrd</option>: checks whether &repmgrd; is running.
|
|
||||||
If &repmgrd; is running but paused, status <literal>1</literal>
|
|
||||||
(<literal>WARNING</literal>) is returned.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Additional checks</title>
|
<title>Additional checks</title>
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
<abstract>
|
<abstract>
|
||||||
<para>
|
<para>
|
||||||
This is the official documentation of &repmgr; &repmgrversion; for
|
This is the official documentation of &repmgr; &repmgrversion; for
|
||||||
use with PostgreSQL 9.4 - PostgreSQL 14.
|
use with PostgreSQL 9.4 - PostgreSQL 13.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
&repmgr; is being continually developed and we strongly recommend using the
|
&repmgr; is being continually developed and we strongly recommend using the
|
||||||
|
|||||||
@@ -485,32 +485,6 @@
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
|
|
||||||
<term><option>repmgrd_exit_on_inactive_node</option></term>
|
|
||||||
<listitem>
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgrd_exit_on_inactive_node</primary>
|
|
||||||
</indexterm>
|
|
||||||
<para>
|
|
||||||
This parameter is available in &repmgr; 5.3 and later.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If a node was marked as inactive but is running, and this option is set to
|
|
||||||
<literal>true</literal>, &repmgrd; will abort on startup.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
By default, <option>repmgrd_exit_on_inactive_node</option> is set
|
|
||||||
to <literal>false</literal>, in which case &repmgrd; will set the
|
|
||||||
node record to active on startup.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Setting this parameter to <literal>true</literal> causes &repmgrd;
|
|
||||||
to behave in the same way it did in &repmgr; 5.2 and earlier.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -1079,29 +1053,6 @@ REPMGRD_OPTS="--daemonize=false"
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="repmgrd-daemon-monitoring">
|
|
||||||
<title>repmgrd daemon monitoring</title>
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgrd</primary>
|
|
||||||
<secondary>monitoring</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<indexterm>
|
|
||||||
<primary>monitoring</primary>
|
|
||||||
<secondary>repmgrd</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The command <command><link linkend="repmgr-service-status">repmgr service status</link></command>
|
|
||||||
provides an overview of the &repmgrd; daemon status (including pause status)
|
|
||||||
on all nodes in the cluster.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
From &repmgr; 5.3, <command><link linkend="repmgr-node-check">repmgr node check --repmgrd</link></command>
|
|
||||||
can be used to check the status of &repmgrd; (including pause status)
|
|
||||||
on the local node.
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="repmgrd-connection-settings">
|
<sect1 id="repmgrd-connection-settings">
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||||
\echo Use "ALTER EXTENSION repmgr UPDATE" to load this file. \quit
|
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
||||||
|
|
||||||
-- This script is intentionally empty and exists to skip the CREATE FUNCTION
|
CREATE FUNCTION set_upstream_last_seen()
|
||||||
-- commands contained in the 4.2--4.3 and 4.3--4.4 extension upgrade scripts,
|
RETURNS VOID
|
||||||
-- which reference C functions which no longer exist in 5.3 and later.
|
AS 'MODULE_PATHNAME', 'set_upstream_last_seen'
|
||||||
--
|
LANGUAGE C STRICT;
|
||||||
-- These functions will be explicitly created in the 5.2--5.3 extension
|
|
||||||
-- upgrade step with the correct C function references.
|
|
||||||
|
|
||||||
|
CREATE FUNCTION get_upstream_last_seen()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_upstream_last_seen'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_wal_receiver_pid()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_wal_receiver_pid'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||||
\echo Use "ALTER EXTENSION repmgr UPDATE" to load this file. \quit
|
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
||||||
|
|
||||||
-- This script is intentionally empty and exists to skip the CREATE FUNCTION
|
DROP FUNCTION set_upstream_last_seen();
|
||||||
-- commands contained in the 4.3--4.4 extension upgrade script, which reference
|
|
||||||
-- C functions which no longer exist in 5.3 and later.
|
CREATE FUNCTION set_upstream_last_seen(INT)
|
||||||
--
|
RETURNS VOID
|
||||||
-- These functions will be explicitly created in the 5.2--5.3 extension
|
AS 'MODULE_PATHNAME', 'set_upstream_last_seen'
|
||||||
-- upgrade step with the correct C function references.
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_upstream_node_id()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_upstream_node_id'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION set_upstream_node_id(INT)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'set_upstream_node_id'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
|
||||||
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION set_local_node_id(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION repmgr.get_local_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION standby_set_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_standby_set_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION standby_get_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_standby_get_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION set_upstream_last_seen(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_last_seen'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION get_upstream_last_seen()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_last_seen'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION get_upstream_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION set_upstream_node_id(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
/* failover functions */
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION notify_follow_primary(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_notify_follow_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION get_new_primary()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_new_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION reset_voting_status()
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_reset_voting_status'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION get_wal_receiver_pid()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_wal_receiver_pid'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
192
repmgr--5.3.sql
192
repmgr--5.3.sql
@@ -1,192 +0,0 @@
|
|||||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
|
||||||
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
|
||||||
|
|
||||||
CREATE TABLE repmgr.nodes (
|
|
||||||
node_id INTEGER PRIMARY KEY,
|
|
||||||
upstream_node_id INTEGER NULL REFERENCES nodes (node_id) DEFERRABLE,
|
|
||||||
active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
||||||
node_name TEXT NOT NULL,
|
|
||||||
type TEXT NOT NULL CHECK (type IN('primary','standby','witness','bdr')),
|
|
||||||
location TEXT NOT NULL DEFAULT 'default',
|
|
||||||
priority INT NOT NULL DEFAULT 100,
|
|
||||||
conninfo TEXT NOT NULL,
|
|
||||||
repluser VARCHAR(63) NOT NULL,
|
|
||||||
slot_name TEXT NULL,
|
|
||||||
config_file TEXT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
SELECT pg_catalog.pg_extension_config_dump('repmgr.nodes', '');
|
|
||||||
|
|
||||||
CREATE TABLE repmgr.events (
|
|
||||||
node_id INTEGER NOT NULL,
|
|
||||||
event TEXT NOT NULL,
|
|
||||||
successful BOOLEAN NOT NULL DEFAULT TRUE,
|
|
||||||
event_timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
details TEXT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
SELECT pg_catalog.pg_extension_config_dump('repmgr.events', '');
|
|
||||||
|
|
||||||
CREATE TABLE repmgr.monitoring_history (
|
|
||||||
primary_node_id INTEGER NOT NULL,
|
|
||||||
standby_node_id INTEGER NOT NULL,
|
|
||||||
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
||||||
last_apply_time TIMESTAMP WITH TIME ZONE,
|
|
||||||
last_wal_primary_location PG_LSN NOT NULL,
|
|
||||||
last_wal_standby_location PG_LSN,
|
|
||||||
replication_lag BIGINT NOT NULL,
|
|
||||||
apply_lag BIGINT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX idx_monitoring_history_time
|
|
||||||
ON repmgr.monitoring_history (last_monitor_time, standby_node_id);
|
|
||||||
|
|
||||||
SELECT pg_catalog.pg_extension_config_dump('repmgr.monitoring_history', '');
|
|
||||||
|
|
||||||
CREATE VIEW repmgr.show_nodes AS
|
|
||||||
SELECT n.node_id,
|
|
||||||
n.node_name,
|
|
||||||
n.active,
|
|
||||||
n.upstream_node_id,
|
|
||||||
un.node_name AS upstream_node_name,
|
|
||||||
n.type,
|
|
||||||
n.priority,
|
|
||||||
n.conninfo
|
|
||||||
FROM repmgr.nodes n
|
|
||||||
LEFT JOIN repmgr.nodes un
|
|
||||||
ON un.node_id = n.upstream_node_id;
|
|
||||||
|
|
||||||
CREATE TABLE repmgr.voting_term (
|
|
||||||
term INT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX voting_term_restrict
|
|
||||||
ON repmgr.voting_term ((TRUE));
|
|
||||||
|
|
||||||
CREATE RULE voting_term_delete AS
|
|
||||||
ON DELETE TO repmgr.voting_term
|
|
||||||
DO INSTEAD NOTHING;
|
|
||||||
|
|
||||||
|
|
||||||
/* ================= */
|
|
||||||
/* repmgrd functions */
|
|
||||||
/* ================= */
|
|
||||||
|
|
||||||
/* monitoring functions */
|
|
||||||
|
|
||||||
CREATE FUNCTION set_local_node_id(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_local_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION standby_set_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_standby_set_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION standby_get_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_standby_get_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_upstream_last_seen(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_last_seen'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_upstream_last_seen()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_last_seen'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_upstream_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_upstream_node_id(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
/* failover functions */
|
|
||||||
|
|
||||||
CREATE FUNCTION notify_follow_primary(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_notify_follow_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_new_primary()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_new_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION reset_voting_status()
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_reset_voting_status'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_repmgrd_pid()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'get_repmgrd_pid'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_repmgrd_pidfile()
|
|
||||||
RETURNS TEXT
|
|
||||||
AS 'MODULE_PATHNAME', 'get_repmgrd_pidfile'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_repmgrd_pid(INT, TEXT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'set_repmgrd_pid'
|
|
||||||
LANGUAGE C CALLED ON NULL INPUT;
|
|
||||||
|
|
||||||
CREATE FUNCTION repmgrd_is_running()
|
|
||||||
RETURNS BOOL
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgrd_is_running'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION repmgrd_pause(BOOL)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgrd_pause'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION repmgrd_is_paused()
|
|
||||||
RETURNS BOOL
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgrd_is_paused'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_wal_receiver_pid()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_wal_receiver_pid'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* views */
|
|
||||||
|
|
||||||
CREATE VIEW repmgr.replication_status AS
|
|
||||||
SELECT m.primary_node_id, m.standby_node_id, n.node_name AS standby_name,
|
|
||||||
n.type AS node_type, n.active, last_monitor_time,
|
|
||||||
CASE WHEN n.type='standby' THEN m.last_wal_primary_location ELSE NULL END AS last_wal_primary_location,
|
|
||||||
m.last_wal_standby_location,
|
|
||||||
CASE WHEN n.type='standby' THEN pg_catalog.pg_size_pretty(m.replication_lag) ELSE NULL END AS replication_lag,
|
|
||||||
CASE WHEN n.type='standby' THEN
|
|
||||||
CASE WHEN replication_lag > 0 THEN age(now(), m.last_apply_time) ELSE '0'::INTERVAL END
|
|
||||||
ELSE NULL
|
|
||||||
END AS replication_time_lag,
|
|
||||||
CASE WHEN n.type='standby' THEN pg_catalog.pg_size_pretty(m.apply_lag) ELSE NULL END AS apply_lag,
|
|
||||||
AGE(NOW(), CASE WHEN pg_catalog.pg_is_in_recovery() THEN repmgr.standby_get_last_updated() ELSE m.last_monitor_time END) AS communication_time_lag
|
|
||||||
FROM repmgr.monitoring_history m
|
|
||||||
JOIN repmgr.nodes n ON m.standby_node_id = n.node_id
|
|
||||||
WHERE (m.standby_node_id, m.last_monitor_time) IN (
|
|
||||||
SELECT m1.standby_node_id, MAX(m1.last_monitor_time)
|
|
||||||
FROM repmgr.monitoring_history m1 GROUP BY 1
|
|
||||||
);
|
|
||||||
|
|
||||||
@@ -1,245 +0,0 @@
|
|||||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
|
||||||
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
|
||||||
|
|
||||||
-- extract the current schema name
|
|
||||||
-- NOTE: this assumes there will be only one schema matching 'repmgr_%';
|
|
||||||
-- user is responsible for ensuring this is the case
|
|
||||||
|
|
||||||
CREATE TEMPORARY TABLE repmgr_old_schema (schema_name TEXT);
|
|
||||||
INSERT INTO repmgr_old_schema (schema_name)
|
|
||||||
SELECT nspname AS schema_name
|
|
||||||
FROM pg_catalog.pg_namespace
|
|
||||||
WHERE nspname LIKE 'repmgr_%'
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
-- move old objects into new schema
|
|
||||||
DO $repmgr$
|
|
||||||
DECLARE
|
|
||||||
old_schema TEXT;
|
|
||||||
BEGIN
|
|
||||||
SELECT schema_name FROM repmgr_old_schema
|
|
||||||
INTO old_schema;
|
|
||||||
EXECUTE format('ALTER TABLE %I.repl_nodes SET SCHEMA repmgr', old_schema);
|
|
||||||
EXECUTE format('ALTER TABLE %I.repl_events SET SCHEMA repmgr', old_schema);
|
|
||||||
EXECUTE format('ALTER TABLE %I.repl_monitor SET SCHEMA repmgr', old_schema);
|
|
||||||
EXECUTE format('DROP VIEW IF EXISTS %I.repl_show_nodes', old_schema);
|
|
||||||
EXECUTE format('DROP VIEW IF EXISTS %I.repl_status', old_schema);
|
|
||||||
END$repmgr$;
|
|
||||||
|
|
||||||
-- convert "repmgr_$cluster.repl_nodes" to "repmgr.nodes"
|
|
||||||
CREATE TABLE repmgr.nodes (
|
|
||||||
node_id INTEGER PRIMARY KEY,
|
|
||||||
upstream_node_id INTEGER NULL REFERENCES repmgr.nodes (node_id) DEFERRABLE,
|
|
||||||
active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
||||||
node_name TEXT NOT NULL,
|
|
||||||
type TEXT NOT NULL CHECK (type IN('primary','standby','witness','bdr')),
|
|
||||||
location TEXT NOT NULL DEFAULT 'default',
|
|
||||||
priority INT NOT NULL DEFAULT 100,
|
|
||||||
conninfo TEXT NOT NULL,
|
|
||||||
repluser VARCHAR(63) NOT NULL,
|
|
||||||
slot_name TEXT NULL,
|
|
||||||
config_file TEXT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO repmgr.nodes
|
|
||||||
(node_id, upstream_node_id, active, node_name, type, location, priority, conninfo, repluser, slot_name, config_file)
|
|
||||||
SELECT id, upstream_node_id, active, name,
|
|
||||||
CASE WHEN type = 'master' THEN 'primary' ELSE type END,
|
|
||||||
'default', priority, conninfo, 'unknown', slot_name, 'unknown'
|
|
||||||
FROM repmgr.repl_nodes
|
|
||||||
ORDER BY id;
|
|
||||||
|
|
||||||
|
|
||||||
-- convert "repmgr_$cluster.repl_event" to "event"
|
|
||||||
|
|
||||||
CREATE TABLE repmgr.events (
|
|
||||||
node_id INTEGER NOT NULL,
|
|
||||||
event TEXT NOT NULL,
|
|
||||||
successful BOOLEAN NOT NULL DEFAULT TRUE,
|
|
||||||
event_timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
details TEXT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO repmgr.events
|
|
||||||
(node_id, event, successful, event_timestamp, details)
|
|
||||||
SELECT node_id, event, successful, event_timestamp, details
|
|
||||||
FROM repmgr.repl_events;
|
|
||||||
|
|
||||||
-- create new table "repmgr.voting_term"
|
|
||||||
CREATE TABLE repmgr.voting_term (
|
|
||||||
term INT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX voting_term_restrict
|
|
||||||
ON repmgr.voting_term ((TRUE));
|
|
||||||
|
|
||||||
CREATE RULE voting_term_delete AS
|
|
||||||
ON DELETE TO repmgr.voting_term
|
|
||||||
DO INSTEAD NOTHING;
|
|
||||||
|
|
||||||
INSERT INTO repmgr.voting_term (term) VALUES (1);
|
|
||||||
|
|
||||||
-- convert "repmgr_$cluster.repl_monitor" to "monitoring_history"
|
|
||||||
|
|
||||||
CREATE TABLE repmgr.monitoring_history (
|
|
||||||
primary_node_id INTEGER NOT NULL,
|
|
||||||
standby_node_id INTEGER NOT NULL,
|
|
||||||
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
||||||
last_apply_time TIMESTAMP WITH TIME ZONE,
|
|
||||||
last_wal_primary_location PG_LSN NOT NULL,
|
|
||||||
last_wal_standby_location PG_LSN,
|
|
||||||
replication_lag BIGINT NOT NULL,
|
|
||||||
apply_lag BIGINT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO repmgr.monitoring_history
|
|
||||||
(primary_node_id, standby_node_id, last_monitor_time, last_apply_time, last_wal_primary_location, last_wal_standby_location, replication_lag, apply_lag)
|
|
||||||
SELECT primary_node, standby_node, last_monitor_time, last_apply_time, last_wal_primary_location::pg_lsn, last_wal_standby_location::pg_lsn, replication_lag, apply_lag
|
|
||||||
FROM repmgr.repl_monitor;
|
|
||||||
|
|
||||||
CREATE INDEX idx_monitoring_history_time
|
|
||||||
ON repmgr.monitoring_history (last_monitor_time, standby_node_id);
|
|
||||||
|
|
||||||
CREATE VIEW repmgr.show_nodes AS
|
|
||||||
SELECT n.node_id,
|
|
||||||
n.node_name,
|
|
||||||
n.active,
|
|
||||||
n.upstream_node_id,
|
|
||||||
un.node_name AS upstream_node_name,
|
|
||||||
n.type,
|
|
||||||
n.priority,
|
|
||||||
n.conninfo
|
|
||||||
FROM repmgr.nodes n
|
|
||||||
LEFT JOIN repmgr.nodes un
|
|
||||||
ON un.node_id = n.upstream_node_id;
|
|
||||||
|
|
||||||
|
|
||||||
/* ================= */
|
|
||||||
/* repmgrd functions */
|
|
||||||
/* ================= */
|
|
||||||
|
|
||||||
/* monitoring functions */
|
|
||||||
|
|
||||||
CREATE FUNCTION set_local_node_id(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_local_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION standby_set_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_standby_set_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION standby_get_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_standby_get_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_upstream_last_seen(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_last_seen'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_upstream_last_seen()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_last_seen'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_upstream_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_upstream_node_id(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
/* failover functions */
|
|
||||||
|
|
||||||
CREATE FUNCTION notify_follow_primary(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_notify_follow_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_new_primary()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_new_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION reset_voting_status()
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_reset_voting_status'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_repmgrd_pid()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'get_repmgrd_pid'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_repmgrd_pidfile()
|
|
||||||
RETURNS TEXT
|
|
||||||
AS 'MODULE_PATHNAME', 'get_repmgrd_pidfile'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_repmgrd_pid(INT, TEXT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'set_repmgrd_pid'
|
|
||||||
LANGUAGE C CALLED ON NULL INPUT;
|
|
||||||
|
|
||||||
CREATE FUNCTION repmgrd_is_running()
|
|
||||||
RETURNS BOOL
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgrd_is_running'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION repmgrd_pause(BOOL)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgrd_pause'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION repmgrd_is_paused()
|
|
||||||
RETURNS BOOL
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgrd_is_paused'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_wal_receiver_pid()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_wal_receiver_pid'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
|
|
||||||
/* views */
|
|
||||||
|
|
||||||
CREATE VIEW repmgr.replication_status AS
|
|
||||||
SELECT m.primary_node_id, m.standby_node_id, n.node_name AS standby_name,
|
|
||||||
n.type AS node_type, n.active, last_monitor_time,
|
|
||||||
CASE WHEN n.type='standby' THEN m.last_wal_primary_location ELSE NULL END AS last_wal_primary_location,
|
|
||||||
m.last_wal_standby_location,
|
|
||||||
CASE WHEN n.type='standby' THEN pg_catalog.pg_size_pretty(m.replication_lag) ELSE NULL END AS replication_lag,
|
|
||||||
CASE WHEN n.type='standby' THEN
|
|
||||||
CASE WHEN replication_lag > 0 THEN age(now(), m.last_apply_time) ELSE '0'::INTERVAL END
|
|
||||||
ELSE NULL
|
|
||||||
END AS replication_time_lag,
|
|
||||||
CASE WHEN n.type='standby' THEN pg_catalog.pg_size_pretty(m.apply_lag) ELSE NULL END AS apply_lag,
|
|
||||||
AGE(NOW(), CASE WHEN pg_catalog.pg_is_in_recovery() THEN repmgr.standby_get_last_updated() ELSE m.last_monitor_time END) AS communication_time_lag
|
|
||||||
FROM repmgr.monitoring_history m
|
|
||||||
JOIN repmgr.nodes n ON m.standby_node_id = n.node_id
|
|
||||||
WHERE (m.standby_node_id, m.last_monitor_time) IN (
|
|
||||||
SELECT m1.standby_node_id, MAX(m1.last_monitor_time)
|
|
||||||
FROM repmgr.monitoring_history m1 GROUP BY 1
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* drop old tables */
|
|
||||||
DROP TABLE repmgr.repl_nodes;
|
|
||||||
DROP TABLE repmgr.repl_monitor;
|
|
||||||
DROP TABLE repmgr.repl_events;
|
|
||||||
|
|
||||||
-- remove temporary table
|
|
||||||
DROP TABLE repmgr_old_schema;
|
|
||||||
@@ -35,7 +35,6 @@
|
|||||||
static bool copy_file(const char *src_file, const char *dest_file);
|
static bool copy_file(const char *src_file, const char *dest_file);
|
||||||
static void format_archive_dir(PQExpBufferData *archive_dir);
|
static void format_archive_dir(PQExpBufferData *archive_dir);
|
||||||
static t_server_action parse_server_action(const char *action);
|
static t_server_action parse_server_action(const char *action);
|
||||||
static const char *output_repmgrd_status(CheckStatus status);
|
|
||||||
|
|
||||||
static void exit_optformat_error(const char *error, int errcode);
|
static void exit_optformat_error(const char *error, int errcode);
|
||||||
|
|
||||||
@@ -53,11 +52,9 @@ static CheckStatus do_node_check_role(PGconn *conn, OutputMode mode, t_node_info
|
|||||||
static CheckStatus do_node_check_slots(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
static CheckStatus do_node_check_slots(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
||||||
static CheckStatus do_node_check_missing_slots(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
static CheckStatus do_node_check_missing_slots(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
||||||
static CheckStatus do_node_check_data_directory(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
static CheckStatus do_node_check_data_directory(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
||||||
static CheckStatus do_node_check_repmgrd(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
|
||||||
static CheckStatus do_node_check_replication_config_owner(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
static CheckStatus do_node_check_replication_config_owner(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
||||||
static CheckStatus do_node_check_db_connection(PGconn *conn, OutputMode mode);
|
static CheckStatus do_node_check_db_connection(PGconn *conn, OutputMode mode);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NODE STATUS
|
* NODE STATUS
|
||||||
*
|
*
|
||||||
@@ -944,16 +941,6 @@ do_node_check(void)
|
|||||||
exit(return_code);
|
exit(return_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtime_options.repmgrd == true)
|
|
||||||
{
|
|
||||||
return_code = do_node_check_repmgrd(conn,
|
|
||||||
runtime_options.output_mode,
|
|
||||||
&node_info,
|
|
||||||
NULL);
|
|
||||||
PQfinish(conn);
|
|
||||||
exit(return_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runtime_options.replication_config_owner == true)
|
if (runtime_options.replication_config_owner == true)
|
||||||
{
|
{
|
||||||
return_code = do_node_check_replication_config_owner(conn,
|
return_code = do_node_check_replication_config_owner(conn,
|
||||||
@@ -2037,6 +2024,7 @@ do_node_check_missing_slots(PGconn *conn, OutputMode mode, t_node_info *node_inf
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CheckStatus
|
CheckStatus
|
||||||
do_node_check_data_directory(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output)
|
do_node_check_data_directory(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output)
|
||||||
{
|
{
|
||||||
@@ -2171,53 +2159,6 @@ do_node_check_data_directory(PGconn *conn, OutputMode mode, t_node_info *node_in
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckStatus
|
|
||||||
do_node_check_repmgrd(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output)
|
|
||||||
{
|
|
||||||
CheckStatus status = CHECK_STATUS_OK;
|
|
||||||
|
|
||||||
if (mode == OM_CSV && list_output == NULL)
|
|
||||||
{
|
|
||||||
log_error(_("--csv output not provided with --repmgrd option"));
|
|
||||||
PQfinish(conn);
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
|
|
||||||
status = get_repmgrd_status(conn);
|
|
||||||
switch (mode)
|
|
||||||
{
|
|
||||||
case OM_OPTFORMAT:
|
|
||||||
printf("--repmgrd=%s\n",
|
|
||||||
output_check_status(status));
|
|
||||||
break;
|
|
||||||
case OM_NAGIOS:
|
|
||||||
printf("REPMGRD %s: %s\n",
|
|
||||||
output_check_status(status),
|
|
||||||
output_repmgrd_status(status));
|
|
||||||
|
|
||||||
break;
|
|
||||||
case OM_CSV:
|
|
||||||
case OM_TEXT:
|
|
||||||
if (list_output != NULL)
|
|
||||||
{
|
|
||||||
check_status_list_set(list_output,
|
|
||||||
"repmgrd",
|
|
||||||
status,
|
|
||||||
output_repmgrd_status(status));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("%s (%s)\n",
|
|
||||||
output_check_status(status),
|
|
||||||
output_repmgrd_status(status));
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is not included in the general list output
|
* This is not included in the general list output
|
||||||
*/
|
*/
|
||||||
@@ -2879,8 +2820,7 @@ do_node_rejoin(void)
|
|||||||
log_notice(_("temporarily removing \"standby.signal\""));
|
log_notice(_("temporarily removing \"standby.signal\""));
|
||||||
log_detail(_("this is required so pg_rewind can fix the unclean shutdown"));
|
log_detail(_("this is required so pg_rewind can fix the unclean shutdown"));
|
||||||
|
|
||||||
make_standby_signal_path(config_file_options.data_directory,
|
make_standby_signal_path(standby_signal_file_path);
|
||||||
standby_signal_file_path);
|
|
||||||
|
|
||||||
if (unlink(standby_signal_file_path) < 0 && errno != ENOENT)
|
if (unlink(standby_signal_file_path) < 0 && errno != ENOENT)
|
||||||
{
|
{
|
||||||
@@ -2905,7 +2845,7 @@ do_node_rejoin(void)
|
|||||||
* of whether the pg_rewind operation failed.
|
* of whether the pg_rewind operation failed.
|
||||||
*/
|
*/
|
||||||
log_notice(_("recreating \"standby.signal\""));
|
log_notice(_("recreating \"standby.signal\""));
|
||||||
write_standby_signal(config_file_options.data_directory);
|
write_standby_signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == false)
|
if (ret == false)
|
||||||
@@ -3629,25 +3569,6 @@ copy_file(const char *src_file, const char *dest_file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
output_repmgrd_status(CheckStatus status)
|
|
||||||
{
|
|
||||||
switch (status)
|
|
||||||
{
|
|
||||||
case CHECK_STATUS_OK:
|
|
||||||
return "repmgrd running";
|
|
||||||
case CHECK_STATUS_WARNING:
|
|
||||||
return "repmgrd running but paused";
|
|
||||||
case CHECK_STATUS_CRITICAL:
|
|
||||||
return "repmgrd not running";
|
|
||||||
case CHECK_STATUS_UNKNOWN:
|
|
||||||
return "repmgrd status unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
do_node_help(void)
|
do_node_help(void)
|
||||||
{
|
{
|
||||||
@@ -3690,7 +3611,6 @@ do_node_help(void)
|
|||||||
printf(_(" --role check node has expected role\n"));
|
printf(_(" --role check node has expected role\n"));
|
||||||
printf(_(" --slots check for inactive replication slots\n"));
|
printf(_(" --slots check for inactive replication slots\n"));
|
||||||
printf(_(" --missing-slots check for missing replication slots\n"));
|
printf(_(" --missing-slots check for missing replication slots\n"));
|
||||||
printf(_(" --repmgrd check if repmgrd is running\n"));
|
|
||||||
printf(_(" --data-directory-config check repmgr's data directory configuration\n"));
|
printf(_(" --data-directory-config check repmgr's data directory configuration\n"));
|
||||||
|
|
||||||
puts("");
|
puts("");
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "repmgr.h"
|
#include "repmgr.h"
|
||||||
#include "dirutil.h"
|
#include "dirutil.h"
|
||||||
@@ -174,6 +173,21 @@ do_standby_clone(void)
|
|||||||
|
|
||||||
initialize_conninfo_params(&recovery_conninfo, false);
|
initialize_conninfo_params(&recovery_conninfo, false);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* --replication-conf-only provided - we'll handle that separately
|
||||||
|
*/
|
||||||
|
if (runtime_options.replication_conf_only == true)
|
||||||
|
{
|
||||||
|
return _do_create_replication_conf();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* conninfo params for the actual upstream node (which might be different
|
||||||
|
* to the node we're cloning from) to write to recovery.conf
|
||||||
|
*/
|
||||||
|
|
||||||
|
mode = get_standby_clone_mode();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the provided data directory; if a configuration file was provided,
|
* Copy the provided data directory; if a configuration file was provided,
|
||||||
* use the (mandatory) value from that; if -D/--pgdata was provided, use
|
* use the (mandatory) value from that; if -D/--pgdata was provided, use
|
||||||
@@ -201,19 +215,6 @@ do_standby_clone(void)
|
|||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* --replication-conf-only provided - we'll handle that separately
|
|
||||||
*/
|
|
||||||
if (runtime_options.replication_conf_only == true)
|
|
||||||
{
|
|
||||||
return _do_create_replication_conf();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* conninfo params for the actual upstream node (which might be different
|
|
||||||
* to the node we're cloning from) to write to recovery.conf
|
|
||||||
*/
|
|
||||||
mode = get_standby_clone_mode();
|
|
||||||
|
|
||||||
if (mode == barman)
|
if (mode == barman)
|
||||||
{
|
{
|
||||||
@@ -669,15 +670,6 @@ do_standby_clone(void)
|
|||||||
log_hint(_("consider using the -c/--fast-checkpoint option"));
|
log_hint(_("consider using the -c/--fast-checkpoint option"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == pg_basebackup)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* In --dry-run mode, this will just output the pg_basebackup command which
|
|
||||||
* would be executed.
|
|
||||||
*/
|
|
||||||
run_basebackup(&local_node_record);
|
|
||||||
}
|
|
||||||
|
|
||||||
PQfinish(source_conn);
|
PQfinish(source_conn);
|
||||||
|
|
||||||
log_info(_("all prerequisites for \"standby clone\" are met"));
|
log_info(_("all prerequisites for \"standby clone\" are met"));
|
||||||
@@ -1546,7 +1538,7 @@ _do_create_replication_conf(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (write_standby_signal(local_data_directory) == false)
|
if (write_standby_signal() == false)
|
||||||
{
|
{
|
||||||
log_error(_("unable to write \"standby.signal\" file"));
|
log_error(_("unable to write \"standby.signal\" file"));
|
||||||
}
|
}
|
||||||
@@ -2007,7 +1999,7 @@ do_standby_register(void)
|
|||||||
/* only do this if record does not exist */
|
/* only do this if record does not exist */
|
||||||
if (record_status != RECORD_FOUND)
|
if (record_status != RECORD_FOUND)
|
||||||
{
|
{
|
||||||
log_warning(_("--upstream-node-id not supplied, assuming upstream node is primary (node ID: %i)"),
|
log_warning(_("--upstream-node-id not supplied, assuming upstream node is primary (node ID %i)"),
|
||||||
primary_node_id);
|
primary_node_id);
|
||||||
|
|
||||||
/* check our standby is connected */
|
/* check our standby is connected */
|
||||||
@@ -3652,9 +3644,8 @@ do_standby_switchover(void)
|
|||||||
PQExpBufferData remote_command_str;
|
PQExpBufferData remote_command_str;
|
||||||
PQExpBufferData command_output;
|
PQExpBufferData command_output;
|
||||||
PQExpBufferData node_rejoin_options;
|
PQExpBufferData node_rejoin_options;
|
||||||
PQExpBufferData logmsg;
|
PQExpBufferData errmsg;
|
||||||
PQExpBufferData detailmsg;
|
PQExpBufferData detailmsg;
|
||||||
PQExpBufferData event_details;
|
|
||||||
|
|
||||||
int r,
|
int r,
|
||||||
i;
|
i;
|
||||||
@@ -3671,9 +3662,6 @@ do_standby_switchover(void)
|
|||||||
/* store list of configuration files on the demotion candidate */
|
/* store list of configuration files on the demotion candidate */
|
||||||
KeyValueList remote_config_files = {NULL, NULL};
|
KeyValueList remote_config_files = {NULL, NULL};
|
||||||
|
|
||||||
/* temporary log file for "repmgr node rejoin" on the demotion candidate */
|
|
||||||
char node_rejoin_log[MAXPGPATH] = "";
|
|
||||||
|
|
||||||
NodeInfoList sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
NodeInfoList sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
SiblingNodeStats sibling_nodes_stats = T_SIBLING_NODES_STATS_INITIALIZER;
|
SiblingNodeStats sibling_nodes_stats = T_SIBLING_NODES_STATS_INITIALIZER;
|
||||||
|
|
||||||
@@ -3816,24 +3804,24 @@ do_standby_switchover(void)
|
|||||||
* the demotion candidate as the rejoin will fail if we are unable to to write to that.
|
* the demotion candidate as the rejoin will fail if we are unable to to write to that.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
initPQExpBuffer(&logmsg);
|
initPQExpBuffer(&errmsg);
|
||||||
initPQExpBuffer(&detailmsg);
|
initPQExpBuffer(&detailmsg);
|
||||||
|
|
||||||
if (check_replication_config_owner(PQserverVersion(local_conn),
|
if (check_replication_config_owner(PQserverVersion(local_conn),
|
||||||
config_file_options.data_directory,
|
config_file_options.data_directory,
|
||||||
&logmsg, &detailmsg) == false)
|
&errmsg, &detailmsg) == false)
|
||||||
{
|
{
|
||||||
log_error("%s", logmsg.data);
|
log_error("%s", errmsg.data);
|
||||||
log_detail("%s", detailmsg.data);
|
log_detail("%s", detailmsg.data);
|
||||||
|
|
||||||
termPQExpBuffer(&logmsg);
|
termPQExpBuffer(&errmsg);
|
||||||
termPQExpBuffer(&detailmsg);
|
termPQExpBuffer(&detailmsg);
|
||||||
|
|
||||||
PQfinish(local_conn);
|
PQfinish(local_conn);
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
termPQExpBuffer(&logmsg);
|
termPQExpBuffer(&errmsg);
|
||||||
termPQExpBuffer(&detailmsg);
|
termPQExpBuffer(&detailmsg);
|
||||||
|
|
||||||
/* check remote server connection and retrieve its record */
|
/* check remote server connection and retrieve its record */
|
||||||
@@ -4781,7 +4769,6 @@ do_standby_switchover(void)
|
|||||||
|
|
||||||
repmgrd_info = (RepmgrdInfo **) pg_malloc0(sizeof(RepmgrdInfo *) * all_nodes.node_count);
|
repmgrd_info = (RepmgrdInfo **) pg_malloc0(sizeof(RepmgrdInfo *) * all_nodes.node_count);
|
||||||
|
|
||||||
log_notice(_("attempting to pause repmgrd on %i nodes"), all_nodes.node_count);
|
|
||||||
for (cell = all_nodes.head; cell; cell = cell->next)
|
for (cell = all_nodes.head; cell; cell = cell->next)
|
||||||
{
|
{
|
||||||
repmgrd_info[i] = pg_malloc0(sizeof(RepmgrdInfo));
|
repmgrd_info[i] = pg_malloc0(sizeof(RepmgrdInfo));
|
||||||
@@ -4810,7 +4797,7 @@ do_standby_switchover(void)
|
|||||||
unreachable_node_count++;
|
unreachable_node_count++;
|
||||||
|
|
||||||
item_list_append_format(&repmgrd_connection_errors,
|
item_list_append_format(&repmgrd_connection_errors,
|
||||||
_("unable to connect to node \"%s\" (ID: %i):\n%s"),
|
_("unable to connect to node \"%s\" (ID %i):\n%s"),
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id,
|
cell->node_info->node_id,
|
||||||
PQerrorMessage(cell->node_info->conn));
|
PQerrorMessage(cell->node_info->conn));
|
||||||
@@ -4841,9 +4828,8 @@ do_standby_switchover(void)
|
|||||||
|
|
||||||
initPQExpBuffer(&msg);
|
initPQExpBuffer(&msg);
|
||||||
appendPQExpBuffer(&msg,
|
appendPQExpBuffer(&msg,
|
||||||
_("unable to connect to %i of %i node(s), unable to pause all repmgrd instances"),
|
_("unable to connect to %i node(s), unable to pause all repmgrd instances"),
|
||||||
unreachable_node_count,
|
unreachable_node_count);
|
||||||
all_nodes.node_count);
|
|
||||||
|
|
||||||
initPQExpBuffer(&detail);
|
initPQExpBuffer(&detail);
|
||||||
|
|
||||||
@@ -4894,7 +4880,7 @@ do_standby_switchover(void)
|
|||||||
*/
|
*/
|
||||||
if (repmgrd_info[i]->pg_running == false)
|
if (repmgrd_info[i]->pg_running == false)
|
||||||
{
|
{
|
||||||
log_warning(_("node \"%s\" (ID: %i) unreachable, unable to pause repmgrd"),
|
log_warning(_("node \"%s\" (ID %i) unreachable, unable to pause repmgrd"),
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
i++;
|
i++;
|
||||||
@@ -4907,7 +4893,7 @@ do_standby_switchover(void)
|
|||||||
*/
|
*/
|
||||||
if (repmgrd_info[i]->running == false)
|
if (repmgrd_info[i]->running == false)
|
||||||
{
|
{
|
||||||
log_notice(_("repmgrd not running on node \"%s\" (ID: %i), not pausing"),
|
log_warning(_("repmgrd not running on node \"%s\" (ID %i)"),
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
i++;
|
i++;
|
||||||
@@ -4928,14 +4914,14 @@ do_standby_switchover(void)
|
|||||||
|
|
||||||
if (runtime_options.dry_run == true)
|
if (runtime_options.dry_run == true)
|
||||||
{
|
{
|
||||||
log_info(_("would pause repmgrd on node \"%s\" (ID: %i)"),
|
log_info(_("would pause repmgrd on node \"%s\" (ID %i)"),
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* XXX check result */
|
/* XXX check result */
|
||||||
log_debug("pausing repmgrd on node \"%s\" (ID: %i)",
|
log_debug("pausing repmgrd on node \"%s\" (ID %i)",
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
|
|
||||||
@@ -5235,18 +5221,6 @@ do_standby_switchover(void)
|
|||||||
format_lsn(replication_info.last_wal_receive_lsn),
|
format_lsn(replication_info.last_wal_receive_lsn),
|
||||||
format_lsn(remote_last_checkpoint_lsn));
|
format_lsn(remote_last_checkpoint_lsn));
|
||||||
|
|
||||||
/*
|
|
||||||
* optionally add a delay before promoting the standby; this is mainly
|
|
||||||
* useful for testing (e.g. for reappearance of the original primary) and
|
|
||||||
* is not documented.
|
|
||||||
*/
|
|
||||||
if (config_file_options.promote_delay > 0)
|
|
||||||
{
|
|
||||||
log_debug("sleeping %i seconds before promoting standby",
|
|
||||||
config_file_options.promote_delay);
|
|
||||||
sleep(config_file_options.promote_delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Promote standby (local node).
|
* Promote standby (local node).
|
||||||
*
|
*
|
||||||
@@ -5372,21 +5346,6 @@ do_standby_switchover(void)
|
|||||||
pfree(conninfo_normalized);
|
pfree(conninfo_normalized);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
|
||||||
snprintf(node_rejoin_log, MAXPGPATH,
|
|
||||||
#if defined(__i386__) || defined(__i386)
|
|
||||||
"/tmp/node-rejoin.%u.log",
|
|
||||||
(unsigned)time(NULL)
|
|
||||||
#else
|
|
||||||
"/tmp/node-rejoin.%lu.log",
|
|
||||||
(unsigned long)time(NULL)
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
|
|
||||||
appendPQExpBuffer(&remote_command_str,
|
|
||||||
" > %s 2>&1 && echo \"1\" || echo \"0\"",
|
|
||||||
node_rejoin_log);
|
|
||||||
|
|
||||||
termPQExpBuffer(&node_rejoin_options);
|
termPQExpBuffer(&node_rejoin_options);
|
||||||
|
|
||||||
log_debug("executing:\n %s", remote_command_str.data);
|
log_debug("executing:\n %s", remote_command_str.data);
|
||||||
@@ -5400,161 +5359,78 @@ do_standby_switchover(void)
|
|||||||
|
|
||||||
termPQExpBuffer(&remote_command_str);
|
termPQExpBuffer(&remote_command_str);
|
||||||
|
|
||||||
initPQExpBuffer(&logmsg);
|
/* TODO: verify this node's record was updated correctly */
|
||||||
initPQExpBuffer(&detailmsg);
|
|
||||||
|
|
||||||
/* This is failure to execute the ssh command */
|
|
||||||
if (command_success == false)
|
if (command_success == false)
|
||||||
{
|
{
|
||||||
log_error(_("rejoin failed with error code %i"), r);
|
log_error(_("rejoin failed with error code %i"), r);
|
||||||
switchover_success = false;
|
|
||||||
|
|
||||||
appendPQExpBuffer(&logmsg,
|
|
||||||
_("unable to execute \"repmgr node rejoin\" on demotion candidate \"%s\" (ID: %i)"),
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
appendPQExpBufferStr(&detailmsg,
|
|
||||||
command_output.data);
|
|
||||||
|
|
||||||
|
create_event_notification_extended(local_conn,
|
||||||
|
&config_file_options,
|
||||||
|
config_file_options.node_id,
|
||||||
|
"standby_switchover",
|
||||||
|
false,
|
||||||
|
command_output.data,
|
||||||
|
&event_info);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
standy_join_status join_success = JOIN_UNKNOWN;
|
PQExpBufferData event_details;
|
||||||
|
standy_join_status join_success = check_standby_join(local_conn,
|
||||||
|
&local_node_record,
|
||||||
|
&remote_node_record);
|
||||||
|
|
||||||
/* "rempgr node rejoin" failed on the demotion candidate */
|
initPQExpBuffer(&event_details);
|
||||||
if (command_output.data[0] == '0')
|
|
||||||
|
switch (join_success) {
|
||||||
|
case JOIN_FAIL_NO_PING:
|
||||||
|
appendPQExpBuffer(&event_details,
|
||||||
|
_("node \"%s\" (ID: %i) promoted to primary, but demote node \"%s\" (ID: %i) did not beome available"),
|
||||||
|
config_file_options.node_name,
|
||||||
|
config_file_options.node_id,
|
||||||
|
remote_node_record.node_name,
|
||||||
|
remote_node_record.node_id);
|
||||||
|
switchover_success = false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case JOIN_FAIL_NO_REPLICATION:
|
||||||
|
appendPQExpBuffer(&event_details,
|
||||||
|
_("node \"%s\" (ID: %i) promoted to primary, but demote node \"%s\" (ID: %i) did not connect to the new primary"),
|
||||||
|
config_file_options.node_name,
|
||||||
|
config_file_options.node_id,
|
||||||
|
remote_node_record.node_name,
|
||||||
|
remote_node_record.node_id);
|
||||||
|
switchover_success = false;
|
||||||
|
break;
|
||||||
|
case JOIN_SUCCESS:
|
||||||
|
appendPQExpBuffer(&event_details,
|
||||||
|
_("node \"%s\" (ID: %i) promoted to primary, node \"%s\" (ID: %i) demoted to standby"),
|
||||||
|
config_file_options.node_name,
|
||||||
|
config_file_options.node_id,
|
||||||
|
remote_node_record.node_name,
|
||||||
|
remote_node_record.node_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
create_event_notification_extended(local_conn,
|
||||||
|
&config_file_options,
|
||||||
|
config_file_options.node_id,
|
||||||
|
"standby_switchover",
|
||||||
|
switchover_success,
|
||||||
|
event_details.data,
|
||||||
|
&event_info);
|
||||||
|
if (switchover_success == true)
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(&logmsg,
|
log_notice("%s", event_details.data);
|
||||||
_("execution of \"repmgr node rejoin\" on demotion candidate \"%s\" (ID: %i) failed"),
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Speculatively check if the demotion candidate has been restarted, e.g. by
|
|
||||||
* an external watchdog process which isn't aware a switchover is happening.
|
|
||||||
* This falls into the category "thing outside of our control which shouldn't
|
|
||||||
* happen, but if it does, make it easier to find out what happened".
|
|
||||||
*/
|
|
||||||
remote_conn = establish_db_connection(remote_node_record.conninfo, false);
|
|
||||||
|
|
||||||
if (PQstatus(remote_conn) == CONNECTION_OK)
|
|
||||||
{
|
|
||||||
if (get_recovery_type(remote_conn) == RECTYPE_PRIMARY)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&detailmsg,
|
|
||||||
_("PostgreSQL instance on demotion candidate \"%s\" (ID: %i) is running as a primary\n"),
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
log_warning("%s", detailmsg.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PQfinish(remote_conn);
|
|
||||||
|
|
||||||
appendPQExpBuffer(&detailmsg,
|
|
||||||
"check log file \"%s\" on \"%s\" for details",
|
|
||||||
node_rejoin_log,
|
|
||||||
remote_node_record.node_name);
|
|
||||||
|
|
||||||
switchover_success = false;
|
|
||||||
join_success = JOIN_COMMAND_FAIL;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
join_success = check_standby_join(local_conn,
|
log_error("%s", event_details.data);
|
||||||
&local_node_record,
|
|
||||||
&remote_node_record);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
switch (join_success) {
|
|
||||||
case JOIN_FAIL_NO_PING:
|
|
||||||
appendPQExpBuffer(&logmsg,
|
|
||||||
_("node \"%s\" (ID: %i) promoted to primary, but demotion candidate \"%s\" (ID: %i) did not become available"),
|
|
||||||
config_file_options.node_name,
|
|
||||||
config_file_options.node_id,
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
|
|
||||||
switchover_success = false;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case JOIN_FAIL_NO_REPLICATION:
|
|
||||||
appendPQExpBuffer(&logmsg,
|
|
||||||
_("node \"%s\" (ID: %i) promoted to primary, but demotion candidate \"%s\" (ID: %i) did not connect to the new primary"),
|
|
||||||
config_file_options.node_name,
|
|
||||||
config_file_options.node_id,
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
switchover_success = false;
|
|
||||||
break;
|
|
||||||
case JOIN_SUCCESS:
|
|
||||||
appendPQExpBuffer(&logmsg,
|
|
||||||
_("node \"%s\" (ID: %i) promoted to primary, node \"%s\" (ID: %i) demoted to standby"),
|
|
||||||
config_file_options.node_name,
|
|
||||||
config_file_options.node_id,
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
break;
|
|
||||||
/* check_standby_join() does not return this */
|
|
||||||
case JOIN_COMMAND_FAIL:
|
|
||||||
break;
|
|
||||||
/* should never happen*/
|
|
||||||
case JOIN_UNKNOWN:
|
|
||||||
appendPQExpBuffer(&logmsg,
|
|
||||||
"unable to determine success of node rejoin action for demotion candidate \"%s\" (ID: %i)",
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
switchover_success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (switchover_success == false)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&detailmsg,
|
|
||||||
"check the PostgreSQL log file on demotion candidate \"%s\" (ID: %i)",
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
termPQExpBuffer(&event_details);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switchover_success == true)
|
|
||||||
{
|
|
||||||
/* TODO: verify demotion candidates's node record was updated correctly */
|
|
||||||
|
|
||||||
log_notice("%s", logmsg.data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_error("%s", logmsg.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
initPQExpBuffer(&event_details);
|
|
||||||
|
|
||||||
appendPQExpBufferStr(&event_details, logmsg.data);
|
|
||||||
|
|
||||||
if (detailmsg.data[0] != '\0')
|
|
||||||
{
|
|
||||||
log_detail("%s", detailmsg.data);
|
|
||||||
appendPQExpBuffer(&event_details, "\n%s",
|
|
||||||
detailmsg.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
create_event_notification_extended(local_conn,
|
|
||||||
&config_file_options,
|
|
||||||
config_file_options.node_id,
|
|
||||||
"standby_switchover",
|
|
||||||
switchover_success,
|
|
||||||
event_details.data,
|
|
||||||
&event_info);
|
|
||||||
|
|
||||||
termPQExpBuffer(&event_details);
|
|
||||||
termPQExpBuffer(&logmsg);
|
|
||||||
termPQExpBuffer(&detailmsg);
|
|
||||||
termPQExpBuffer(&command_output);
|
termPQExpBuffer(&command_output);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If --siblings-follow specified, attempt to make them follow the new
|
* If --siblings-follow specified, attempt to make them follow the new
|
||||||
* primary
|
* primary
|
||||||
@@ -5667,7 +5543,7 @@ do_standby_switchover(void)
|
|||||||
|
|
||||||
if (repmgrd_info[i]->paused == true && runtime_options.repmgrd_force_unpause == false)
|
if (repmgrd_info[i]->paused == true && runtime_options.repmgrd_force_unpause == false)
|
||||||
{
|
{
|
||||||
log_debug("repmgrd on node \"%s\" (ID: %i) paused before switchover, --repmgrd-force-unpause not provided, not unpausing",
|
log_debug("repmgrd on node \"%s\" (ID %i) paused before switchover, --repmgrd-force-unpause not provided, not unpausing",
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
|
|
||||||
@@ -5675,7 +5551,7 @@ do_standby_switchover(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debug("unpausing repmgrd on node \"%s\" (ID: %i)",
|
log_debug("unpausing repmgrd on node \"%s\" (ID %i)",
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
|
|
||||||
@@ -5686,7 +5562,7 @@ do_standby_switchover(void)
|
|||||||
if (repmgrd_pause(cell->node_info->conn, false) == false)
|
if (repmgrd_pause(cell->node_info->conn, false) == false)
|
||||||
{
|
{
|
||||||
item_list_append_format(&repmgrd_unpause_errors,
|
item_list_append_format(&repmgrd_unpause_errors,
|
||||||
_("unable to unpause node \"%s\" (ID: %i)"),
|
_("unable to unpause node \"%s\" (ID %i)"),
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
error_node_count++;
|
error_node_count++;
|
||||||
@@ -5695,7 +5571,7 @@ do_standby_switchover(void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
item_list_append_format(&repmgrd_unpause_errors,
|
item_list_append_format(&repmgrd_unpause_errors,
|
||||||
_("unable to connect to node \"%s\" (ID: %i):\n%s"),
|
_("unable to connect to node \"%s\" (ID %i):\n%s"),
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id,
|
cell->node_info->node_id,
|
||||||
PQerrorMessage(cell->node_info->conn));
|
PQerrorMessage(cell->node_info->conn));
|
||||||
@@ -6979,13 +6855,6 @@ run_basebackup(t_node_info *node_record)
|
|||||||
|
|
||||||
termPQExpBuffer(¶ms);
|
termPQExpBuffer(¶ms);
|
||||||
|
|
||||||
if (runtime_options.dry_run == true)
|
|
||||||
{
|
|
||||||
log_info(_("would execute:\n %s"), script.data);
|
|
||||||
termPQExpBuffer(&script);
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info(_("executing:\n %s"), script.data);
|
log_info(_("executing:\n %s"), script.data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -8149,9 +8018,9 @@ create_recovery_file(t_node_info *node_record, t_conninfo_param_list *primary_co
|
|||||||
free(escaped);
|
free(escaped);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Caller requests the generated file to be written into a buffer
|
|
||||||
*/
|
|
||||||
if (as_file == false)
|
if (as_file == false)
|
||||||
{
|
{
|
||||||
/* create file in buffer */
|
/* create file in buffer */
|
||||||
@@ -8171,17 +8040,20 @@ create_recovery_file(t_node_info *node_record, t_conninfo_param_list *primary_co
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PostgreSQL 12 and later: modify postgresql.auto.conf
|
* PostgreSQL 12 and later: modify postgresql.auto.conf
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
if (server_version_num >= 120000)
|
if (server_version_num >= 120000)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (modify_auto_conf(dest, &recovery_config) == false)
|
if (modify_auto_conf(dest, &recovery_config) == false)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write_standby_signal(dest) == false)
|
if (write_standby_signal() == false)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,7 +120,6 @@ typedef struct
|
|||||||
bool missing_slots;
|
bool missing_slots;
|
||||||
bool has_passfile;
|
bool has_passfile;
|
||||||
bool replication_connection;
|
bool replication_connection;
|
||||||
bool repmgrd;
|
|
||||||
bool data_directory_config;
|
bool data_directory_config;
|
||||||
bool replication_config_owner;
|
bool replication_config_owner;
|
||||||
bool db_connection;
|
bool db_connection;
|
||||||
@@ -176,7 +175,7 @@ typedef struct
|
|||||||
/* "node status" options */ \
|
/* "node status" options */ \
|
||||||
false, \
|
false, \
|
||||||
/* "node check" options */ \
|
/* "node check" options */ \
|
||||||
false, false, false, false, false, false, false, false, false, false, false, false, false, \
|
false, false, false, false, false, false, false, false, false, false, false, false, \
|
||||||
/* "node rejoin" options */ \
|
/* "node rejoin" options */ \
|
||||||
"", \
|
"", \
|
||||||
/* "node service" options */ \
|
/* "node service" options */ \
|
||||||
@@ -220,9 +219,7 @@ typedef enum
|
|||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
JOIN_UNKNOWN = -1,
|
|
||||||
JOIN_SUCCESS,
|
JOIN_SUCCESS,
|
||||||
JOIN_COMMAND_FAIL,
|
|
||||||
JOIN_FAIL_NO_PING,
|
JOIN_FAIL_NO_PING,
|
||||||
JOIN_FAIL_NO_REPLICATION
|
JOIN_FAIL_NO_REPLICATION
|
||||||
} standy_join_status;
|
} standy_join_status;
|
||||||
@@ -285,8 +282,8 @@ extern void get_node_config_directory(char *config_dir_buf);
|
|||||||
extern void get_node_data_directory(char *data_dir_buf);
|
extern void get_node_data_directory(char *data_dir_buf);
|
||||||
extern void init_node_record(t_node_info *node_record);
|
extern void init_node_record(t_node_info *node_record);
|
||||||
extern bool can_use_pg_rewind(PGconn *conn, const char *data_directory, PQExpBufferData *reason);
|
extern bool can_use_pg_rewind(PGconn *conn, const char *data_directory, PQExpBufferData *reason);
|
||||||
extern void make_standby_signal_path(const char *data_dir, char *buf);
|
extern void make_standby_signal_path(char *buf);
|
||||||
extern bool write_standby_signal(const char *data_dir);
|
extern bool write_standby_signal(void);
|
||||||
|
|
||||||
extern bool create_replication_slot(PGconn *conn, char *slot_name, t_node_info *upstream_node_record, PQExpBufferData *error_msg);
|
extern bool create_replication_slot(PGconn *conn, char *slot_name, t_node_info *upstream_node_record, PQExpBufferData *error_msg);
|
||||||
extern bool drop_replication_slot_if_exists(PGconn *conn, int node_id, char *slot_name);
|
extern bool drop_replication_slot_if_exists(PGconn *conn, int node_id, char *slot_name);
|
||||||
|
|||||||
@@ -51,7 +51,6 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -550,10 +549,6 @@ main(int argc, char **argv)
|
|||||||
runtime_options.data_directory_config = true;
|
runtime_options.data_directory_config = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPT_REPMGRD:
|
|
||||||
runtime_options.repmgrd = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPT_REPLICATION_CONFIG_OWNER:
|
case OPT_REPLICATION_CONFIG_OWNER:
|
||||||
runtime_options.replication_config_owner = true;
|
runtime_options.replication_config_owner = true;
|
||||||
break;
|
break;
|
||||||
@@ -3666,11 +3661,11 @@ can_use_pg_rewind(PGconn *conn, const char *data_directory, PQExpBufferData *rea
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
make_standby_signal_path(const char *data_dir, char *buf)
|
make_standby_signal_path(char *buf)
|
||||||
{
|
{
|
||||||
snprintf(buf, MAXPGPATH,
|
snprintf(buf, MAXPGPATH,
|
||||||
"%s/%s",
|
"%s/%s",
|
||||||
data_dir,
|
config_file_options.data_directory,
|
||||||
STANDBY_SIGNAL_FILE);
|
STANDBY_SIGNAL_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3678,15 +3673,13 @@ make_standby_signal_path(const char *data_dir, char *buf)
|
|||||||
* create standby.signal (PostgreSQL 12 and later)
|
* create standby.signal (PostgreSQL 12 and later)
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
write_standby_signal(const char *data_dir)
|
write_standby_signal(void)
|
||||||
{
|
{
|
||||||
char standby_signal_file_path[MAXPGPATH] = "";
|
char standby_signal_file_path[MAXPGPATH] = "";
|
||||||
FILE *file;
|
FILE *file;
|
||||||
mode_t um;
|
mode_t um;
|
||||||
|
|
||||||
Assert(data_dir != NULL);
|
make_standby_signal_path(standby_signal_file_path);
|
||||||
|
|
||||||
make_standby_signal_path(data_dir, standby_signal_file_path);
|
|
||||||
|
|
||||||
/* Set umask to 0600 */
|
/* Set umask to 0600 */
|
||||||
um = umask((~(S_IRUSR | S_IWUSR)) & (S_IRWXG | S_IRWXO));
|
um = umask((~(S_IRUSR | S_IWUSR)) & (S_IRWXG | S_IRWXO));
|
||||||
|
|||||||
@@ -100,7 +100,6 @@
|
|||||||
#define OPT_DB_CONNECTION 1047
|
#define OPT_DB_CONNECTION 1047
|
||||||
#define OPT_VERIFY_BACKUP 1048
|
#define OPT_VERIFY_BACKUP 1048
|
||||||
#define OPT_RECOVERY_MIN_APPLY_DELAY 1049
|
#define OPT_RECOVERY_MIN_APPLY_DELAY 1049
|
||||||
#define OPT_REPMGRD 1050
|
|
||||||
|
|
||||||
/* These options are for internal use only */
|
/* These options are for internal use only */
|
||||||
#define OPT_CONFIG_ARCHIVE_DIR 2001
|
#define OPT_CONFIG_ARCHIVE_DIR 2001
|
||||||
@@ -194,7 +193,6 @@ static struct option long_options[] =
|
|||||||
{"role", no_argument, NULL, OPT_ROLE},
|
{"role", no_argument, NULL, OPT_ROLE},
|
||||||
{"slots", no_argument, NULL, OPT_SLOTS},
|
{"slots", no_argument, NULL, OPT_SLOTS},
|
||||||
{"missing-slots", no_argument, NULL, OPT_MISSING_SLOTS},
|
{"missing-slots", no_argument, NULL, OPT_MISSING_SLOTS},
|
||||||
{"repmgrd", no_argument, NULL, OPT_REPMGRD},
|
|
||||||
{"has-passfile", no_argument, NULL, OPT_HAS_PASSFILE},
|
{"has-passfile", no_argument, NULL, OPT_HAS_PASSFILE},
|
||||||
{"replication-connection", no_argument, NULL, OPT_REPL_CONN},
|
{"replication-connection", no_argument, NULL, OPT_REPL_CONN},
|
||||||
{"data-directory-config", no_argument, NULL, OPT_DATA_DIRECTORY_CONFIG},
|
{"data-directory-config", no_argument, NULL, OPT_DATA_DIRECTORY_CONFIG},
|
||||||
|
|||||||
83
repmgr.c
83
repmgr.c
@@ -88,24 +88,59 @@ void _PG_fini(void);
|
|||||||
|
|
||||||
static void repmgr_shmem_startup(void);
|
static void repmgr_shmem_startup(void);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(repmgr_set_local_node_id);
|
Datum set_local_node_id(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_get_local_node_id);
|
PG_FUNCTION_INFO_V1(set_local_node_id);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_standby_set_last_updated);
|
|
||||||
PG_FUNCTION_INFO_V1(repmgr_standby_get_last_updated);
|
Datum get_local_node_id(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_set_upstream_last_seen);
|
PG_FUNCTION_INFO_V1(get_local_node_id);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_get_upstream_last_seen);
|
|
||||||
PG_FUNCTION_INFO_V1(repmgr_get_upstream_node_id);
|
Datum standby_set_last_updated(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_set_upstream_node_id);
|
PG_FUNCTION_INFO_V1(standby_set_last_updated);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_notify_follow_primary);
|
|
||||||
PG_FUNCTION_INFO_V1(repmgr_get_new_primary);
|
Datum standby_get_last_updated(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_reset_voting_status);
|
PG_FUNCTION_INFO_V1(standby_get_last_updated);
|
||||||
|
|
||||||
|
Datum set_upstream_last_seen(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(set_upstream_last_seen);
|
||||||
|
|
||||||
|
Datum get_upstream_last_seen(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(get_upstream_last_seen);
|
||||||
|
|
||||||
|
Datum get_upstream_node_id(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(get_upstream_node_id);
|
||||||
|
|
||||||
|
Datum set_upstream_node_id(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(set_upstream_node_id);
|
||||||
|
|
||||||
|
Datum notify_follow_primary(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(notify_follow_primary);
|
||||||
|
|
||||||
|
Datum get_new_primary(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(get_new_primary);
|
||||||
|
|
||||||
|
Datum reset_voting_status(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(reset_voting_status);
|
||||||
|
|
||||||
|
Datum set_repmgrd_pid(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(set_repmgrd_pid);
|
PG_FUNCTION_INFO_V1(set_repmgrd_pid);
|
||||||
|
|
||||||
|
Datum get_repmgrd_pid(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(get_repmgrd_pid);
|
PG_FUNCTION_INFO_V1(get_repmgrd_pid);
|
||||||
|
|
||||||
|
Datum get_repmgrd_pidfile(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(get_repmgrd_pidfile);
|
PG_FUNCTION_INFO_V1(get_repmgrd_pidfile);
|
||||||
|
|
||||||
|
Datum repmgrd_is_running(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(repmgrd_is_running);
|
PG_FUNCTION_INFO_V1(repmgrd_is_running);
|
||||||
|
|
||||||
|
Datum repmgrd_pause(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(repmgrd_pause);
|
PG_FUNCTION_INFO_V1(repmgrd_pause);
|
||||||
|
|
||||||
|
Datum repmgrd_is_paused(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(repmgrd_is_paused);
|
PG_FUNCTION_INFO_V1(repmgrd_is_paused);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_get_wal_receiver_pid);
|
|
||||||
|
Datum get_wal_receiver_pid(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(get_wal_receiver_pid);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -198,7 +233,7 @@ repmgr_shmem_startup(void)
|
|||||||
/* ==================== */
|
/* ==================== */
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_set_local_node_id(PG_FUNCTION_ARGS)
|
set_local_node_id(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int local_node_id = UNKNOWN_NODE_ID;
|
int local_node_id = UNKNOWN_NODE_ID;
|
||||||
int stored_node_id = UNKNOWN_NODE_ID;
|
int stored_node_id = UNKNOWN_NODE_ID;
|
||||||
@@ -268,7 +303,7 @@ repmgr_set_local_node_id(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_get_local_node_id(PG_FUNCTION_ARGS)
|
get_local_node_id(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int local_node_id = UNKNOWN_NODE_ID;
|
int local_node_id = UNKNOWN_NODE_ID;
|
||||||
|
|
||||||
@@ -285,7 +320,7 @@ repmgr_get_local_node_id(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* update and return last updated with current timestamp */
|
/* update and return last updated with current timestamp */
|
||||||
Datum
|
Datum
|
||||||
repmgr_standby_set_last_updated(PG_FUNCTION_ARGS)
|
standby_set_last_updated(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
TimestampTz last_updated = GetCurrentTimestamp();
|
TimestampTz last_updated = GetCurrentTimestamp();
|
||||||
|
|
||||||
@@ -302,7 +337,7 @@ repmgr_standby_set_last_updated(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* get last updated timestamp */
|
/* get last updated timestamp */
|
||||||
Datum
|
Datum
|
||||||
repmgr_standby_get_last_updated(PG_FUNCTION_ARGS)
|
standby_get_last_updated(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
TimestampTz last_updated;
|
TimestampTz last_updated;
|
||||||
|
|
||||||
@@ -319,7 +354,7 @@ repmgr_standby_get_last_updated(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_set_upstream_last_seen(PG_FUNCTION_ARGS)
|
set_upstream_last_seen(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int upstream_node_id = UNKNOWN_NODE_ID;
|
int upstream_node_id = UNKNOWN_NODE_ID;
|
||||||
|
|
||||||
@@ -342,7 +377,7 @@ repmgr_set_upstream_last_seen(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_get_upstream_last_seen(PG_FUNCTION_ARGS)
|
get_upstream_last_seen(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
long secs;
|
long secs;
|
||||||
int microsecs;
|
int microsecs;
|
||||||
@@ -376,7 +411,7 @@ repmgr_get_upstream_last_seen(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_get_upstream_node_id(PG_FUNCTION_ARGS)
|
get_upstream_node_id(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int upstream_node_id = UNKNOWN_NODE_ID;
|
int upstream_node_id = UNKNOWN_NODE_ID;
|
||||||
|
|
||||||
@@ -391,7 +426,7 @@ repmgr_get_upstream_node_id(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_set_upstream_node_id(PG_FUNCTION_ARGS)
|
set_upstream_node_id(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int upstream_node_id = UNKNOWN_NODE_ID;
|
int upstream_node_id = UNKNOWN_NODE_ID;
|
||||||
int local_node_id = UNKNOWN_NODE_ID;
|
int local_node_id = UNKNOWN_NODE_ID;
|
||||||
@@ -427,7 +462,7 @@ repmgr_set_upstream_node_id(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_notify_follow_primary(PG_FUNCTION_ARGS)
|
notify_follow_primary(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int primary_node_id = UNKNOWN_NODE_ID;
|
int primary_node_id = UNKNOWN_NODE_ID;
|
||||||
|
|
||||||
@@ -470,7 +505,7 @@ repmgr_notify_follow_primary(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_get_new_primary(PG_FUNCTION_ARGS)
|
get_new_primary(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int new_primary_node_id = UNKNOWN_NODE_ID;
|
int new_primary_node_id = UNKNOWN_NODE_ID;
|
||||||
|
|
||||||
@@ -492,7 +527,7 @@ repmgr_get_new_primary(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_reset_voting_status(PG_FUNCTION_ARGS)
|
reset_voting_status(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
if (!shared_state)
|
if (!shared_state)
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
@@ -700,7 +735,7 @@ repmgrd_is_paused(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_get_wal_receiver_pid(PG_FUNCTION_ARGS)
|
get_wal_receiver_pid(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int wal_receiver_pid;
|
int wal_receiver_pid;
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@
|
|||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
#replication_user='repmgr' # User to make replication connections with, if not set
|
#replication_user='repmgr' # User to make replication connections with, if not set
|
||||||
# defaults to the user defined in "conninfo".
|
# defaults to the user defined in "conninfo".
|
||||||
|
|
||||||
#replication_type='physical' # Must "physical" (the default).
|
#replication_type='physical' # Must "physical" (the default).
|
||||||
|
|
||||||
@@ -314,7 +314,7 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
#follow_command='' # command repmgrd executes when instructing a standby to follow a new primary;
|
#follow_command='' # command repmgrd executes when instructing a standby to follow a new primary;
|
||||||
# use something like:
|
# use something like:
|
||||||
#
|
#
|
||||||
# repmgr standby follow -f /etc/repmgr.conf --upstream-node-id=%n
|
# repmgr standby follow -f /etc/repmgr.conf -W --upstream-node-id=%n
|
||||||
#
|
#
|
||||||
#primary_notification_timeout=60 # Interval (in seconds) which repmgrd on a standby
|
#primary_notification_timeout=60 # Interval (in seconds) which repmgrd on a standby
|
||||||
# will wait for a notification from the new primary,
|
# will wait for a notification from the new primary,
|
||||||
@@ -337,7 +337,6 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
# "--no-pid-file" will force PID file creation to be skipped.
|
# "--no-pid-file" will force PID file creation to be skipped.
|
||||||
# Note: there is normally no need to set this, particularly if
|
# Note: there is normally no need to set this, particularly if
|
||||||
# repmgr was installed from packages.
|
# repmgr was installed from packages.
|
||||||
#repmgrd_exit_on_inactive_node=false # If "true", and the node record is marked as "inactive", abort repmgrd startup
|
|
||||||
#standby_disconnect_on_failover=false # If "true", in a failover situation wait for all standbys to
|
#standby_disconnect_on_failover=false # If "true", in a failover situation wait for all standbys to
|
||||||
# disconnect their WAL receivers before electing a new primary
|
# disconnect their WAL receivers before electing a new primary
|
||||||
# (PostgreSQL 9.5 and later only; repmgr user must be a superuser for this)
|
# (PostgreSQL 9.5 and later only; repmgr user must be a superuser for this)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# repmgr extension
|
# repmgr extension
|
||||||
comment = 'Replication manager for PostgreSQL'
|
comment = 'Replication manager for PostgreSQL'
|
||||||
default_version = '5.3'
|
default_version = '5.2'
|
||||||
module_pathname = '$libdir/repmgr'
|
module_pathname = '$libdir/repmgr'
|
||||||
relocatable = false
|
relocatable = false
|
||||||
schema = repmgr
|
schema = repmgr
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
1
repmgr.h
1
repmgr.h
@@ -135,7 +135,6 @@
|
|||||||
#define DEFAULT_ASYNC_QUERY_TIMEOUT 60 /* seconds */
|
#define DEFAULT_ASYNC_QUERY_TIMEOUT 60 /* seconds */
|
||||||
#define DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT 60 /* seconds */
|
#define DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT 60 /* seconds */
|
||||||
#define DEFAULT_REPMGRD_STANDBY_STARTUP_TIMEOUT -1 /*seconds */
|
#define DEFAULT_REPMGRD_STANDBY_STARTUP_TIMEOUT -1 /*seconds */
|
||||||
#define DEFAULT_REPMGRD_EXIT_ON_INACTIVE_NODE false,
|
|
||||||
#define DEFAULT_STANDBY_DISCONNECT_ON_FAILOVER false
|
#define DEFAULT_STANDBY_DISCONNECT_ON_FAILOVER false
|
||||||
#define DEFAULT_SIBLING_NODES_DISCONNECT_TIMEOUT 30 /* seconds */
|
#define DEFAULT_SIBLING_NODES_DISCONNECT_TIMEOUT 30 /* seconds */
|
||||||
#define DEFAULT_CONNECTION_CHECK_TYPE CHECK_PING
|
#define DEFAULT_CONNECTION_CHECK_TYPE CHECK_PING
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#define REPMGR_VERSION_DATE ""
|
#define REPMGR_VERSION_DATE ""
|
||||||
#define REPMGR_VERSION "5.3.1"
|
#define REPMGR_VERSION "5.2.1"
|
||||||
#define REPMGR_VERSION_NUM 50301
|
#define REPMGR_VERSION_NUM 50201
|
||||||
#define REPMGR_EXTENSION_VERSION "5.3"
|
#define REPMGR_RELEASE_DATE "2020-12-07"
|
||||||
#define REPMGR_EXTENSION_NUM 50300
|
|
||||||
#define REPMGR_RELEASE_DATE "2022-02-15"
|
|
||||||
#define PG_ACTUAL_VERSION_NUM
|
#define PG_ACTUAL_VERSION_NUM
|
||||||
|
|||||||
@@ -169,126 +169,45 @@ handle_sigint_physical(SIGNAL_ARGS)
|
|||||||
/* perform some sanity checks on the node's configuration */
|
/* perform some sanity checks on the node's configuration */
|
||||||
|
|
||||||
void
|
void
|
||||||
do_physical_node_check(PGconn *conn)
|
do_physical_node_check(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* If node record is "inactive"; if not, attempt to set it to "active".
|
* Check if node record is active - if not, and `failover=automatic`, the
|
||||||
|
* node won't be considered as a promotion candidate; this often happens
|
||||||
|
* when a failed primary is recloned and the node was not re-registered,
|
||||||
|
* giving the impression failover capability is there when it's not. In
|
||||||
|
* this case abort with an error and a hint about registering.
|
||||||
*
|
*
|
||||||
* Usually it will have become inactive due to e.g. a standby being shut down
|
* If `failover=manual`, repmgrd can continue to passively monitor the
|
||||||
* while repmgrd was running in an unpaused state. In this case it's
|
* node, but we should nevertheless issue a warning and the same hint.
|
||||||
* perfectly reasonable to automatically mark the node as "active".
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (local_node_info.active == false)
|
if (local_node_info.active == false)
|
||||||
{
|
{
|
||||||
char *hint = "Check that \"repmgr (primary|standby) register\" was executed for this node";
|
char *hint = "Check that \"repmgr (primary|standby) register\" was executed for this node";
|
||||||
RecoveryType recovery_type = get_recovery_type(conn);
|
|
||||||
|
|
||||||
/*
|
switch (config_file_options.failover)
|
||||||
* If the local node's recovery status is incompatible with its registered
|
|
||||||
* status, e.g. registered as primary but running as a standby, refuse to start.
|
|
||||||
*
|
|
||||||
* This typically happens when a failed primary is recloned but the node was not
|
|
||||||
* re-registered, leaving the cluster in a potentially ambiguous state. In
|
|
||||||
* this case it would not be possible or desirable to attempt to set the
|
|
||||||
* node to active; the user should ensure the cluster is in the correct state.
|
|
||||||
*/
|
|
||||||
if (recovery_type != RECTYPE_UNKNOWN && local_node_info.type != UNKNOWN)
|
|
||||||
{
|
{
|
||||||
bool require_reregister = false;
|
/* "failover" is an enum, all values should be covered here */
|
||||||
PQExpBufferData event_details;
|
|
||||||
initPQExpBuffer(&event_details);
|
|
||||||
|
|
||||||
if (recovery_type == RECTYPE_STANDBY && local_node_info.type != STANDBY)
|
case FAILOVER_AUTOMATIC:
|
||||||
{
|
log_error(_("this node is marked as inactive and cannot be used as a failover target"));
|
||||||
appendPQExpBuffer(&event_details,
|
|
||||||
_("node is registered as a %s but running as a standby"),
|
|
||||||
get_node_type_string(local_node_info.type));
|
|
||||||
|
|
||||||
require_reregister = true;
|
|
||||||
}
|
|
||||||
else if (recovery_type == RECTYPE_PRIMARY && local_node_info.type == STANDBY)
|
|
||||||
{
|
|
||||||
log_error(_("node is registered as a standby but running as a %s"), get_node_type_string(local_node_info.type));
|
|
||||||
require_reregister = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (require_reregister == true)
|
|
||||||
{
|
|
||||||
log_error("%s", event_details.data);
|
|
||||||
log_hint(_("%s"), hint);
|
log_hint(_("%s"), hint);
|
||||||
|
|
||||||
create_event_notification(NULL,
|
create_event_notification(NULL,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
"repmgrd_start",
|
"repmgrd_shutdown",
|
||||||
false,
|
false,
|
||||||
event_details.data);
|
"node is inactive and cannot be used as a failover target");
|
||||||
|
|
||||||
termPQExpBuffer(&event_details);
|
|
||||||
terminate(ERR_BAD_CONFIG);
|
terminate(ERR_BAD_CONFIG);
|
||||||
}
|
break;
|
||||||
|
|
||||||
termPQExpBuffer(&event_details);
|
case FAILOVER_MANUAL:
|
||||||
}
|
log_warning(_("this node is marked as inactive and will be passively monitored only"));
|
||||||
|
log_hint(_("%s"), hint);
|
||||||
/*
|
break;
|
||||||
* Attempt to set node record active (unless explicitly configured not to)
|
|
||||||
*/
|
|
||||||
log_notice(_("setting node record for node \"%s\" (ID: %i) to \"active\""),
|
|
||||||
local_node_info.node_name,
|
|
||||||
local_node_info.node_id);
|
|
||||||
|
|
||||||
if (config_file_options.repmgrd_exit_on_inactive_node == false)
|
|
||||||
{
|
|
||||||
PGconn *primary_conn = get_primary_connection(conn, NULL, NULL);
|
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
if (PQstatus(primary_conn) != CONNECTION_OK)
|
|
||||||
{
|
|
||||||
log_error(_("unable to connect to the primary node to activate the node record"));
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
success = update_node_record_set_active(primary_conn, local_node_info.node_id, true);
|
|
||||||
PQfinish(primary_conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success == true)
|
|
||||||
{
|
|
||||||
local_node_info.active = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Corner-case where it was not possible to set the node to "active"
|
|
||||||
*/
|
|
||||||
if (local_node_info.active == false)
|
|
||||||
{
|
|
||||||
switch (config_file_options.failover)
|
|
||||||
{
|
|
||||||
/* "failover" is an enum, all values should be covered here */
|
|
||||||
|
|
||||||
case FAILOVER_AUTOMATIC:
|
|
||||||
log_error(_("this node is marked as inactive and cannot be used as a failover target"));
|
|
||||||
log_hint(_("%s"), hint);
|
|
||||||
|
|
||||||
create_event_notification(NULL,
|
|
||||||
&config_file_options,
|
|
||||||
config_file_options.node_id,
|
|
||||||
"repmgrd_start",
|
|
||||||
false,
|
|
||||||
"node is inactive and cannot be used as a failover target");
|
|
||||||
|
|
||||||
terminate(ERR_BAD_CONFIG);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FAILOVER_MANUAL:
|
|
||||||
log_warning(_("this node is marked as inactive and will be passively monitored only"));
|
|
||||||
log_hint(_("%s"), hint);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,7 +504,6 @@ monitor_streaming_primary(void)
|
|||||||
|
|
||||||
if (is_server_available(local_node_info.conninfo) == true)
|
if (is_server_available(local_node_info.conninfo) == true)
|
||||||
{
|
{
|
||||||
close_connection(&local_conn);
|
|
||||||
local_conn = establish_db_connection(local_node_info.conninfo, false);
|
local_conn = establish_db_connection(local_node_info.conninfo, false);
|
||||||
|
|
||||||
if (PQstatus(local_conn) != CONNECTION_OK)
|
if (PQstatus(local_conn) != CONNECTION_OK)
|
||||||
@@ -1814,10 +1732,7 @@ monitor_streaming_standby(void)
|
|||||||
if (upstream_check_result == true)
|
if (upstream_check_result == true)
|
||||||
{
|
{
|
||||||
if (config_file_options.connection_check_type != CHECK_QUERY)
|
if (config_file_options.connection_check_type != CHECK_QUERY)
|
||||||
{
|
|
||||||
close_connection(&upstream_conn);
|
|
||||||
upstream_conn = establish_db_connection(upstream_node_info.conninfo, false);
|
upstream_conn = establish_db_connection(upstream_node_info.conninfo, false);
|
||||||
}
|
|
||||||
|
|
||||||
if (PQstatus(upstream_conn) == CONNECTION_OK)
|
if (PQstatus(upstream_conn) == CONNECTION_OK)
|
||||||
{
|
{
|
||||||
@@ -1898,7 +1813,6 @@ monitor_streaming_standby(void)
|
|||||||
int former_upstream_node_id = local_node_info.upstream_node_id;
|
int former_upstream_node_id = local_node_info.upstream_node_id;
|
||||||
NodeInfoList sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
NodeInfoList sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
t_event_info event_info = T_EVENT_INFO_INITIALIZER;
|
|
||||||
|
|
||||||
update_node_record_set_primary(local_conn, local_node_info.node_id);
|
update_node_record_set_primary(local_conn, local_node_info.node_id);
|
||||||
record_status = get_node_record(local_conn, local_node_info.node_id, &local_node_info);
|
record_status = get_node_record(local_conn, local_node_info.node_id, &local_node_info);
|
||||||
@@ -1911,16 +1825,12 @@ monitor_streaming_standby(void)
|
|||||||
initPQExpBuffer(&event_details);
|
initPQExpBuffer(&event_details);
|
||||||
appendPQExpBufferStr(&event_details,
|
appendPQExpBufferStr(&event_details,
|
||||||
_("promotion command failed but promotion completed successfully"));
|
_("promotion command failed but promotion completed successfully"));
|
||||||
|
create_event_notification(local_conn,
|
||||||
event_info.node_id = former_upstream_node_id;
|
&config_file_options,
|
||||||
|
local_node_info.node_id,
|
||||||
create_event_notification_extended(local_conn,
|
"repmgrd_failover_promote",
|
||||||
&config_file_options,
|
true,
|
||||||
local_node_info.node_id,
|
event_details.data);
|
||||||
"repmgrd_failover_promote",
|
|
||||||
true,
|
|
||||||
event_details.data,
|
|
||||||
&event_info);
|
|
||||||
|
|
||||||
termPQExpBuffer(&event_details);
|
termPQExpBuffer(&event_details);
|
||||||
|
|
||||||
@@ -2550,10 +2460,8 @@ monitor_streaming_witness(void)
|
|||||||
if (check_upstream_connection(&primary_conn, upstream_node_info.conninfo, NULL) == true)
|
if (check_upstream_connection(&primary_conn, upstream_node_info.conninfo, NULL) == true)
|
||||||
{
|
{
|
||||||
if (config_file_options.connection_check_type != CHECK_QUERY)
|
if (config_file_options.connection_check_type != CHECK_QUERY)
|
||||||
{
|
|
||||||
close_connection(&primary_conn);
|
|
||||||
primary_conn = establish_db_connection(upstream_node_info.conninfo, false);
|
primary_conn = establish_db_connection(upstream_node_info.conninfo, false);
|
||||||
}
|
|
||||||
if (PQstatus(primary_conn) == CONNECTION_OK)
|
if (PQstatus(primary_conn) == CONNECTION_OK)
|
||||||
{
|
{
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
@@ -3067,6 +2975,7 @@ do_primary_failover(void)
|
|||||||
|
|
||||||
t_node_info new_primary = T_NODE_INFO_INITIALIZER;
|
t_node_info new_primary = T_NODE_INFO_INITIALIZER;
|
||||||
RecordStatus record_status = RECORD_NOT_FOUND;
|
RecordStatus record_status = RECORD_NOT_FOUND;
|
||||||
|
PGconn *new_primary_conn;
|
||||||
|
|
||||||
record_status = get_node_record(local_conn, new_primary_id, &new_primary);
|
record_status = get_node_record(local_conn, new_primary_id, &new_primary);
|
||||||
|
|
||||||
@@ -3078,7 +2987,6 @@ do_primary_failover(void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
PGconn *new_primary_conn;
|
|
||||||
|
|
||||||
initPQExpBuffer(&event_details);
|
initPQExpBuffer(&event_details);
|
||||||
appendPQExpBuffer(&event_details,
|
appendPQExpBuffer(&event_details,
|
||||||
@@ -3099,6 +3007,7 @@ do_primary_failover(void)
|
|||||||
event_details.data);
|
event_details.data);
|
||||||
close_connection(&new_primary_conn);
|
close_connection(&new_primary_conn);
|
||||||
termPQExpBuffer(&event_details);
|
termPQExpBuffer(&event_details);
|
||||||
|
|
||||||
}
|
}
|
||||||
failover_state = FAILOVER_STATE_REQUIRES_MANUAL_FAILOVER;
|
failover_state = FAILOVER_STATE_REQUIRES_MANUAL_FAILOVER;
|
||||||
}
|
}
|
||||||
@@ -3765,7 +3674,6 @@ promote_self(void)
|
|||||||
|
|
||||||
{
|
{
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
t_event_info event_info = T_EVENT_INFO_INITIALIZER;
|
|
||||||
|
|
||||||
/* update own internal node record */
|
/* update own internal node record */
|
||||||
record_status = get_node_record(local_conn, local_node_info.node_id, &local_node_info);
|
record_status = get_node_record(local_conn, local_node_info.node_id, &local_node_info);
|
||||||
@@ -3782,16 +3690,13 @@ promote_self(void)
|
|||||||
failed_primary.node_name,
|
failed_primary.node_name,
|
||||||
failed_primary.node_id);
|
failed_primary.node_id);
|
||||||
|
|
||||||
event_info.node_id = failed_primary.node_id;
|
|
||||||
|
|
||||||
/* local_conn is now the primary connection */
|
/* local_conn is now the primary connection */
|
||||||
create_event_notification_extended(local_conn,
|
create_event_notification(local_conn,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
local_node_info.node_id,
|
local_node_info.node_id,
|
||||||
"repmgrd_failover_promote",
|
"repmgrd_failover_promote",
|
||||||
true,
|
true,
|
||||||
event_details.data,
|
event_details.data);
|
||||||
&event_info);
|
|
||||||
|
|
||||||
termPQExpBuffer(&event_details);
|
termPQExpBuffer(&event_details);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
#ifndef _REPMGRD_PHYSICAL_H_
|
#ifndef _REPMGRD_PHYSICAL_H_
|
||||||
#define _REPMGRD_PHYSICAL_H_
|
#define _REPMGRD_PHYSICAL_H_
|
||||||
|
|
||||||
void do_physical_node_check(PGconn *conn);
|
void do_physical_node_check(void);
|
||||||
|
|
||||||
void monitor_streaming_primary(void);
|
void monitor_streaming_primary(void);
|
||||||
void monitor_streaming_standby(void);
|
void monitor_streaming_standby(void);
|
||||||
|
|||||||
16
repmgrd.c
16
repmgrd.c
@@ -396,14 +396,13 @@ main(int argc, char **argv)
|
|||||||
* extension is the latest available according to "pg_available_extensions" -
|
* extension is the latest available according to "pg_available_extensions" -
|
||||||
* - does our (major) version match that?
|
* - does our (major) version match that?
|
||||||
*/
|
*/
|
||||||
log_verbose(LOG_DEBUG, "expected extension version: %i; extension version: %i",
|
log_verbose(LOG_DEBUG, "binary version: %i; extension version: %i",
|
||||||
REPMGR_EXTENSION_NUM, extversions.installed_version_num);
|
REPMGR_VERSION_NUM, extversions.installed_version_num);
|
||||||
if ((REPMGR_EXTENSION_NUM/100) < (extversions.installed_version_num / 100))
|
if ((REPMGR_VERSION_NUM/100) < (extversions.installed_version_num / 100))
|
||||||
{
|
{
|
||||||
log_error(_("this \"repmgr\" version is older than the installed \"repmgr\" extension version"));
|
log_error(_("this \"repmgr\" version is older than the installed \"repmgr\" extension version"));
|
||||||
log_detail(_("\"repmgr\" version %s providing extension version %s is installed but extension is version %s"),
|
log_detail(_("\"repmgr\" version %s is installed but extension is version %s"),
|
||||||
REPMGR_VERSION,
|
REPMGR_VERSION,
|
||||||
REPMGR_EXTENSION_VERSION,
|
|
||||||
extversions.installed_version);
|
extversions.installed_version);
|
||||||
log_hint(_("update the repmgr binaries to match the installed extension version"));
|
log_hint(_("update the repmgr binaries to match the installed extension version"));
|
||||||
|
|
||||||
@@ -411,12 +410,11 @@ main(int argc, char **argv)
|
|||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((REPMGR_EXTENSION_NUM/100) > (extversions.installed_version_num / 100))
|
if ((REPMGR_VERSION_NUM/100) > (extversions.installed_version_num / 100))
|
||||||
{
|
{
|
||||||
log_error(_("this \"repmgr\" version is newer than the installed \"repmgr\" extension version"));
|
log_error(_("this \"repmgr\" version is newer than the installed \"repmgr\" extension version"));
|
||||||
log_detail(_("\"repmgr\" version %s providing extension version %s is installed but extension is version %s"),
|
log_detail(_("\"repmgr\" version %s is installed but extension is version %s"),
|
||||||
REPMGR_VERSION,
|
REPMGR_VERSION,
|
||||||
REPMGR_EXTENSION_VERSION,
|
|
||||||
extversions.installed_version);
|
extversions.installed_version);
|
||||||
log_hint(_("update the installed extension version by executing \"ALTER EXTENSION repmgr UPDATE\" in the repmgr database"));
|
log_hint(_("update the installed extension version by executing \"ALTER EXTENSION repmgr UPDATE\" in the repmgr database"));
|
||||||
|
|
||||||
@@ -512,7 +510,7 @@ main(int argc, char **argv)
|
|||||||
log_debug("node id is %i, upstream node id is %i",
|
log_debug("node id is %i, upstream node id is %i",
|
||||||
local_node_info.node_id,
|
local_node_info.node_id,
|
||||||
local_node_info.upstream_node_id);
|
local_node_info.upstream_node_id);
|
||||||
do_physical_node_check(local_conn);
|
do_physical_node_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daemonize == true)
|
if (daemonize == true)
|
||||||
|
|||||||
Reference in New Issue
Block a user