mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-24 15:46:29 +00:00
Compare commits
345 Commits
v4.1.0
...
REL4_0_STA
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee1a6f9d0f | ||
|
|
49eb408873 | ||
|
|
fba3d29514 | ||
|
|
77200e5030 | ||
|
|
4589b8d439 | ||
|
|
048f7c3310 | ||
|
|
1e5f63792f | ||
|
|
d26989bd12 | ||
|
|
f999c810a7 | ||
|
|
81077d4bc2 | ||
|
|
a549941d4f | ||
|
|
2f6c159f9a | ||
|
|
2eca1a0311 | ||
|
|
f6377084ec | ||
|
|
d85c02b92b | ||
|
|
d9ba41fc35 | ||
|
|
afdaf9be66 | ||
|
|
8067924c3e | ||
|
|
e94a6eefde | ||
|
|
69d7b6f7eb | ||
|
|
8ec3b2a536 | ||
|
|
68a9745e7e | ||
|
|
20ce53e2d2 | ||
|
|
638a119c85 | ||
|
|
053863cdd0 | ||
|
|
009cc0480c | ||
|
|
63bdc19132 | ||
|
|
fbd389d0b3 | ||
|
|
4aef4ea11e | ||
|
|
0ffaff75df | ||
|
|
c54bb73fb2 | ||
|
|
28ea2e48de | ||
|
|
41274f5525 | ||
|
|
edceb32ccb | ||
|
|
3dba8336e9 | ||
|
|
97d0cee259 | ||
|
|
2dfe1d18e9 | ||
|
|
55bb93bd3f | ||
|
|
4c49954cd4 | ||
|
|
a880b6ce16 | ||
|
|
c51a2283dd | ||
|
|
717828e73e | ||
|
|
c7477d7a9c | ||
|
|
1db8d3904f | ||
|
|
362f478d55 | ||
|
|
cb1bf892e6 | ||
|
|
b1b5fe1193 | ||
|
|
af0e141859 | ||
|
|
580c1a9170 | ||
|
|
b624fc7efa | ||
|
|
67ccd4dcb3 | ||
|
|
6de3a5a997 | ||
|
|
f86e89ba45 | ||
|
|
a6d0ba07ed | ||
|
|
b553a70ad5 | ||
|
|
3364f8bdf0 | ||
|
|
242fa287b4 | ||
|
|
fa908432c8 | ||
|
|
afa942fef6 | ||
|
|
94cfc66b04 | ||
|
|
87eae9a50f | ||
|
|
82a37f4865 | ||
|
|
a38f727b7d | ||
|
|
e6df936c1b | ||
|
|
91ca997d40 | ||
|
|
65c90a2a64 | ||
|
|
90cba78f52 | ||
|
|
f8908d7e31 | ||
|
|
478bbcccbf | ||
|
|
a03d41de28 | ||
|
|
f1e527adcb | ||
|
|
09e597dcdd | ||
|
|
94a7f0c719 | ||
|
|
6ac42f1593 | ||
|
|
94b72382e5 | ||
|
|
18c12f58a4 | ||
|
|
cf3fa18085 | ||
|
|
a5281d93dc | ||
|
|
0d73d3c2b5 | ||
|
|
23c99304a6 | ||
|
|
1ab16bc6c2 | ||
|
|
7f1f04636d | ||
|
|
6a1797cadd | ||
|
|
94d26dbe9f | ||
|
|
ae655eb4fd | ||
|
|
65371489c6 | ||
|
|
28c7737dc0 | ||
|
|
505d72d19c | ||
|
|
b292ac61f8 | ||
|
|
293d66bf71 | ||
|
|
3e1f0ec168 | ||
|
|
6f9a1f975e | ||
|
|
deea4f69f7 | ||
|
|
37e53108a2 | ||
|
|
96cf06204c | ||
|
|
381e22c2c7 | ||
|
|
7e2af17783 | ||
|
|
b4272853e7 | ||
|
|
562b6ddfc2 | ||
|
|
a15e5c9d52 | ||
|
|
d9cc09cee4 | ||
|
|
c4f6abe951 | ||
|
|
e454fb77d3 | ||
|
|
b76e5852d3 | ||
|
|
0674364ffd | ||
|
|
b2eb9b8525 | ||
|
|
71c5d10a8c | ||
|
|
1476b21cd4 | ||
|
|
b17993abdb | ||
|
|
8f68344f9a | ||
|
|
125ac6c297 | ||
|
|
955860923f | ||
|
|
50626f90cc | ||
|
|
9aea5b8aa7 | ||
|
|
ed1bcb159e | ||
|
|
9c72c0d66e | ||
|
|
0ddc226c2a | ||
|
|
93830cad61 | ||
|
|
bca1660d5e | ||
|
|
5a52917421 | ||
|
|
70752d7d4a | ||
|
|
c29d1efc37 | ||
|
|
6fbbe2a97a | ||
|
|
ce42d6827e | ||
|
|
98384559a6 | ||
|
|
4a1477343b | ||
|
|
d2b9d20393 | ||
|
|
fe594c95ad | ||
|
|
60e63feaca | ||
|
|
ae4d0f2622 | ||
|
|
5e8b41e221 | ||
|
|
c7a585c555 | ||
|
|
a27dd8c49c | ||
|
|
9365bf3474 | ||
|
|
e8ae0831fe | ||
|
|
518866eba5 | ||
|
|
ed0330c334 | ||
|
|
1f021dc9fa | ||
|
|
425839d764 | ||
|
|
3a764f678a | ||
|
|
829cf5cca4 | ||
|
|
14420d83fa | ||
|
|
a80e22f0ed | ||
|
|
832993bfbc | ||
|
|
f1ea5e62df | ||
|
|
b47448d0e5 | ||
|
|
a8232337d8 | ||
|
|
c9eb1bfcc0 | ||
|
|
db552dfbc7 | ||
|
|
9732f78565 | ||
|
|
eb7dca2919 | ||
|
|
c113102926 | ||
|
|
ed6a167915 | ||
|
|
fbbe7afd61 | ||
|
|
ae1fc93e48 | ||
|
|
7b4ee80af2 | ||
|
|
0b8755e278 | ||
|
|
d3e1937808 | ||
|
|
871d6fdee3 | ||
|
|
c7dfe9e040 | ||
|
|
5c92a9e057 | ||
|
|
aa5f025738 | ||
|
|
5b91a2d409 | ||
|
|
596a19ee37 | ||
|
|
23ff83b3b4 | ||
|
|
ba1f6bee0d | ||
|
|
da9c8f2491 | ||
|
|
64035ef701 | ||
|
|
da3a5ab1dc | ||
|
|
9d301b4789 | ||
|
|
c070c649f7 | ||
|
|
3b823396eb | ||
|
|
c19e7f1025 | ||
|
|
e4b5a1e19f | ||
|
|
f96cc3b906 | ||
|
|
a481ca7ce2 | ||
|
|
32dc450a09 | ||
|
|
34dbf64f50 | ||
|
|
ea653a8dbc | ||
|
|
50894b6124 | ||
|
|
94e187c476 | ||
|
|
de6284ae79 | ||
|
|
c54045bcd8 | ||
|
|
c0a53471e1 | ||
|
|
2eec8b5d79 | ||
|
|
c11e92cf2a | ||
|
|
f294d09034 | ||
|
|
26c597ef5a | ||
|
|
b8efbb7a15 | ||
|
|
3044696c05 | ||
|
|
6dc1969ad5 | ||
|
|
cb41ef1733 | ||
|
|
d10f1f289e | ||
|
|
5731ba6043 | ||
|
|
3d6437c8f8 | ||
|
|
54b5c8ad94 | ||
|
|
0eca08ffaf | ||
|
|
05c1dc2b92 | ||
|
|
2bd300073d | ||
|
|
01e020df8e | ||
|
|
ae7963dc64 | ||
|
|
faffb2a6e7 | ||
|
|
5d57044118 | ||
|
|
07a88c78a5 | ||
|
|
f7df8b9c80 | ||
|
|
20920b3da1 | ||
|
|
683f4de182 | ||
|
|
0c62821ffb | ||
|
|
6b70e8bbe6 | ||
|
|
6b223698c9 | ||
|
|
aee12dc2c7 | ||
|
|
c5c86e1ada | ||
|
|
7476dc84f2 | ||
|
|
f6d63f5216 | ||
|
|
a608b0bc18 | ||
|
|
469ebba656 | ||
|
|
647c21ad0e | ||
|
|
3d2530d6f9 | ||
|
|
b26e400199 | ||
|
|
152e9545a4 | ||
|
|
83b8f05221 | ||
|
|
486f8e5a2c | ||
|
|
e517cc74d1 | ||
|
|
26285b470f | ||
|
|
1521657965 | ||
|
|
041604e303 | ||
|
|
0be0100a7c | ||
|
|
2133834dda | ||
|
|
d5fd93c350 | ||
|
|
5804778b58 | ||
|
|
407a7ea2f4 | ||
|
|
4d2eca0978 | ||
|
|
9d25544ab5 | ||
|
|
8506607388 | ||
|
|
e8e059c26d | ||
|
|
38d293694d | ||
|
|
54a10a0c3f | ||
|
|
a8016f602f | ||
|
|
de57ecdad1 | ||
|
|
1fde81cf3f | ||
|
|
146c412061 | ||
|
|
e9cb61ae7a | ||
|
|
50e9460b3e | ||
|
|
47e7cbe147 | ||
|
|
bf0be3eb43 | ||
|
|
270da1294c | ||
|
|
d3c47f450f | ||
|
|
c20475f94a | ||
|
|
e0560c3e70 | ||
|
|
3fa2bef6f4 | ||
|
|
f8a0b051c8 | ||
|
|
3e4a5e6ff5 | ||
|
|
020b5b6982 | ||
|
|
932326e4a0 | ||
|
|
019cd081e8 | ||
|
|
3ace908126 | ||
|
|
2ad174489c | ||
|
|
9124e0f0a2 | ||
|
|
060b746743 | ||
|
|
bdb82d3aba | ||
|
|
f6a6df3600 | ||
|
|
67e27f9ecd | ||
|
|
454c0b7bd9 | ||
|
|
faf297b07f | ||
|
|
0dae8c9f0b | ||
|
|
3f872cde0c | ||
|
|
e331069f53 | ||
|
|
53ebde8f33 | ||
|
|
5e9d50f8ca | ||
|
|
347e753c27 | ||
|
|
2f978847b1 | ||
|
|
3014f72fda | ||
|
|
e02ddd0f37 | ||
|
|
29fcee2209 | ||
|
|
f61f7f82eb | ||
|
|
efe28cbbeb | ||
|
|
6131c1d8ce | ||
|
|
c907b7b33d | ||
|
|
e6644305d3 | ||
|
|
31b856dd9f | ||
|
|
dff2bcc5de | ||
|
|
688e609169 | ||
|
|
3e68c9fcc6 | ||
|
|
d459b92186 | ||
|
|
2a898721c0 | ||
|
|
35782d83c0 | ||
|
|
e16eb42693 | ||
|
|
4d6dc57589 | ||
|
|
cbc97d84ac | ||
|
|
96fe7dd2d6 | ||
|
|
13935a88c9 | ||
|
|
5275890467 | ||
|
|
7f865fdaf3 | ||
|
|
9e2fb7ea13 | ||
|
|
a3428e4d8a | ||
|
|
03b9475755 | ||
|
|
de1eb3c459 | ||
|
|
a13eccccc5 | ||
|
|
158f132bc0 | ||
|
|
cdf54d217a | ||
|
|
1a8a82f207 | ||
|
|
60e877ca39 | ||
|
|
91531bffe4 | ||
|
|
fc5f46ca5a | ||
|
|
b76952e136 | ||
|
|
c3a1969f55 | ||
|
|
11d856a1ec | ||
|
|
fbf357947d | ||
|
|
47eaa99537 | ||
|
|
aeee11d1b7 | ||
|
|
e4713c5eca | ||
|
|
e55e5a0581 | ||
|
|
fb0aae183d | ||
|
|
52655e9cd5 | ||
|
|
c5d91ca88c | ||
|
|
9f5edd07ad | ||
|
|
f58b102d51 | ||
|
|
90733aecf7 | ||
|
|
e0be228c89 | ||
|
|
a9759cf6ca | ||
|
|
6852ac82c6 | ||
|
|
c27bd2a135 | ||
|
|
5045e2eb9d | ||
|
|
23f7af17a2 | ||
|
|
93936c090d | ||
|
|
564c951f0c | ||
|
|
3f5e8f6aec | ||
|
|
a6a97cda86 | ||
|
|
18c8e4c529 | ||
|
|
6984fe7029 | ||
|
|
5ecc3a0a8f | ||
|
|
febde097be | ||
|
|
19ea248226 | ||
|
|
acdbd1110a | ||
|
|
946683182c | ||
|
|
c9fbb7febf | ||
|
|
ff966fe533 | ||
|
|
7001960cc1 | ||
|
|
1cfba44799 | ||
|
|
d1f9ca4b43 | ||
|
|
f6c253f8a6 | ||
|
|
95ec8d8b21 | ||
|
|
041f1b7667 | ||
|
|
104279016a | ||
|
|
901a7603b1 |
26
HISTORY
26
HISTORY
@@ -1,29 +1,3 @@
|
|||||||
4.1.0 2018-??-??
|
|
||||||
repmgr: change default log_level to INFO, add documentation; GitHub #470 (Ian)
|
|
||||||
repmgr: add "--missing-slots" check to "repmgr node check" (Ian)
|
|
||||||
repmgr: improve command line error handling; GitHub #464 (Ian)
|
|
||||||
repmgr: fix "standby register --wait-sync" when no timeout provided (Ian)
|
|
||||||
repmgr: "cluster show" returns non-zero value if an issue encountered;
|
|
||||||
GitHub #456 (Ian)
|
|
||||||
repmgr: "node check" and "node status" returns non-zero value if an issue
|
|
||||||
encountered (Ian)
|
|
||||||
repmgr: add CSV output mode to "cluster event"; GitHub #471 (Ian)
|
|
||||||
repmgr: add -q/--quiet option to suppress non-error output; GitHub #468 (Ian)
|
|
||||||
repmgr: "node status" returns non-zero value if an issue encountered (Ian)
|
|
||||||
repmgr: enable "recovery_min_apply_delay" to be 0; GitHub #448 (Ian)
|
|
||||||
repmgr: "cluster cleanup" - add missing help options; GitHub #461/#462 (gclough)
|
|
||||||
repmgr: ensure witness node follows new primary after switchover;
|
|
||||||
GitHub #453 (Ian)
|
|
||||||
repmgr: fix witness node handling in "node check"/"node status";
|
|
||||||
GitHub #451 (Ian)
|
|
||||||
repmgr: fix "primary_slot_name" when using "standby clone" with --recovery-conf-only;
|
|
||||||
GitHub #474 (Ian)
|
|
||||||
repmgr: don't perform a switchover if an exclusive backup is running;
|
|
||||||
GitHub #476 (Martín)
|
|
||||||
repmgr: enable "witness unregister" to be run on any node; GitHub #472 (Ian)
|
|
||||||
repmgrd: create a PID file by default; GitHub #457 (Ian)
|
|
||||||
repmgrd: daemonize process by default; GitHub #458 (Ian)
|
|
||||||
|
|
||||||
4.0.6 2018-06-14
|
4.0.6 2018-06-14
|
||||||
repmgr: (witness register) prevent registration of a witness server with the
|
repmgr: (witness register) prevent registration of a witness server with the
|
||||||
same name as an existing node (Ian)
|
same name as an existing node (Ian)
|
||||||
|
|||||||
@@ -11,10 +11,7 @@ EXTENSION = repmgr
|
|||||||
|
|
||||||
DATA = \
|
DATA = \
|
||||||
repmgr--unpackaged--4.0.sql \
|
repmgr--unpackaged--4.0.sql \
|
||||||
repmgr--4.0.sql \
|
repmgr--4.0.sql
|
||||||
repmgr--4.0--4.1.sql \
|
|
||||||
repmgr--4.1.sql
|
|
||||||
|
|
||||||
|
|
||||||
REGRESS = repmgr_extension
|
REGRESS = repmgr_extension
|
||||||
|
|
||||||
|
|||||||
97
configfile.c
97
configfile.c
@@ -29,6 +29,9 @@ static bool config_file_provided = false;
|
|||||||
bool config_file_found = false;
|
bool config_file_found = false;
|
||||||
|
|
||||||
static void _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *warning_list);
|
static void _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *warning_list);
|
||||||
|
static bool parse_bool(const char *s,
|
||||||
|
const char *config_item,
|
||||||
|
ItemList *error_list);
|
||||||
|
|
||||||
static void _parse_line(char *buf, char *name, char *value);
|
static void _parse_line(char *buf, char *name, char *value);
|
||||||
static void parse_event_notifications_list(t_configuration_options *options, const char *arg);
|
static void parse_event_notifications_list(t_configuration_options *options, const char *arg);
|
||||||
@@ -330,12 +333,6 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
options->primary_follow_timeout = DEFAULT_PRIMARY_FOLLOW_TIMEOUT;
|
options->primary_follow_timeout = DEFAULT_PRIMARY_FOLLOW_TIMEOUT;
|
||||||
options->standby_follow_timeout = DEFAULT_STANDBY_FOLLOW_TIMEOUT;
|
options->standby_follow_timeout = DEFAULT_STANDBY_FOLLOW_TIMEOUT;
|
||||||
|
|
||||||
/*------------------------
|
|
||||||
* standby switchover settings
|
|
||||||
*------------------------
|
|
||||||
*/
|
|
||||||
options->standby_reconnect_timeout = DEFAULT_STANDBY_RECONNECT_TIMEOUT;
|
|
||||||
|
|
||||||
/*-----------------
|
/*-----------------
|
||||||
* repmgrd settings
|
* repmgrd settings
|
||||||
*-----------------
|
*-----------------
|
||||||
@@ -355,8 +352,7 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
options->degraded_monitoring_timeout = -1;
|
options->degraded_monitoring_timeout = -1;
|
||||||
options->async_query_timeout = DEFAULT_ASYNC_QUERY_TIMEOUT;
|
options->async_query_timeout = DEFAULT_ASYNC_QUERY_TIMEOUT;
|
||||||
options->primary_notification_timeout = DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT;
|
options->primary_notification_timeout = DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT;
|
||||||
options->repmgrd_standby_startup_timeout = -1; /* defaults to "standby_reconnect_timeout" if not set */
|
options->standby_reconnect_timeout = DEFAULT_STANDBY_RECONNECT_TIMEOUT;
|
||||||
memset(options->repmgrd_pid_file, 0, sizeof(options->repmgrd_pid_file));
|
|
||||||
|
|
||||||
/*-------------
|
/*-------------
|
||||||
* witness settings
|
* witness settings
|
||||||
@@ -543,14 +539,6 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
else if (strcmp(name, "standby_follow_timeout") == 0)
|
else if (strcmp(name, "standby_follow_timeout") == 0)
|
||||||
options->standby_follow_timeout = repmgr_atoi(value, name, error_list, 0);
|
options->standby_follow_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
|
||||||
/* standby switchover settings */
|
|
||||||
else if (strcmp(name, "standby_reconnect_timeout") == 0)
|
|
||||||
options->standby_reconnect_timeout = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
|
|
||||||
/* node rejoin settings */
|
|
||||||
else if (strcmp(name, "node_rejoin_timeout") == 0)
|
|
||||||
options->node_rejoin_timeout = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
|
|
||||||
/* node check settings */
|
/* node check settings */
|
||||||
else if (strcmp(name, "archive_ready_warning") == 0)
|
else if (strcmp(name, "archive_ready_warning") == 0)
|
||||||
options->archive_ready_warning = repmgr_atoi(value, name, error_list, 1);
|
options->archive_ready_warning = repmgr_atoi(value, name, error_list, 1);
|
||||||
@@ -600,10 +588,8 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
options->async_query_timeout = repmgr_atoi(value, name, error_list, 0);
|
options->async_query_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
else if (strcmp(name, "primary_notification_timeout") == 0)
|
else if (strcmp(name, "primary_notification_timeout") == 0)
|
||||||
options->primary_notification_timeout = repmgr_atoi(value, name, error_list, 0);
|
options->primary_notification_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
else if (strcmp(name, "repmgrd_standby_startup_timeout") == 0)
|
else if (strcmp(name, "standby_reconnect_timeout") == 0)
|
||||||
options->repmgrd_standby_startup_timeout = repmgr_atoi(value, name, error_list, 0);
|
options->standby_reconnect_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
else if (strcmp(name, "repmgrd_pid_file") == 0)
|
|
||||||
strncpy(options->repmgrd_pid_file, value, MAXPGPATH);
|
|
||||||
|
|
||||||
/* witness settings */
|
/* witness settings */
|
||||||
else if (strcmp(name, "witness_sync_interval") == 0)
|
else if (strcmp(name, "witness_sync_interval") == 0)
|
||||||
@@ -785,18 +771,6 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
PQconninfoFree(conninfo_options);
|
PQconninfoFree(conninfo_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* set values for parameters which default to other parameters */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* From 4.1, "repmgrd_standby_startup_timeout" replaces "standby_reconnect_timeout"
|
|
||||||
* in repmgrd; fall back to "standby_reconnect_timeout" if no value explicitly provided
|
|
||||||
*/
|
|
||||||
if (options->repmgrd_standby_startup_timeout == -1)
|
|
||||||
{
|
|
||||||
options->repmgrd_standby_startup_timeout = options->standby_reconnect_timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add warning about changed "barman_" parameter meanings */
|
/* add warning about changed "barman_" parameter meanings */
|
||||||
if ((options->barman_host[0] == '\0' && options->barman_server[0] != '\0') ||
|
if ((options->barman_host[0] == '\0' && options->barman_server[0] != '\0') ||
|
||||||
(options->barman_host[0] != '\0' && options->barman_server[0] == '\0'))
|
(options->barman_host[0] != '\0' && options->barman_server[0] == '\0'))
|
||||||
@@ -821,12 +795,6 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
item_list_append(error_list,
|
item_list_append(error_list,
|
||||||
_("\replication_lag_critical\" must be greater than \"replication_lag_warning\""));
|
_("\replication_lag_critical\" must be greater than \"replication_lag_warning\""));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options->standby_reconnect_timeout < options->node_rejoin_timeout)
|
|
||||||
{
|
|
||||||
item_list_append(error_list,
|
|
||||||
_("\"standby_reconnect_timeout\" must be equal to or greater than \"node_rejoin_timeout\""));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -991,11 +959,12 @@ parse_time_unit_parameter(const char *name, const char *value, char *dest, ItemL
|
|||||||
char *ptr = NULL;
|
char *ptr = NULL;
|
||||||
int targ = strtol(value, &ptr, 10);
|
int targ = strtol(value, &ptr, 10);
|
||||||
|
|
||||||
if (targ < 0)
|
if (targ < 1)
|
||||||
{
|
{
|
||||||
if (errors != NULL)
|
if (errors != NULL)
|
||||||
{
|
{
|
||||||
item_list_append_format(errors,
|
item_list_append_format(
|
||||||
|
errors,
|
||||||
_("invalid value provided for \"%s\""),
|
_("invalid value provided for \"%s\""),
|
||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
@@ -1049,7 +1018,6 @@ parse_time_unit_parameter(const char *name, const char *value, char *dest, ItemL
|
|||||||
* - promote_delay
|
* - promote_delay
|
||||||
* - reconnect_attempts
|
* - reconnect_attempts
|
||||||
* - reconnect_interval
|
* - reconnect_interval
|
||||||
* - repmgrd_standby_startup_timeout
|
|
||||||
* - retry_promote_interval_secs
|
* - retry_promote_interval_secs
|
||||||
*
|
*
|
||||||
* non-changeable options
|
* non-changeable options
|
||||||
@@ -1075,36 +1043,17 @@ reload_config(t_configuration_options *orig_options)
|
|||||||
static ItemList config_errors = {NULL, NULL};
|
static ItemList config_errors = {NULL, NULL};
|
||||||
static ItemList config_warnings = {NULL, NULL};
|
static ItemList config_warnings = {NULL, NULL};
|
||||||
|
|
||||||
PQExpBufferData errors;
|
|
||||||
|
|
||||||
log_info(_("reloading configuration file"));
|
log_info(_("reloading configuration file"));
|
||||||
|
|
||||||
_parse_config(&new_options, &config_errors, &config_warnings);
|
_parse_config(&new_options, &config_errors, &config_warnings);
|
||||||
|
|
||||||
if (config_errors.head != NULL)
|
if (config_errors.head != NULL)
|
||||||
{
|
{
|
||||||
ItemListCell *cell = NULL;
|
/* XXX dump errors to log */
|
||||||
|
|
||||||
log_warning(_("unable to parse new configuration, retaining current configuration"));
|
log_warning(_("unable to parse new configuration, retaining current configuration"));
|
||||||
|
|
||||||
initPQExpBuffer(&errors);
|
|
||||||
|
|
||||||
appendPQExpBuffer(&errors,
|
|
||||||
"following errors were detected:\n");
|
|
||||||
|
|
||||||
for (cell = config_errors.head; cell; cell = cell->next)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&errors,
|
|
||||||
" %s\n", cell->string);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_detail("%s", errors.data);
|
|
||||||
termPQExpBuffer(&errors);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* The following options cannot be changed */
|
/* The following options cannot be changed */
|
||||||
|
|
||||||
if (new_options.node_id != orig_options->node_id)
|
if (new_options.node_id != orig_options->node_id)
|
||||||
@@ -1285,15 +1234,6 @@ reload_config(t_configuration_options *orig_options)
|
|||||||
config_changed = true;
|
config_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* repmgrd_standby_startup_timeout */
|
|
||||||
if (orig_options->repmgrd_standby_startup_timeout != new_options.repmgrd_standby_startup_timeout)
|
|
||||||
{
|
|
||||||
orig_options->repmgrd_standby_startup_timeout = new_options.repmgrd_standby_startup_timeout;
|
|
||||||
log_info(_("\"repmgrd_standby_startup_timeout\" is now \"%i\""), new_options.repmgrd_standby_startup_timeout);
|
|
||||||
|
|
||||||
config_changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle changes to logging configuration
|
* Handle changes to logging configuration
|
||||||
*/
|
*/
|
||||||
@@ -1386,23 +1326,13 @@ exit_with_config_file_errors(ItemList *config_errors, ItemList *config_warnings,
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
exit_with_cli_errors(ItemList *error_list, const char *repmgr_command)
|
exit_with_cli_errors(ItemList *error_list)
|
||||||
{
|
{
|
||||||
fprintf(stderr, _("The following command line errors were encountered:\n"));
|
fprintf(stderr, _("The following command line errors were encountered:\n"));
|
||||||
|
|
||||||
print_item_list(error_list);
|
print_item_list(error_list);
|
||||||
|
|
||||||
if (repmgr_command != NULL)
|
|
||||||
{
|
|
||||||
fprintf(stderr, _("Try \"%s --help\" or \"%s %s --help\" for more information.\n"),
|
|
||||||
progname(),
|
|
||||||
progname(),
|
|
||||||
repmgr_command);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname());
|
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname());
|
||||||
}
|
|
||||||
|
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
@@ -1507,7 +1437,7 @@ repmgr_atoi(const char *value, const char *config_item, ItemList *error_list, in
|
|||||||
*
|
*
|
||||||
* https://www.postgresql.org/docs/current/static/config-setting.html
|
* https://www.postgresql.org/docs/current/static/config-setting.html
|
||||||
*/
|
*/
|
||||||
bool
|
static bool
|
||||||
parse_bool(const char *s, const char *config_item, ItemList *error_list)
|
parse_bool(const char *s, const char *config_item, ItemList *error_list)
|
||||||
{
|
{
|
||||||
PQExpBufferData errors;
|
PQExpBufferData errors;
|
||||||
@@ -1793,9 +1723,6 @@ free_parsed_argv(char ***argv_array)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_options *backup_options, int server_version_num, ItemList *error_list)
|
parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_options *backup_options, int server_version_num, ItemList *error_list)
|
||||||
{
|
{
|
||||||
|
|||||||
21
configfile.h
21
configfile.h
@@ -102,12 +102,6 @@ typedef struct
|
|||||||
int primary_follow_timeout;
|
int primary_follow_timeout;
|
||||||
int standby_follow_timeout;
|
int standby_follow_timeout;
|
||||||
|
|
||||||
/* standby switchover settings */
|
|
||||||
int standby_reconnect_timeout;
|
|
||||||
|
|
||||||
/* node rejoin settings */
|
|
||||||
int node_rejoin_timeout;
|
|
||||||
|
|
||||||
/* node check settings */
|
/* node check settings */
|
||||||
int archive_ready_warning;
|
int archive_ready_warning;
|
||||||
int archive_ready_critical;
|
int archive_ready_critical;
|
||||||
@@ -130,8 +124,7 @@ typedef struct
|
|||||||
int degraded_monitoring_timeout;
|
int degraded_monitoring_timeout;
|
||||||
int async_query_timeout;
|
int async_query_timeout;
|
||||||
int primary_notification_timeout;
|
int primary_notification_timeout;
|
||||||
int repmgrd_standby_startup_timeout;
|
int standby_reconnect_timeout;
|
||||||
char repmgrd_pid_file[MAXPGPATH];
|
|
||||||
|
|
||||||
/* BDR settings */
|
/* BDR settings */
|
||||||
bool bdr_local_monitoring_only;
|
bool bdr_local_monitoring_only;
|
||||||
@@ -180,10 +173,6 @@ typedef struct
|
|||||||
/* standby follow settings */ \
|
/* standby follow settings */ \
|
||||||
DEFAULT_PRIMARY_FOLLOW_TIMEOUT, \
|
DEFAULT_PRIMARY_FOLLOW_TIMEOUT, \
|
||||||
DEFAULT_STANDBY_FOLLOW_TIMEOUT, \
|
DEFAULT_STANDBY_FOLLOW_TIMEOUT, \
|
||||||
/* standby switchover settings */ \
|
|
||||||
DEFAULT_STANDBY_RECONNECT_TIMEOUT, \
|
|
||||||
/* node rejoin settings */ \
|
|
||||||
DEFAULT_NODE_REJOIN_TIMEOUT, \
|
|
||||||
/* node check settings */ \
|
/* node check settings */ \
|
||||||
DEFAULT_ARCHIVE_READY_WARNING, DEFAULT_ARCHIVE_READY_CRITICAL, \
|
DEFAULT_ARCHIVE_READY_WARNING, DEFAULT_ARCHIVE_READY_CRITICAL, \
|
||||||
DEFAULT_REPLICATION_LAG_WARNING, DEFAULT_REPLICATION_LAG_CRITICAL, \
|
DEFAULT_REPLICATION_LAG_WARNING, DEFAULT_REPLICATION_LAG_CRITICAL, \
|
||||||
@@ -197,7 +186,7 @@ typedef struct
|
|||||||
false, -1, \
|
false, -1, \
|
||||||
DEFAULT_ASYNC_QUERY_TIMEOUT, \
|
DEFAULT_ASYNC_QUERY_TIMEOUT, \
|
||||||
DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT, \
|
DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT, \
|
||||||
-1, "", \
|
DEFAULT_STANDBY_RECONNECT_TIMEOUT, \
|
||||||
/* BDR settings */ \
|
/* BDR settings */ \
|
||||||
false, DEFAULT_BDR_RECOVERY_TIMEOUT, \
|
false, DEFAULT_BDR_RECOVERY_TIMEOUT, \
|
||||||
/* service settings */ \
|
/* service settings */ \
|
||||||
@@ -283,10 +272,6 @@ bool reload_config(t_configuration_options *orig_options);
|
|||||||
|
|
||||||
bool parse_recovery_conf(const char *data_dir, t_recovery_conf *conf);
|
bool parse_recovery_conf(const char *data_dir, t_recovery_conf *conf);
|
||||||
|
|
||||||
bool parse_bool(const char *s,
|
|
||||||
const char *config_item,
|
|
||||||
ItemList *error_list);
|
|
||||||
|
|
||||||
int repmgr_atoi(const char *s,
|
int repmgr_atoi(const char *s,
|
||||||
const char *config_item,
|
const char *config_item,
|
||||||
ItemList *error_list,
|
ItemList *error_list,
|
||||||
@@ -302,7 +287,7 @@ void free_parsed_argv(char ***argv_array);
|
|||||||
|
|
||||||
|
|
||||||
/* called by repmgr-client and repmgrd */
|
/* called by repmgr-client and repmgrd */
|
||||||
void exit_with_cli_errors(ItemList *error_list, const char *repmgr_command);
|
void exit_with_cli_errors(ItemList *error_list);
|
||||||
void print_item_list(ItemList *item_list);
|
void print_item_list(ItemList *item_list);
|
||||||
|
|
||||||
#endif /* _REPMGR_CONFIGFILE_H_ */
|
#endif /* _REPMGR_CONFIGFILE_H_ */
|
||||||
|
|||||||
18
configure
vendored
18
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 4.1.
|
# Generated by GNU Autoconf 2.69 for repmgr 4.0.5.
|
||||||
#
|
#
|
||||||
# Report bugs to <pgsql-bugs@postgresql.org>.
|
# Report bugs to <pgsql-bugs@postgresql.org>.
|
||||||
#
|
#
|
||||||
@@ -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='4.1'
|
PACKAGE_VERSION='4.0.5'
|
||||||
PACKAGE_STRING='repmgr 4.1'
|
PACKAGE_STRING='repmgr 4.0.5'
|
||||||
PACKAGE_BUGREPORT='pgsql-bugs@postgresql.org'
|
PACKAGE_BUGREPORT='pgsql-bugs@postgresql.org'
|
||||||
PACKAGE_URL='https://2ndquadrant.com/en/resources/repmgr/'
|
PACKAGE_URL='https://2ndquadrant.com/en/resources/repmgr/'
|
||||||
|
|
||||||
@@ -1178,7 +1178,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 4.1 to adapt to many kinds of systems.
|
\`configure' configures repmgr 4.0.5 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@@ -1239,7 +1239,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 4.1:";;
|
short | recursive ) echo "Configuration of repmgr 4.0.5:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@@ -1313,7 +1313,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 4.1
|
repmgr configure 4.0.5
|
||||||
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.
|
||||||
@@ -1332,7 +1332,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 4.1, which was
|
It was created by repmgr $as_me 4.0.5, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@@ -2359,7 +2359,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 4.1, which was
|
This file was extended by repmgr $as_me 4.0.5, 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
|
||||||
@@ -2422,7 +2422,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 4.1
|
repmgr config.status 4.0.5
|
||||||
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], [4.1], [pgsql-bugs@postgresql.org], [repmgr], [https://2ndquadrant.com/en/resources/repmgr/])
|
AC_INIT([repmgr], [4.0.6], [pgsql-bugs@postgresql.org], [repmgr], [https://2ndquadrant.com/en/resources/repmgr/])
|
||||||
|
|
||||||
AC_COPYRIGHT([Copyright (c) 2010-2018, 2ndQuadrant Ltd.])
|
AC_COPYRIGHT([Copyright (c) 2010-2018, 2ndQuadrant Ltd.])
|
||||||
|
|
||||||
|
|||||||
333
dbutils.c
333
dbutils.c
@@ -33,12 +33,6 @@
|
|||||||
/* mainly for use by repmgrd */
|
/* mainly for use by repmgrd */
|
||||||
int server_version_num = UNKNOWN_SERVER_VERSION_NUM;
|
int server_version_num = UNKNOWN_SERVER_VERSION_NUM;
|
||||||
|
|
||||||
/*
|
|
||||||
* This is set by is_bdr_db(), which is called by every BDR-related
|
|
||||||
* action anyway; this is required to be able to generate appropriate
|
|
||||||
* queries for versions 2 and 3.
|
|
||||||
*/
|
|
||||||
int bdr_version_num = UNKNOWN_BDR_VERSION_NUM;
|
|
||||||
|
|
||||||
static PGconn *_establish_db_connection(const char *conninfo,
|
static PGconn *_establish_db_connection(const char *conninfo,
|
||||||
const bool exit_on_error,
|
const bool exit_on_error,
|
||||||
@@ -90,10 +84,7 @@ wrap_ddl_query(PQExpBufferData *query_buf, int replication_type, const char *fmt
|
|||||||
|
|
||||||
if (replication_type == REPLICATION_TYPE_BDR)
|
if (replication_type == REPLICATION_TYPE_BDR)
|
||||||
{
|
{
|
||||||
if (bdr_version_num < 3)
|
|
||||||
appendPQExpBuffer(query_buf, "SELECT bdr.bdr_replicate_ddl_command($repmgr$");
|
appendPQExpBuffer(query_buf, "SELECT bdr.bdr_replicate_ddl_command($repmgr$");
|
||||||
else
|
|
||||||
appendPQExpBuffer(query_buf, "SELECT bdr.replicate_ddl_command($repmgr$");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
va_start(arglist, fmt);
|
va_start(arglist, fmt);
|
||||||
@@ -1601,39 +1592,6 @@ repmgrd_get_local_node_id(PGconn *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Function that checks if the primary is in exclusive backup mode.
|
|
||||||
* We'll use this when executing an action can conflict with an exclusive
|
|
||||||
* backup.
|
|
||||||
*/
|
|
||||||
BackupState
|
|
||||||
server_in_exclusive_backup_mode(PGconn *conn)
|
|
||||||
{
|
|
||||||
BackupState backup_state = BACKUP_STATE_UNKNOWN;
|
|
||||||
PGresult *res = PQexec(conn, "SELECT pg_catalog.pg_is_in_backup()");
|
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
|
||||||
{
|
|
||||||
log_error(_("unable to retrieve information regarding backup mode of node"));
|
|
||||||
log_detail("%s", PQerrorMessage(conn));
|
|
||||||
PQclear(res);
|
|
||||||
return BACKUP_STATE_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (atobool(PQgetvalue(res, 0, 0)) == true)
|
|
||||||
{
|
|
||||||
backup_state = BACKUP_STATE_IN_BACKUP;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
backup_state = BACKUP_STATE_NO_BACKUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
PQclear(res);
|
|
||||||
|
|
||||||
return backup_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ================ */
|
/* ================ */
|
||||||
/* result functions */
|
/* result functions */
|
||||||
@@ -2282,7 +2240,6 @@ _create_update_node_record(PGconn *conn, char *action, t_node_info *node_info)
|
|||||||
const char *param_values[param_count];
|
const char *param_values[param_count];
|
||||||
|
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
maxlen_snprintf(node_id, "%i", node_info->node_id);
|
maxlen_snprintf(node_id, "%i", node_info->node_id);
|
||||||
maxlen_snprintf(priority, "%i", node_info->priority);
|
maxlen_snprintf(priority, "%i", node_info->priority);
|
||||||
@@ -2369,13 +2326,13 @@ _create_update_node_record(PGconn *conn, char *action, t_node_info *node_info)
|
|||||||
node_info->node_name,
|
node_info->node_name,
|
||||||
node_info->node_id);
|
node_info->node_id);
|
||||||
log_detail("%s", PQerrorMessage(conn));
|
log_detail("%s", PQerrorMessage(conn));
|
||||||
|
PQclear(res);
|
||||||
success = false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
return success;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2384,7 +2341,6 @@ update_node_record_set_active(PGconn *conn, int this_node_id, bool active)
|
|||||||
{
|
{
|
||||||
PQExpBufferData query;
|
PQExpBufferData query;
|
||||||
PGresult *res = NULL;
|
PGresult *res = NULL;
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
@@ -2403,13 +2359,13 @@ update_node_record_set_active(PGconn *conn, int this_node_id, bool active)
|
|||||||
{
|
{
|
||||||
log_error(_("unable to update node record:\n %s"),
|
log_error(_("unable to update node record:\n %s"),
|
||||||
PQerrorMessage(conn));
|
PQerrorMessage(conn));
|
||||||
|
PQclear(res);
|
||||||
success = false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
return success;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2418,7 +2374,6 @@ update_node_record_set_active_standby(PGconn *conn, int this_node_id)
|
|||||||
{
|
{
|
||||||
PQExpBufferData query;
|
PQExpBufferData query;
|
||||||
PGresult *res = NULL;
|
PGresult *res = NULL;
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
@@ -2438,13 +2393,13 @@ update_node_record_set_active_standby(PGconn *conn, int this_node_id)
|
|||||||
{
|
{
|
||||||
log_error(_("unable to update node record:\n %s"),
|
log_error(_("unable to update node record:\n %s"),
|
||||||
PQerrorMessage(conn));
|
PQerrorMessage(conn));
|
||||||
|
PQclear(res);
|
||||||
success = false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
return success;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2513,13 +2468,11 @@ update_node_record_set_primary(PGconn *conn, int this_node_id)
|
|||||||
return commit_transaction(conn);
|
return commit_transaction(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
update_node_record_set_upstream(PGconn *conn, int this_node_id, int new_upstream_node_id)
|
update_node_record_set_upstream(PGconn *conn, int this_node_id, int new_upstream_node_id)
|
||||||
{
|
{
|
||||||
PQExpBufferData query;
|
PQExpBufferData query;
|
||||||
PGresult *res = NULL;
|
PGresult *res = NULL;
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
log_debug(_("update_node_record_set_upstream(): Updating node %i's upstream node to %i"),
|
log_debug(_("update_node_record_set_upstream(): Updating node %i's upstream node to %i"),
|
||||||
this_node_id, new_upstream_node_id);
|
this_node_id, new_upstream_node_id);
|
||||||
@@ -2541,13 +2494,14 @@ update_node_record_set_upstream(PGconn *conn, int this_node_id, int new_upstream
|
|||||||
{
|
{
|
||||||
log_error(_("unable to set new upstream node id:\n %s"),
|
log_error(_("unable to set new upstream node id:\n %s"),
|
||||||
PQerrorMessage(conn));
|
PQerrorMessage(conn));
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
success = false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
return success;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2560,7 +2514,6 @@ update_node_record_status(PGconn *conn, int this_node_id, char *type, int upstre
|
|||||||
{
|
{
|
||||||
PQExpBufferData query;
|
PQExpBufferData query;
|
||||||
PGresult *res = NULL;
|
PGresult *res = NULL;
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
@@ -2584,13 +2537,14 @@ update_node_record_status(PGconn *conn, int this_node_id, char *type, int upstre
|
|||||||
{
|
{
|
||||||
log_error(_("unable to update node record:\n %s"),
|
log_error(_("unable to update node record:\n %s"),
|
||||||
PQerrorMessage(conn));
|
PQerrorMessage(conn));
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
success = false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
return success;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2603,7 +2557,6 @@ update_node_record_conn_priority(PGconn *conn, t_configuration_options *options)
|
|||||||
{
|
{
|
||||||
PQExpBufferData query;
|
PQExpBufferData query;
|
||||||
PGresult *res = NULL;
|
PGresult *res = NULL;
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
@@ -2621,12 +2574,13 @@ update_node_record_conn_priority(PGconn *conn, t_configuration_options *options)
|
|||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||||
{
|
{
|
||||||
success = false;
|
|
||||||
|
PQclear(res);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
return true;
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2690,7 +2644,6 @@ delete_node_record(PGconn *conn, int node)
|
|||||||
{
|
{
|
||||||
PQExpBufferData query;
|
PQExpBufferData query;
|
||||||
PGresult *res = NULL;
|
PGresult *res = NULL;
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
@@ -2708,20 +2661,19 @@ delete_node_record(PGconn *conn, int node)
|
|||||||
{
|
{
|
||||||
log_error(_("unable to delete node record:\n %s"),
|
log_error(_("unable to delete node record:\n %s"),
|
||||||
PQerrorMessage(conn));
|
PQerrorMessage(conn));
|
||||||
|
PQclear(res);
|
||||||
success = false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
return success;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
truncate_node_records(PGconn *conn)
|
truncate_node_records(PGconn *conn)
|
||||||
{
|
{
|
||||||
PGresult *res = NULL;
|
PGresult *res = NULL;
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
res = PQexec(conn, "TRUNCATE TABLE repmgr.nodes");
|
res = PQexec(conn, "TRUNCATE TABLE repmgr.nodes");
|
||||||
|
|
||||||
@@ -2729,13 +2681,12 @@ truncate_node_records(PGconn *conn)
|
|||||||
{
|
{
|
||||||
log_error(_("unable to truncate node record table:\n %s"),
|
log_error(_("unable to truncate node record table:\n %s"),
|
||||||
PQerrorMessage(conn));
|
PQerrorMessage(conn));
|
||||||
|
PQclear(res);
|
||||||
success = false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
return true;
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4401,7 +4352,6 @@ get_last_wal_receive_location(PGconn *conn)
|
|||||||
/* BDR functions */
|
/* BDR functions */
|
||||||
/* ============= */
|
/* ============= */
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
_is_bdr_db(PGconn *conn, PQExpBufferData *output, bool quiet)
|
_is_bdr_db(PGconn *conn, PQExpBufferData *output, bool quiet)
|
||||||
{
|
{
|
||||||
@@ -4412,9 +4362,7 @@ _is_bdr_db(PGconn *conn, PQExpBufferData *output, bool quiet)
|
|||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
appendPQExpBuffer(&query,
|
appendPQExpBuffer(&query,
|
||||||
" SELECT (pg_catalog.regexp_matches(extversion, '^\\d+'))[1] AS major_version "
|
"SELECT pg_catalog.count(*) FROM pg_catalog.pg_extension WHERE extname='bdr'");
|
||||||
" FROM pg_catalog.pg_extension "
|
|
||||||
" WHERE extname = 'bdr' ");
|
|
||||||
|
|
||||||
res = PQexec(conn, query.data);
|
res = PQexec(conn, query.data);
|
||||||
termPQExpBuffer(&query);
|
termPQExpBuffer(&query);
|
||||||
@@ -4422,18 +4370,14 @@ _is_bdr_db(PGconn *conn, PQExpBufferData *output, bool quiet)
|
|||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) == 0)
|
if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) == 0)
|
||||||
{
|
{
|
||||||
is_bdr_db = false;
|
is_bdr_db = false;
|
||||||
bdr_version_num = UNKNOWN_BDR_VERSION_NUM;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
is_bdr_db = true;
|
is_bdr_db = atoi(PQgetvalue(res, 0, 0)) == 1 ? true : false;
|
||||||
bdr_version_num = atoi(PQgetvalue(res, 0, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
log_verbose(LOG_DEBUG, "BDR ext version number is %i", bdr_version_num);
|
|
||||||
|
|
||||||
if (is_bdr_db == false)
|
if (is_bdr_db == false)
|
||||||
{
|
{
|
||||||
const char *warning = _("BDR extension is not available for this database");
|
const char *warning = _("BDR extension is not available for this database");
|
||||||
@@ -4446,8 +4390,6 @@ _is_bdr_db(PGconn *conn, PQExpBufferData *output, bool quiet)
|
|||||||
return is_bdr_db;
|
return is_bdr_db;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdr_version_num < 3)
|
|
||||||
{
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
appendPQExpBuffer(&query,
|
appendPQExpBuffer(&query,
|
||||||
@@ -4468,20 +4410,16 @@ _is_bdr_db(PGconn *conn, PQExpBufferData *output, bool quiet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return is_bdr_db;
|
return is_bdr_db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_bdr_db(PGconn *conn, PQExpBufferData *output)
|
is_bdr_db(PGconn *conn, PQExpBufferData *output)
|
||||||
{
|
{
|
||||||
return _is_bdr_db(conn, output, false);
|
return _is_bdr_db(conn, output, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_bdr_db_quiet(PGconn *conn)
|
is_bdr_db_quiet(PGconn *conn)
|
||||||
{
|
{
|
||||||
@@ -4489,11 +4427,6 @@ is_bdr_db_quiet(PGconn *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
get_bdr_version_num(void)
|
|
||||||
{
|
|
||||||
return bdr_version_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_active_bdr_node(PGconn *conn, const char *node_name)
|
is_active_bdr_node(PGconn *conn, const char *node_name)
|
||||||
@@ -4503,9 +4436,6 @@ is_active_bdr_node(PGconn *conn, const char *node_name)
|
|||||||
bool is_active_bdr_node = false;
|
bool is_active_bdr_node = false;
|
||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
if (bdr_version_num < 3)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&query,
|
appendPQExpBuffer(&query,
|
||||||
" SELECT COALESCE(s.active, TRUE) AS active"
|
" SELECT COALESCE(s.active, TRUE) AS active"
|
||||||
" FROM bdr.bdr_nodes n "
|
" FROM bdr.bdr_nodes n "
|
||||||
@@ -4513,19 +4443,6 @@ is_active_bdr_node(PGconn *conn, const char *node_name)
|
|||||||
" ON s.slot_name=bdr.bdr_format_slot_name(n.node_sysid, n.node_timeline, n.node_dboid, (SELECT oid FROM pg_catalog.pg_database WHERE datname = pg_catalog.current_database())) "
|
" ON s.slot_name=bdr.bdr_format_slot_name(n.node_sysid, n.node_timeline, n.node_dboid, (SELECT oid FROM pg_catalog.pg_database WHERE datname = pg_catalog.current_database())) "
|
||||||
" WHERE n.node_name='%s' ",
|
" WHERE n.node_name='%s' ",
|
||||||
node_name);
|
node_name);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&query,
|
|
||||||
" SELECT COALESCE(s.active, FALSE) AS active"
|
|
||||||
" FROM bdr.node bn "
|
|
||||||
" INNER JOIN pglogical.node pn "
|
|
||||||
" ON (pn.node_id = bn.pglogical_node_id) "
|
|
||||||
" LEFT JOIN pg_catalog.pg_replication_slots s "
|
|
||||||
" ON s.slot_name=bn.local_slot_name "
|
|
||||||
" WHERE pn.node_name='%s' ",
|
|
||||||
node_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_verbose(LOG_DEBUG, "is_active_bdr_node():\n %s", query.data);
|
log_verbose(LOG_DEBUG, "is_active_bdr_node():\n %s", query.data);
|
||||||
|
|
||||||
@@ -4579,64 +4496,6 @@ is_bdr_repmgr(PGconn *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get name of default BDR replication set.
|
|
||||||
*
|
|
||||||
* Caller must free provided value.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
get_default_bdr_replication_set(PGconn *conn)
|
|
||||||
{
|
|
||||||
PQExpBufferData query;
|
|
||||||
PGresult *res = NULL;
|
|
||||||
char *default_replication_set = NULL;
|
|
||||||
int namelen;
|
|
||||||
|
|
||||||
if (bdr_version_num < 3)
|
|
||||||
{
|
|
||||||
/* For BDR2, we use a custom replication set */
|
|
||||||
namelen = strlen(BDR2_REPLICATION_SET_NAME);
|
|
||||||
default_replication_set = pg_malloc0(namelen + 1);
|
|
||||||
strncpy(default_replication_set, BDR2_REPLICATION_SET_NAME, namelen);
|
|
||||||
|
|
||||||
return default_replication_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
initPQExpBuffer(&query);
|
|
||||||
|
|
||||||
appendPQExpBuffer(&query,
|
|
||||||
" SELECT rs.set_name "
|
|
||||||
" FROM pglogical.replication_set rs "
|
|
||||||
" INNER JOIN bdr.node_group ng "
|
|
||||||
" ON ng.node_group_default_repset = rs.set_id ");
|
|
||||||
|
|
||||||
res = PQexec(conn, query.data);
|
|
||||||
termPQExpBuffer(&query);
|
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) == 0)
|
|
||||||
{
|
|
||||||
log_warning(_("unable to retrieve default BDR replication set name"));
|
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
|
||||||
log_detail("%s", PQerrorMessage(conn));
|
|
||||||
|
|
||||||
PQclear(res);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
namelen = strlen(PQgetvalue(res, 0, 0));
|
|
||||||
default_replication_set = pg_malloc0(namelen + 1);
|
|
||||||
|
|
||||||
strncpy(default_replication_set, PQgetvalue(res, 0, 0), namelen);
|
|
||||||
|
|
||||||
PQclear(res);
|
|
||||||
|
|
||||||
return default_replication_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_table_in_bdr_replication_set(PGconn *conn, const char *tablename, const char *set)
|
is_table_in_bdr_replication_set(PGconn *conn, const char *tablename, const char *set)
|
||||||
{
|
{
|
||||||
@@ -4646,28 +4505,12 @@ is_table_in_bdr_replication_set(PGconn *conn, const char *tablename, const char
|
|||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
if (bdr_version_num < 3)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&query,
|
appendPQExpBuffer(&query,
|
||||||
"SELECT pg_catalog.count(*) "
|
"SELECT pg_catalog.count(*) "
|
||||||
" FROM pg_catalog.unnest(bdr.table_get_replication_sets('repmgr.%s')) AS repset "
|
" FROM pg_catalog.unnest(bdr.table_get_replication_sets('repmgr.%s')) AS repset "
|
||||||
" WHERE repset='%s' ",
|
" WHERE repset='%s' ",
|
||||||
tablename,
|
tablename,
|
||||||
set);
|
set);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&query,
|
|
||||||
" SELECT pg_catalog.count(*) "
|
|
||||||
" FROM pglogical.replication_set s "
|
|
||||||
" INNER JOIN pglogical.replication_set_table st "
|
|
||||||
" ON s.set_id = st.set_id "
|
|
||||||
" WHERE s.set_name = '%s' "
|
|
||||||
" AND st.set_reloid = 'repmgr.%s'::REGCLASS ",
|
|
||||||
set,
|
|
||||||
tablename);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
res = PQexec(conn, query.data);
|
res = PQexec(conn, query.data);
|
||||||
termPQExpBuffer(&query);
|
termPQExpBuffer(&query);
|
||||||
@@ -4693,44 +4536,32 @@ add_table_to_bdr_replication_set(PGconn *conn, const char *tablename, const char
|
|||||||
{
|
{
|
||||||
PQExpBufferData query;
|
PQExpBufferData query;
|
||||||
PGresult *res = NULL;
|
PGresult *res = NULL;
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
if (bdr_version_num < 3)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&query,
|
appendPQExpBuffer(&query,
|
||||||
"SELECT bdr.table_set_replication_sets('repmgr.%s', '{%s}')",
|
"SELECT bdr.table_set_replication_sets('repmgr.%s', '{%s}')",
|
||||||
tablename,
|
tablename,
|
||||||
set);
|
set);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&query,
|
|
||||||
" SELECT bdr.replication_set_add_table( "
|
|
||||||
" relation := 'repmgr.%s', "
|
|
||||||
" set_name := '%s' "
|
|
||||||
" ) ",
|
|
||||||
tablename,
|
|
||||||
set);
|
|
||||||
}
|
|
||||||
|
|
||||||
res = PQexec(conn, query.data);
|
res = PQexec(conn, query.data);
|
||||||
termPQExpBuffer(&query);
|
termPQExpBuffer(&query);
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
{
|
{
|
||||||
log_error(_("unable to add table \"repmgr.%s\" to replication set \"%s\""),
|
log_error(_("unable to add table \"repmgr.%s\" to replication set \"%s\":\n %s"),
|
||||||
tablename,
|
tablename,
|
||||||
set);
|
set,
|
||||||
log_detail("%s", PQerrorMessage(conn));
|
PQerrorMessage(conn));
|
||||||
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (res != NULL)
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
return success;
|
return false;
|
||||||
|
}
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4743,16 +4574,8 @@ bdr_node_name_matches(PGconn *conn, const char *node_name, PQExpBufferData *bdr_
|
|||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
if (bdr_version_num < 3)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&query,
|
appendPQExpBuffer(&query,
|
||||||
"SELECT bdr.bdr_get_local_node_name() AS node_name");
|
"SELECT bdr.bdr_get_local_node_name() AS node_name");
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&query,
|
|
||||||
"SELECT node_name FROM bdr.local_node_info()");
|
|
||||||
}
|
|
||||||
|
|
||||||
res = PQexec(conn, query.data);
|
res = PQexec(conn, query.data);
|
||||||
termPQExpBuffer(&query);
|
termPQExpBuffer(&query);
|
||||||
@@ -4783,8 +4606,6 @@ get_bdr_node_replication_slot_status(PGconn *conn, const char *node_name)
|
|||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
if (bdr_version_num < 3)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&query,
|
appendPQExpBuffer(&query,
|
||||||
" SELECT s.active "
|
" SELECT s.active "
|
||||||
" FROM pg_catalog.pg_replication_slots s "
|
" FROM pg_catalog.pg_replication_slots s "
|
||||||
@@ -4793,26 +4614,13 @@ get_bdr_node_replication_slot_status(PGconn *conn, const char *node_name)
|
|||||||
" FROM bdr.bdr_nodes "
|
" FROM bdr.bdr_nodes "
|
||||||
" WHERE node_name = '%s') ",
|
" WHERE node_name = '%s') ",
|
||||||
node_name);
|
node_name);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&query,
|
|
||||||
" SELECT COALESCE(s.active, FALSE) AS active"
|
|
||||||
" FROM bdr.node bn "
|
|
||||||
" INNER JOIN pglogical.node pn "
|
|
||||||
" ON (pn.node_id = bn.pglogical_node_id) "
|
|
||||||
" INNER JOIN pg_catalog.pg_replication_slots s "
|
|
||||||
" ON s.slot_name=bn.local_slot_name "
|
|
||||||
" WHERE pn.node_name='%s' ",
|
|
||||||
node_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_verbose(LOG_DEBUG, "get_bdr_node_replication_slot_status():\n %s", query.data);
|
log_verbose(LOG_DEBUG, "get_bdr_node_replication_slot_status():\n %s", query.data);
|
||||||
|
|
||||||
res = PQexec(conn, query.data);
|
res = PQexec(conn, query.data);
|
||||||
termPQExpBuffer(&query);
|
termPQExpBuffer(&query);
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) == 0)
|
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
{
|
{
|
||||||
status = SLOT_UNKNOWN;
|
status = SLOT_UNKNOWN;
|
||||||
}
|
}
|
||||||
@@ -4863,9 +4671,6 @@ get_bdr_other_node_name(PGconn *conn, int node_id, char *node_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For BDR 2.x only
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
add_extension_tables_to_bdr_replication_set(PGconn *conn)
|
add_extension_tables_to_bdr_replication_set(PGconn *conn)
|
||||||
{
|
{
|
||||||
@@ -4887,7 +4692,7 @@ add_extension_tables_to_bdr_replication_set(PGconn *conn)
|
|||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
{
|
{
|
||||||
/* XXX log error */
|
/* */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -4895,7 +4700,8 @@ add_extension_tables_to_bdr_replication_set(PGconn *conn)
|
|||||||
|
|
||||||
for (i = 0; i < PQntuples(res); i++)
|
for (i = 0; i < PQntuples(res); i++)
|
||||||
{
|
{
|
||||||
add_table_to_bdr_replication_set(conn,
|
add_table_to_bdr_replication_set(
|
||||||
|
conn,
|
||||||
PQgetvalue(res, i, 0),
|
PQgetvalue(res, i, 0),
|
||||||
"repmgr");
|
"repmgr");
|
||||||
}
|
}
|
||||||
@@ -4914,20 +4720,10 @@ get_all_bdr_node_records(PGconn *conn, BdrNodeInfoList *node_list)
|
|||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
if (bdr_version_num < 3)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&query,
|
appendPQExpBuffer(&query,
|
||||||
" SELECT " BDR2_NODES_COLUMNS
|
" SELECT " BDR_NODES_COLUMNS
|
||||||
" FROM bdr.bdr_nodes "
|
" FROM bdr.bdr_nodes "
|
||||||
"ORDER BY node_seq_id ");
|
"ORDER BY node_seq_id ");
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&query,
|
|
||||||
" SELECT " BDR3_NODES_COLUMNS
|
|
||||||
" FROM bdr.node_summary ns "
|
|
||||||
" ORDER BY node_name");
|
|
||||||
}
|
|
||||||
|
|
||||||
log_verbose(LOG_DEBUG, "get_all_node_records():\n%s", query.data);
|
log_verbose(LOG_DEBUG, "get_all_node_records():\n%s", query.data);
|
||||||
|
|
||||||
@@ -4948,22 +4744,11 @@ get_bdr_node_record_by_name(PGconn *conn, const char *node_name, t_bdr_node_info
|
|||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
if (bdr_version_num < 3)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&query,
|
appendPQExpBuffer(&query,
|
||||||
" SELECT " BDR2_NODES_COLUMNS
|
" SELECT " BDR_NODES_COLUMNS
|
||||||
" FROM bdr.bdr_nodes "
|
" FROM bdr.bdr_nodes "
|
||||||
" WHERE node_name = '%s'",
|
" WHERE node_name = '%s'",
|
||||||
node_name);
|
node_name);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&query,
|
|
||||||
" SELECT " BDR3_NODES_COLUMNS
|
|
||||||
" FROM bdr.node_summary ns "
|
|
||||||
" WHERE ns.node_name = '%s'",
|
|
||||||
node_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_verbose(LOG_DEBUG, "get_bdr_node_record_by_name():\n%s", query.data);
|
log_verbose(LOG_DEBUG, "get_bdr_node_record_by_name():\n%s", query.data);
|
||||||
|
|
||||||
@@ -5033,12 +4818,16 @@ _populate_bdr_node_records(PGresult *res, BdrNodeInfoList *node_list)
|
|||||||
static void
|
static void
|
||||||
_populate_bdr_node_record(PGresult *res, t_bdr_node_info *node_info, int row)
|
_populate_bdr_node_record(PGresult *res, t_bdr_node_info *node_info, int row)
|
||||||
{
|
{
|
||||||
|
char buf[MAXLEN] = "";
|
||||||
|
|
||||||
strncpy(node_info->node_sysid, PQgetvalue(res, row, 0), MAXLEN);
|
strncpy(node_info->node_sysid, PQgetvalue(res, row, 0), MAXLEN);
|
||||||
node_info->node_timeline = atoi(PQgetvalue(res, row, 1));
|
node_info->node_timeline = atoi(PQgetvalue(res, row, 1));
|
||||||
node_info->node_dboid = atoi(PQgetvalue(res, row, 2));
|
node_info->node_dboid = atoi(PQgetvalue(res, row, 2));
|
||||||
strncpy(node_info->node_name, PQgetvalue(res, row, 3), MAXLEN);
|
strncpy(buf, PQgetvalue(res, row, 3), MAXLEN);
|
||||||
strncpy(node_info->node_local_dsn, PQgetvalue(res, row, 4), MAXLEN);
|
node_info->node_status = buf[0];
|
||||||
strncpy(node_info->peer_state_name, PQgetvalue(res, row, 5), MAXLEN);
|
strncpy(node_info->node_name, PQgetvalue(res, row, 4), MAXLEN);
|
||||||
|
strncpy(node_info->node_local_dsn, PQgetvalue(res, row, 5), MAXLEN);
|
||||||
|
strncpy(node_info->node_init_from_dsn, PQgetvalue(res, row, 6), MAXLEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -5093,17 +4882,13 @@ bdr_node_has_repmgr_set(PGconn *conn, const char *node_name)
|
|||||||
PGresult *res = NULL;
|
PGresult *res = NULL;
|
||||||
bool has_repmgr_set = false;
|
bool has_repmgr_set = false;
|
||||||
|
|
||||||
if (bdr_version_num >= 3)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
appendPQExpBuffer(&query,
|
appendPQExpBuffer(&query,
|
||||||
" SELECT pg_catalog.count(*) "
|
" SELECT pg_catalog.count(*) "
|
||||||
" FROM pg_catalog.unnest(bdr.connection_get_replication_sets('%s') AS repset "
|
" FROM pg_catalog.unnest(bdr.connection_get_replication_sets('%s') AS repset "
|
||||||
" WHERE repset = '%s'",
|
" WHERE repset = 'repmgr'",
|
||||||
node_name,
|
node_name);
|
||||||
BDR2_REPLICATION_SET_NAME);
|
|
||||||
|
|
||||||
res = PQexec(conn, query.data);
|
res = PQexec(conn, query.data);
|
||||||
termPQExpBuffer(&query);
|
termPQExpBuffer(&query);
|
||||||
@@ -5130,40 +4915,26 @@ bdr_node_set_repmgr_set(PGconn *conn, const char *node_name)
|
|||||||
PGresult *res = NULL;
|
PGresult *res = NULL;
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
if (bdr_version_num >= 3)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
/*
|
|
||||||
* Here we extract a list of existing replication sets, add 'repmgr', and
|
|
||||||
* set the replication sets to the new list.
|
|
||||||
*/
|
|
||||||
appendPQExpBuffer(&query,
|
appendPQExpBuffer(&query,
|
||||||
" SELECT bdr.connection_set_replication_sets( "
|
" SELECT bdr.connection_set_replication_sets( "
|
||||||
" ARRAY( "
|
" ARRAY( "
|
||||||
" SELECT repset::TEXT "
|
" SELECT repset::TEXT "
|
||||||
" FROM pg_catalog.unnest(bdr.connection_get_replication_sets('%s')) AS repset "
|
" FROM pg_catalog.unnest(bdr.connection_get_replication_sets('%s')) AS repset "
|
||||||
" UNION "
|
" UNION "
|
||||||
" SELECT '%s'::TEXT "
|
" SELECT 'repmgr'::TEXT "
|
||||||
" ), "
|
" ), "
|
||||||
" '%s' "
|
" '%s' "
|
||||||
" ) ",
|
" ) ",
|
||||||
node_name,
|
node_name,
|
||||||
BDR2_REPLICATION_SET_NAME,
|
|
||||||
node_name);
|
node_name);
|
||||||
|
|
||||||
log_debug("bdr_node_set_repmgr_set():\n%s", query.data);
|
|
||||||
|
|
||||||
res = PQexec(conn, query.data);
|
res = PQexec(conn, query.data);
|
||||||
termPQExpBuffer(&query);
|
termPQExpBuffer(&query);
|
||||||
|
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
{
|
{
|
||||||
log_debug("result status: %s", PQresStatus(PQresultStatus(res)));
|
|
||||||
log_error(_("unable to create replication set \"repmgr\""));
|
|
||||||
log_detail("%s", PQerrorMessage(conn));
|
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
23
dbutils.h
23
dbutils.h
@@ -29,9 +29,7 @@
|
|||||||
#include "voting.h"
|
#include "voting.h"
|
||||||
|
|
||||||
#define REPMGR_NODES_COLUMNS "n.node_id, n.type, n.upstream_node_id, n.node_name, n.conninfo, n.repluser, n.slot_name, n.location, n.priority, n.active, n.config_file, '' AS upstream_node_name "
|
#define REPMGR_NODES_COLUMNS "n.node_id, n.type, n.upstream_node_id, n.node_name, n.conninfo, n.repluser, n.slot_name, n.location, n.priority, n.active, n.config_file, '' AS upstream_node_name "
|
||||||
#define BDR2_NODES_COLUMNS "node_sysid, node_timeline, node_dboid, node_name, node_local_dsn, ''"
|
#define BDR_NODES_COLUMNS "node_sysid, node_timeline, node_dboid, node_status, node_name, node_local_dsn, node_init_from_dsn, node_read_only, node_seq_id"
|
||||||
#define BDR3_NODES_COLUMNS "ns.node_id, 0, 0, ns.node_name, ns.interface_connstr, ns.peer_state_name"
|
|
||||||
|
|
||||||
|
|
||||||
#define ERRBUFF_SIZE 512
|
#define ERRBUFF_SIZE 512
|
||||||
|
|
||||||
@@ -96,14 +94,6 @@ typedef enum
|
|||||||
SLOT_ACTIVE
|
SLOT_ACTIVE
|
||||||
} ReplSlotStatus;
|
} ReplSlotStatus;
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
BACKUP_STATE_UNKNOWN = -1,
|
|
||||||
BACKUP_STATE_IN_BACKUP,
|
|
||||||
BACKUP_STATE_NO_BACKUP
|
|
||||||
} BackupState;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Struct to store node information
|
* Struct to store node information
|
||||||
*/
|
*/
|
||||||
@@ -247,14 +237,18 @@ typedef struct s_bdr_node_info
|
|||||||
char node_sysid[MAXLEN];
|
char node_sysid[MAXLEN];
|
||||||
uint32 node_timeline;
|
uint32 node_timeline;
|
||||||
uint32 node_dboid;
|
uint32 node_dboid;
|
||||||
|
char node_status;
|
||||||
char node_name[MAXLEN];
|
char node_name[MAXLEN];
|
||||||
char node_local_dsn[MAXLEN];
|
char node_local_dsn[MAXLEN];
|
||||||
char peer_state_name[MAXLEN];
|
char node_init_from_dsn[MAXLEN];
|
||||||
|
bool read_only;
|
||||||
|
uint32 node_seq_id;
|
||||||
} t_bdr_node_info;
|
} t_bdr_node_info;
|
||||||
|
|
||||||
#define T_BDR_NODE_INFO_INITIALIZER { \
|
#define T_BDR_NODE_INFO_INITIALIZER { \
|
||||||
"", InvalidOid, InvalidOid, \
|
"", InvalidOid, InvalidOid, \
|
||||||
"", "", "" \
|
'?', "", "", "", \
|
||||||
|
false, -1 \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -398,7 +392,6 @@ int get_ready_archive_files(PGconn *conn, const char *data_directory);
|
|||||||
bool identify_system(PGconn *repl_conn, t_system_identification *identification);
|
bool identify_system(PGconn *repl_conn, t_system_identification *identification);
|
||||||
bool repmgrd_set_local_node_id(PGconn *conn, int local_node_id);
|
bool repmgrd_set_local_node_id(PGconn *conn, int local_node_id);
|
||||||
int repmgrd_get_local_node_id(PGconn *conn);
|
int repmgrd_get_local_node_id(PGconn *conn);
|
||||||
BackupState server_in_exclusive_backup_mode(PGconn *conn);
|
|
||||||
|
|
||||||
/* extension functions */
|
/* extension functions */
|
||||||
ExtensionStatus get_repmgr_extension_status(PGconn *conn);
|
ExtensionStatus get_repmgr_extension_status(PGconn *conn);
|
||||||
@@ -514,14 +507,12 @@ void get_node_replication_stats(PGconn *conn, int server_version_num, t_node_in
|
|||||||
bool is_downstream_node_attached(PGconn *conn, char *node_name);
|
bool is_downstream_node_attached(PGconn *conn, char *node_name);
|
||||||
|
|
||||||
/* BDR functions */
|
/* BDR functions */
|
||||||
int get_bdr_version_num(void);
|
|
||||||
void get_all_bdr_node_records(PGconn *conn, BdrNodeInfoList *node_list);
|
void get_all_bdr_node_records(PGconn *conn, BdrNodeInfoList *node_list);
|
||||||
RecordStatus get_bdr_node_record_by_name(PGconn *conn, const char *node_name, t_bdr_node_info *node_info);
|
RecordStatus get_bdr_node_record_by_name(PGconn *conn, const char *node_name, t_bdr_node_info *node_info);
|
||||||
bool is_bdr_db(PGconn *conn, PQExpBufferData *output);
|
bool is_bdr_db(PGconn *conn, PQExpBufferData *output);
|
||||||
bool is_bdr_db_quiet(PGconn *conn);
|
bool is_bdr_db_quiet(PGconn *conn);
|
||||||
bool is_active_bdr_node(PGconn *conn, const char *node_name);
|
bool is_active_bdr_node(PGconn *conn, const char *node_name);
|
||||||
bool is_bdr_repmgr(PGconn *conn);
|
bool is_bdr_repmgr(PGconn *conn);
|
||||||
char *get_default_bdr_replication_set(PGconn *conn);
|
|
||||||
bool is_table_in_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
bool is_table_in_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
||||||
bool add_table_to_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
bool add_table_to_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
||||||
void add_extension_tables_to_bdr_replication_set(PGconn *conn);
|
void add_extension_tables_to_bdr_replication_set(PGconn *conn);
|
||||||
|
|||||||
@@ -364,48 +364,4 @@
|
|||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
<sect1 id="packages-packager-info" xreflabel="Information for packagers">
|
|
||||||
<title>Information for packagers</title>
|
|
||||||
<indexterm>
|
|
||||||
<primary>packages</primary>
|
|
||||||
<secondary>information for packagers</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<para>
|
|
||||||
We recommend patching the following parameters when
|
|
||||||
building the package as built-in default values for user convenience.
|
|
||||||
These values can nevertheless be overridden by the user, if desired.
|
|
||||||
</para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Configuration file location: the default configuration file location
|
|
||||||
can be hard-coded by patching <varname>package_conf_file</varname>
|
|
||||||
in <filename>configfile.c</filename>:
|
|
||||||
<programlisting>
|
|
||||||
/* packagers: if feasible, patch configuration file path into "package_conf_file" */
|
|
||||||
char package_conf_file[MAXPGPATH] = "";</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
See also: <xref linkend="configuration-file">
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
PID file location: the default <application>repmgrd</application> PID file
|
|
||||||
location can be hard-coded by patching <varname>package_pid_file</varname>
|
|
||||||
in <filename>repmgrd.c</filename>:
|
|
||||||
<programlisting>
|
|
||||||
/* packagers: if feasible, patch PID file path into "package_pid_file" */
|
|
||||||
char package_pid_file[MAXPGPATH] = "";</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
See also: <xref linkend="repmgrd-pid-file">
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</sect1>
|
|
||||||
</appendix>
|
</appendix>
|
||||||
|
|||||||
@@ -15,203 +15,6 @@
|
|||||||
See also: <xref linkend="upgrading-repmgr">
|
See also: <xref linkend="upgrading-repmgr">
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<sect1 id="release-4.1.0">
|
|
||||||
<title>Release 4.1.0</title>
|
|
||||||
<para><emphasis>???? ??, 2018</emphasis></para>
|
|
||||||
<para>
|
|
||||||
&repmgr; 4.1.0 introduces some changes to <application>repmgrd</application>
|
|
||||||
behaviour and some additional configuration parameters.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This release can be installed as a simple package upgrade from repmgr 4.0 ~ 4.0.6.
|
|
||||||
The following post-upgrade steps must be carried out:
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application> (if running) must be restarted.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Execute <command>ALTER EXTENSION repmgr UPDATE</command>
|
|
||||||
on the primary server in the database where &repmgr; is installed.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
A restart of the PostgreSQL server is <emphasis>not</emphasis> required
|
|
||||||
for this release.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
See <xref linkend="upgrading-repmgr-extension"> for more details.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Configuration changes are backwards-compatible and no changes to
|
|
||||||
<filename>repmgr.conf</filename> are required. However users should
|
|
||||||
review the changes listed below.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<sect2>
|
|
||||||
<title>Configuration file changes</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Default for <xref linkend="repmgr-conf-log-level"> is now <option>INFO</option>.
|
|
||||||
This produces additional informative log output, without creating excessive additional
|
|
||||||
log file volume, and matches the setting assumed for examples in the documentation.
|
|
||||||
(GitHub #470).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<varname>recovery_min_apply_delay</varname> now accepts a minimum value
|
|
||||||
of <literal>zero</literal> (GitHub #448).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
|
|
||||||
<sect2>
|
|
||||||
<title>repmgr enhancements</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgr</application>: always exit with an error if an unrecognised
|
|
||||||
command line option is provided. This matches the behaviour of other PostgreSQL
|
|
||||||
utilities such as <application>psql</application>. (GitHub #464).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgr</application>: add <option>-q/--quiet</option> option to suppress non-error
|
|
||||||
output. (GitHub #468).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<command><link linkend="repmgr-cluster-show">repmgr cluster show</link></command>,
|
|
||||||
<command><link linkend="repmgr-node-check">repmgr node check</link></command> and
|
|
||||||
<command><link linkend="repmgr-node-status">repmgr node status</link></command>
|
|
||||||
return non-zero exit code if node status issues detected. (GitHub #456).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Add <option>--csv</option> output option for
|
|
||||||
<command><link linkend="repmgr-cluster-event">repmgr cluster event</link></command>.
|
|
||||||
(GitHub #471).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<command><link linkend="repmgr-witness-unregister">repmgr witness unregister</link></command>
|
|
||||||
can be run on any node, by providing the ID of the witness node with <option>--node-id</option>.
|
|
||||||
(GitHub #472).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<command><link linkend="repmgr-standby-switchover">repmgr standby switchover</link></command>
|
|
||||||
will refuse to run if an exclusive backup is taking place on the current primary.
|
|
||||||
(GitHub #476).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2>
|
|
||||||
<title>repmgrd enhancements</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application>: create a PID file by default
|
|
||||||
(GitHub #457). For details, see <xref linkend="repmgrd-pid-file">.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application>: daemonize process by default.
|
|
||||||
In case, for whatever reason, the user does not wish to daemonize the
|
|
||||||
process, provide <option>--daemonize=false</option>.
|
|
||||||
(GitHub #458).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
|
|
||||||
<sect2>
|
|
||||||
<title>Bug fixes</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<command><link linkend="repmgr-standby-register">repmgr standby register --wait-sync</link></command>:
|
|
||||||
fix behaviour when no timeout provided.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<command><link linkend="repmgr-cluster-cleanup">repmgr cluster cleanup</link></command>:
|
|
||||||
add missing help options. (GitHub #461/#462).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Ensure witness node follows new primary after switchover. (GitHub #453).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<command><link linkend="repmgr-node-check">repmgr node check</link></command> and
|
|
||||||
<command><link linkend="repmgr-node-status">repmgr node status</link></command>:
|
|
||||||
fix witness node handling. (GitHub #451).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
When using <command><link linkend="repmgr-standby-clone">repmgr standby clone</link></command>
|
|
||||||
with <option>--recovery-conf-only</option> and replication slots, ensure
|
|
||||||
<varname>primary_slot_name</varname> is set correctly. (GitHub #474).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
</sect1>
|
|
||||||
|
|
||||||
<sect1 id="release-4.0.6">
|
<sect1 id="release-4.0.6">
|
||||||
<title>Release 4.0.6</title>
|
<title>Release 4.0.6</title>
|
||||||
<para><emphasis>June 14, 2018</emphasis></para>
|
<para><emphasis>June 14, 2018</emphasis></para>
|
||||||
@@ -337,7 +140,7 @@
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Various documentation improvements, with particular emphasis on
|
Various documentation improvements, with particular emphasis on
|
||||||
the importance of setting appropriate <link linkend="configuration-file-service-commands">service commands</link>
|
the importance of setting appropriate <link linkend="configuration-service-commands">service commands</link>
|
||||||
instead of relying on <application>pg_ctl</application>.
|
instead of relying on <application>pg_ctl</application>.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
<sect1 id="configuration-file-log-settings" xreflabel="log settings">
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgr.conf</primary>
|
|
||||||
<secondary>log settings</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<indexterm>
|
|
||||||
<primary>log settings</primary>
|
|
||||||
<secondary>configuration in repmgr.conf</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<title>Log settings</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
By default, &repmgr; and <application>repmgrd</application> write log output to
|
|
||||||
<literal>STDERR</literal>. An alternative log destination can be specified
|
|
||||||
(either a file or <literal>syslog</literal>).
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
The &repmgr; application itself will continue to write log output to <literal>STDERR</literal>
|
|
||||||
even if another log destination is configured, as otherwise any output resulting from a command
|
|
||||||
line operation will "disappear" into the log.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This behaviour can be overriden with the command line option <option>--log-to-file</option>,
|
|
||||||
which will redirect all logging output to the configured log destination. This is recommended
|
|
||||||
when &repmgr; is executed by another application, particularly <application>repmgrd</application>,
|
|
||||||
to enable log output generated by the &repmgr; application to be stored for later reference.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
|
|
||||||
<varlistentry id="repmgr-conf-log-level" xreflabel="log_level">
|
|
||||||
<term><varname>log_level</varname> (<type>string</type>)
|
|
||||||
<indexterm>
|
|
||||||
<primary><varname>log_level</varname> configuration file parameter</primary>
|
|
||||||
</indexterm>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
One of <option>DEBUG</option>, <option>INFO</option>, <option>NOTICE</option>,
|
|
||||||
<option>WARNING</option>, <option>ERROR</option>, <option>ALERT</option>, <option>CRIT</option>
|
|
||||||
or <option>EMERG</option>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Default is <option>INFO</option>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Note that <option>DEBUG</option> will produce a substantial amount of log output
|
|
||||||
and should not be enabled in normal use.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry id="repmgr-conf-log-facility" xreflabel="log_facility">
|
|
||||||
<term><varname>log_facility</varname> (<type>string</type>)
|
|
||||||
<indexterm>
|
|
||||||
<primary><varname>log_facility</varname> configuration file parameter</primary>
|
|
||||||
</indexterm>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Logging facility: possible values are <option>STDERR</option> (default), or for
|
|
||||||
syslog integration, one of <option>LOCAL0</option>, <option>LOCAL1</option>, <option>...</option>,
|
|
||||||
<option>LOCAL7</option>, <option>USER</option>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry id="repmgr-conf-log-file" xreflabel="log_file">
|
|
||||||
<term><varname>log_file</varname> (<type>string</type>)
|
|
||||||
<indexterm>
|
|
||||||
<primary><varname>log_file</varname> configuration file parameter</primary>
|
|
||||||
</indexterm>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If <xref linkend="repmgr-conf-log-facility"> is set to <option>STDERR</option>, log output
|
|
||||||
can be redirected to the specified file.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
See <xref linkend="repmgrd-log-rotation"> for information on configuring log rotation.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry id="repmgr-conf-log-status-interval" xreflabel="log_status_interval">
|
|
||||||
<term><varname>log_status_interval</varname> (<type>integer</type>)
|
|
||||||
<indexterm>
|
|
||||||
<primary><varname>log_status_interval</varname> configuration file parameter</primary>
|
|
||||||
</indexterm>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This setting causes <application>repmgrd</application> to emit a status log
|
|
||||||
line at the specified interval (in seconds, default <literal>300</literal>)
|
|
||||||
describing <application>repmgrd</application>'s current state, e.g.:
|
|
||||||
</para>
|
|
||||||
<programlisting>
|
|
||||||
[2018-07-12 00:47:32] [INFO] monitoring connection to upstream node "node1" (node ID: 1)</programlisting>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</variablelist>
|
|
||||||
|
|
||||||
</sect1>
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
<sect1 id="configuration-file-settings" xreflabel="required configuration file settings">
|
<sect1 id="configuration-file-settings" xreflabel="configuration file settings">
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>repmgr.conf</primary>
|
<primary>repmgr.conf</primary>
|
||||||
<secondary>required settings</secondary>
|
<secondary>basic settings</secondary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<title>Required configuration file settings</title>
|
<title>Basic configuration file settings</title>
|
||||||
<para>
|
<para>
|
||||||
Each <filename>repmgr.conf</filename> file must contain the following parameters:
|
Each <filename>repmgr.conf</filename> file must contain the following parameters:
|
||||||
</para>
|
</para>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<sect1 id="configuration-file-service-commands" xreflabel="service command settings">
|
<sect1 id="configuration-service-commands" xreflabel="service command settings">
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>repmgr.conf</primary>
|
<primary>repmgr.conf</primary>
|
||||||
<secondary>service command settings</secondary>
|
<secondary>service command settings</secondary>
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
If using <application>systemd</application>, ensure you have <varname>RemoteIPC</varname> set to <literal>off</literal>.
|
If using <application>systemd</application>, ensure you have <varname>RemoveIPC</varname> set to <literal>off</literal>.
|
||||||
See the <ulink url="https://wiki.postgresql.org/wiki/Systemd">systemd</ulink>
|
See the <ulink url="https://wiki.postgresql.org/wiki/Systemd">systemd</ulink>
|
||||||
entry in the <ulink url="https://wiki.postgresql.org/wiki/Main_Page">PostgreSQL wiki</ulink> for details.
|
entry in the <ulink url="https://wiki.postgresql.org/wiki/Main_Page">PostgreSQL wiki</ulink> for details.
|
||||||
</para>
|
</para>
|
||||||
@@ -47,7 +47,6 @@
|
|||||||
service_restart_command
|
service_restart_command
|
||||||
service_reload_command</programlisting>
|
service_reload_command</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
It's also possible to specify a <varname>service_promote_command</varname>.
|
It's also possible to specify a <varname>service_promote_command</varname>.
|
||||||
@@ -57,7 +56,7 @@
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
If your packaging system does not provide such a command, it can be left empty,
|
If your packaging system does not provide such a command, it can be left empty,
|
||||||
and &repmgr; will generate the appropriate `pg_ctl ... promote` command.
|
and &repmgr; will generate the appropriate <command>pg_ctl ... promote</command> command.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Do not confuse this with <varname>promote_command</varname>, which is used
|
Do not confuse this with <varname>promote_command</varname>, which is used
|
||||||
@@ -65,6 +64,7 @@
|
|||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To confirm which command &repmgr; will execute for each action, use
|
To confirm which command &repmgr; will execute for each action, use
|
||||||
<command>repmgr node service --list --action=...</command>, e.g.:
|
<command>repmgr node service --list --action=...</command>, e.g.:
|
||||||
@@ -2,17 +2,16 @@
|
|||||||
<title>repmgr configuration</title>
|
<title>repmgr configuration</title>
|
||||||
|
|
||||||
&configuration-file;
|
&configuration-file;
|
||||||
&configuration-file-required-settings;
|
&configuration-file-settings;
|
||||||
&configuration-file-log-settings;
|
&configuration-service-commands;
|
||||||
&configuration-file-service-commands;
|
|
||||||
|
|
||||||
<sect1 id="configuration-permissions" xreflabel="Database user permissions">
|
<sect1 id="configuration-permissions" xreflabel="User permissions">
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>configuration</primary>
|
<primary>configuration</primary>
|
||||||
<secondary>database user permissions</secondary>
|
<secondary>user permissions</secondary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<title>repmgr database user permissions</title>
|
<title>repmgr user permissions</title>
|
||||||
<para>
|
<para>
|
||||||
&repmgr; will create an extension database containing objects
|
&repmgr; will create an extension database containing objects
|
||||||
for administering &repmgr; metadata. The user defined in the <varname>conninfo</varname>
|
for administering &repmgr; metadata. The user defined in the <varname>conninfo</varname>
|
||||||
|
|||||||
@@ -38,9 +38,8 @@
|
|||||||
<!ENTITY quickstart SYSTEM "quickstart.sgml">
|
<!ENTITY quickstart SYSTEM "quickstart.sgml">
|
||||||
<!ENTITY configuration SYSTEM "configuration.sgml">
|
<!ENTITY configuration SYSTEM "configuration.sgml">
|
||||||
<!ENTITY configuration-file SYSTEM "configuration-file.sgml">
|
<!ENTITY configuration-file SYSTEM "configuration-file.sgml">
|
||||||
<!ENTITY configuration-file-required-settings SYSTEM "configuration-file-required-settings.sgml">
|
<!ENTITY configuration-file-settings SYSTEM "configuration-file-settings.sgml">
|
||||||
<!ENTITY configuration-file-log-settings SYSTEM "configuration-file-log-settings.sgml">
|
<!ENTITY configuration-service-commands SYSTEM "configuration-service-commands.sgml">
|
||||||
<!ENTITY configuration-file-service-commands SYSTEM "configuration-file-service-commands.sgml">
|
|
||||||
<!ENTITY cloning-standbys SYSTEM "cloning-standbys.sgml">
|
<!ENTITY cloning-standbys SYSTEM "cloning-standbys.sgml">
|
||||||
<!ENTITY promoting-standby SYSTEM "promoting-standby.sgml">
|
<!ENTITY promoting-standby SYSTEM "promoting-standby.sgml">
|
||||||
<!ENTITY follow-new-primary SYSTEM "follow-new-primary.sgml">
|
<!ENTITY follow-new-primary SYSTEM "follow-new-primary.sgml">
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
For more information on the package contents, including details of installation
|
For more information on the package contents, including details of installation
|
||||||
paths and relevant <link linkend="configuration-file-service-commands">service commands</link>,
|
paths and relevant <link linkend="configuration-service-commands">service commands</link>,
|
||||||
see the appendix section <xref linkend="packages-centos">.
|
see the appendix section <xref linkend="packages-centos">.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ $ yum install repmgr10</programlisting>
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
For more information on the package contents, including details of installation
|
For more information on the package contents, including details of installation
|
||||||
paths and relevant <link linkend="configuration-file-service-commands">service commands</link>,
|
paths and relevant <link linkend="configuration-service-commands">service commands</link>,
|
||||||
see the appendix section <xref linkend="packages-debian-ubuntu">.
|
see the appendix section <xref linkend="packages-debian-ubuntu">.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
|||||||
@@ -234,7 +234,7 @@
|
|||||||
<para>
|
<para>
|
||||||
<filename>repmgr.conf</filename> should not be stored inside the PostgreSQL data directory,
|
<filename>repmgr.conf</filename> should not be stored inside the PostgreSQL data directory,
|
||||||
as it could be overwritten when setting up or reinitialising the PostgreSQL
|
as it could be overwritten when setting up or reinitialising the PostgreSQL
|
||||||
server. See sections <xref linkend="configuration"> and <xref linkend="configuration-file">
|
server. See sections on <xref linkend="configuration-file"> and <xref linkend="configuration-file-settings">
|
||||||
for further details about <filename>repmgr.conf</filename>.
|
for further details about <filename>repmgr.conf</filename>.
|
||||||
</para>
|
</para>
|
||||||
<tip>
|
<tip>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>ERR_NODE_STATUS (25)</option></term>
|
<term><option>ERR_CLUSTER_CHECK (25)</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
One or more nodes could not be reached.
|
One or more nodes could not be reached.
|
||||||
|
|||||||
@@ -49,22 +49,6 @@
|
|||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Output format</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<literal>--csv</literal>: generate output in CSV format. Note that the <literal>Details</literal>
|
|
||||||
column will currently not be emitted in CSV format.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Example</title>
|
<title>Example</title>
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -116,7 +116,7 @@
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>ERR_NODE_STATUS (25)</option></term>
|
<term><option>ERR_CLUSTER_CHECK (25)</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
One or more nodes could not be reached.
|
One or more nodes could not be reached.
|
||||||
|
|||||||
@@ -113,40 +113,4 @@
|
|||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Exit codes</title>
|
|
||||||
<para>
|
|
||||||
Following exit codes can be emitted by <command>repmgr cluster show</command>:
|
|
||||||
</para>
|
|
||||||
<variablelist>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>SUCCESS (0)</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
No issues were detected.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>ERR_NODE_STATUS (25)</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
One or more issues were detected.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</variablelist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>See also</title>
|
|
||||||
<para>
|
|
||||||
<xref linkend="repmgr-node-status">, <xref linkend="repmgr-node-check">
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|||||||
@@ -61,9 +61,7 @@
|
|||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara>
|
<simpara>
|
||||||
<literal>--archive-ready</literal>: checks for WAL files which have not yet been archived,
|
<literal>--archive-ready</literal>: checks for WAL files which have not yet been archived
|
||||||
and returns <literal>WARNING</literal> or <literal>CRITICAL</literal> if the number
|
|
||||||
exceeds <varname>archive_ready_warning</varname> or <varname>archive_ready_critical</varname> respectively.
|
|
||||||
</simpara>
|
</simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
@@ -79,12 +77,6 @@
|
|||||||
</simpara>
|
</simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<literal>--missing-slots</literal>: checks there are no missing replication slots
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
@@ -109,80 +101,4 @@
|
|||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Exit codes</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
When executing <command>repmgr node check</command> with one of the individual
|
|
||||||
checks listed above, &repmgr; will emit one of the following Nagios-style exit codes
|
|
||||||
(even if <literal>--nagios</literal> is not supplied):
|
|
||||||
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<literal>0</literal>: OK
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<literal>1</literal>: WARNING
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<literal>2</literal>: ERROR
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<literal>3</literal>: UNKNOWN
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Following exit codes can be emitted by <command>repmgr status check</command>
|
|
||||||
if no individual check was specified.
|
|
||||||
</para>
|
|
||||||
<variablelist>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>SUCCESS (0)</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
No issues were detected.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>ERR_NODE_STATUS (25)</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
One or more issues were detected.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</variablelist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>See also</title>
|
|
||||||
<para>
|
|
||||||
<xref linkend="repmgr-node-status">, <xref linkend="repmgr-cluster-show">
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|||||||
@@ -115,24 +115,7 @@
|
|||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
<refsect1>
|
|
||||||
<title>Configuration file settings</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<literal>node_rejoin_timeout</literal>:
|
|
||||||
the maximum length of time (in seconds) to wait for
|
|
||||||
the node to reconnect to the replication cluster (defaults to
|
|
||||||
the value set in <literal>standby_reconnect_timeout</literal>,
|
|
||||||
60 seconds).
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</refsect1>
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Event notifications</title>
|
<title>Event notifications</title>
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -52,40 +52,10 @@
|
|||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Exit codes</title>
|
|
||||||
<para>
|
|
||||||
Following exit codes can be emitted by <command>repmgr node status</command>:
|
|
||||||
</para>
|
|
||||||
<variablelist>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>SUCCESS (0)</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
No issues were detected.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>ERR_NODE_STATUS (25)</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
One or more issues were detected.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</variablelist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>See also</title>
|
<title>See also</title>
|
||||||
<para>
|
<para>
|
||||||
See <xref linkend="repmgr-node-check"> to diagnose issues and <xref linkend="repmgr-cluster-show">
|
See <xref linkend="repmgr-node-check"> to diagnose issues.
|
||||||
for an overview of all nodes in the cluster.
|
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<title>Description</title>
|
<title>Description</title>
|
||||||
<para>
|
<para>
|
||||||
<command>repmgr primary register</command> registers a primary node in a
|
<command>repmgr primary register</command> registers a primary node in a
|
||||||
streaming replication cluster, and configures it for use with &repmgr;, including
|
streaming replication cluster, and configures it for use with repmgr, including
|
||||||
installing the &repmgr; extension. This command needs to be executed before any
|
installing the &repmgr; extension. This command needs to be executed before any
|
||||||
standby nodes are registered.
|
standby nodes are registered.
|
||||||
</para>
|
</para>
|
||||||
|
|||||||
@@ -213,15 +213,6 @@
|
|||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>-d, --dbname=CONNINFO</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Connection string of the upstream node to use for cloning.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--dry-run</option></term>
|
<term><option>--dry-run</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
|||||||
@@ -46,9 +46,6 @@
|
|||||||
<application>repmgrd</application> should not be active on any nodes while a switchover is being
|
<application>repmgrd</application> should not be active on any nodes while a switchover is being
|
||||||
executed. This restriction may be lifted in a later version.
|
executed. This restriction may be lifted in a later version.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
|
||||||
&repmgr; will not perform the switchover if an exclusive backup is running on the current primary.
|
|
||||||
</para>
|
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
@@ -166,8 +163,8 @@
|
|||||||
<listitem>
|
<listitem>
|
||||||
<simpara>
|
<simpara>
|
||||||
<literal>standby_reconnect_timeout</literal>:
|
<literal>standby_reconnect_timeout</literal>:
|
||||||
number of seconds to attempt to wait for the demoted primary
|
Number of seconds to attempt to reconnect to the demoted primary
|
||||||
to reconnect to the promoted primary (default: 60 seconds)
|
once it has been restarted.
|
||||||
</simpara>
|
</simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,7 @@
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The node does not have to be running to be unregistered, however if this is the
|
The node does not have to be running to be unregistered, however if this is the
|
||||||
case then either provide connection information for the primary server, or
|
case then connection information for the primary server must be provided.
|
||||||
execute <command>repmgr witness unregister</command> on a running node and
|
|
||||||
provide the parameter <option>--node-id</option> with the node ID of the
|
|
||||||
witness server.
|
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Execute with the <literal>--dry-run</literal> option to check what would happen
|
Execute with the <literal>--dry-run</literal> option to check what would happen
|
||||||
@@ -39,17 +36,17 @@
|
|||||||
INFO: connecting to witness node "node3" (ID: 3)
|
INFO: connecting to witness node "node3" (ID: 3)
|
||||||
INFO: unregistering witness node 3
|
INFO: unregistering witness node 3
|
||||||
INFO: witness unregistration complete
|
INFO: witness unregistration complete
|
||||||
DETAIL: witness node with UD 3 successfully unregistered</programlisting>
|
DETAIL: witness node with id 3 (conninfo: host=node3 dbname=repmgr user=repmgr port=5499) successfully unregistered</programlisting>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Unregistering a non-running witness node:
|
Unregistering a non-running witness node:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
$ repmgr -f /etc/repmgr.conf witness unregister -h node1 -p 5501 -F
|
$ repmgr -f /etc/repmgr.conf witness unregister -h node1 -p 5501 -F
|
||||||
INFO: connecting to node "node3" (ID: 3)
|
INFO: connecting to witness node "node3" (ID: 3)
|
||||||
NOTICE: unable to connect to node "node3" (ID: 3), removing node record on cluster primary only
|
NOTICE: unable to connect to witness node "node3" (ID: 3), removing node record on cluster primary only
|
||||||
INFO: unregistering witness node 3
|
INFO: unregistering witness node 3
|
||||||
INFO: witness unregistration complete
|
INFO: witness unregistration complete
|
||||||
DETAIL: witness node with id ID 3 successfully unregistered</programlisting>
|
DETAIL: witness node with id 3 (conninfo: host=node3 dbname=repmgr user=repmgr port=5499) successfully unregistered</programlisting>
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
@@ -65,32 +62,6 @@
|
|||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
|
|
||||||
<title>Options</title>
|
|
||||||
<variablelist>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--dry-run</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Check prerequisites but don't actually unregister the witness.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--node-id</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Unregister witness server with the specified node ID.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</variablelist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Event notifications</title>
|
<title>Event notifications</title>
|
||||||
|
|||||||
@@ -25,7 +25,13 @@
|
|||||||
<para>
|
<para>
|
||||||
This is the official documentation of &repmgr; &repmgrversion; for
|
This is the official documentation of &repmgr; &repmgrversion; for
|
||||||
use with PostgreSQL 9.3 - PostgreSQL 10.
|
use with PostgreSQL 9.3 - PostgreSQL 10.
|
||||||
It describes the functionality supported by the current version of &repmgr;.
|
</para>
|
||||||
|
<para>
|
||||||
|
&repmgr; is being continually developed and we strongly recommend using the
|
||||||
|
latest version. Please check the
|
||||||
|
<ulink url="https://repmgr.org/">repmgr website</ulink> for details
|
||||||
|
about the current &repmgr; version as well as the
|
||||||
|
<ulink url="https://repmgr.org/docs/current/index.html">current documentation</ulink>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
To use <application>repmgrd</application>, its associated function library <emphasis>must</emphasis> be
|
To use <application>repmgrd</application>, its associated function library <emphasis>must</emphasis> be
|
||||||
included via <filename>postgresql.conf</filename> with:
|
included in <filename>postgresql.conf</filename> with:
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
shared_preload_libraries = 'repmgr'</programlisting>
|
shared_preload_libraries = 'repmgr'</programlisting>
|
||||||
@@ -52,7 +52,6 @@
|
|||||||
running <application>repmgrd</application> daemon.
|
running <application>repmgrd</application> daemon.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
|
||||||
<sect2 id="repmgrd-automatic-failover-configuration">
|
<sect2 id="repmgrd-automatic-failover-configuration">
|
||||||
<title>automatic failover configuration</title>
|
<title>automatic failover configuration</title>
|
||||||
<para>
|
<para>
|
||||||
@@ -131,7 +130,7 @@
|
|||||||
particularly on <application>systemd</application>-based systems.
|
particularly on <application>systemd</application>-based systems.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
For more details, see <xref linkend="configuration-file-service-commands">.
|
For more details, see <xref linkend="configuration-service-commands">.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
@@ -178,63 +177,10 @@
|
|||||||
<para>
|
<para>
|
||||||
<application>repmgrd</application> can be started manually like this:
|
<application>repmgrd</application> can be started manually like this:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
repmgrd -f /etc/repmgr.conf --pid-file /tmp/repmgrd.pid</programlisting>
|
repmgrd -f /etc/repmgr.conf --pid-file /tmp/repmgrd.pid --daemonize</programlisting>
|
||||||
and stopped with <command>kill `cat /tmp/repmgrd.pid`</command>. Adjust paths as appropriate.
|
and stopped with <command>kill `cat /tmp/repmgrd.pid`</command>. Adjust paths as appropriate.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<sect2 id="repmgrd-pid-file" xreflabel="repmgrd's PID file">
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgrd</primary>
|
|
||||||
<secondary>PID file</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<indexterm>
|
|
||||||
<primary>PID file</primary>
|
|
||||||
<secondary>repmgrd</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<title>repmgrd's PID file</title>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application> will generate a PID file by default.
|
|
||||||
</para>
|
|
||||||
<note>
|
|
||||||
<simpara>
|
|
||||||
This is a behaviour change from previous versions (earlier than 4.1), where
|
|
||||||
the PID file had to be explicitly specified with the command line
|
|
||||||
parameter <option> --pid-file</option>.
|
|
||||||
</simpara>
|
|
||||||
</note>
|
|
||||||
<para>
|
|
||||||
The PID file can be specified in <filename>repmgr.conf</filename> with the configuration
|
|
||||||
parameter <varname>repmgrd_pid_file</varname>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
It can also be specified on the command line (as in previous versions) with
|
|
||||||
the command line parameter <option>--pid-file</option>. Note this will override
|
|
||||||
any value set in <filename>repmgr.conf</filename> with <varname>repmgrd_pid_file</varname>.
|
|
||||||
<option>--pid-file</option> may be deprecated in future releases.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If a PID file location was specified by the package maintainer, <application>repmgrd</application>
|
|
||||||
will use that. This only applies if &repmgr; was installed from a package and the package
|
|
||||||
maintainer has specified the PID file location.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If none of the above apply, <application>repmgrd</application> will create a PID file
|
|
||||||
in the operating system's temporary directory (das etermined by the environment variable
|
|
||||||
<varname>TMPDIR</varname>, or if that is not set, will use <filename>/tmp</filename>).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To prevent a PID file being generated at all, provide the command line option
|
|
||||||
<option>--no-pid-file</option>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To see which PID file <application>repmgrd</application> would use, execute <application>repmgrd</application>
|
|
||||||
with the option <option>--show-pid-file</option>. <application>repmgrd</application>
|
|
||||||
will not start if this option is provided. Note that the value shown is the
|
|
||||||
file <application>repmgrd</application> would use next time it starts, and is
|
|
||||||
not necessarily the PID file currently in use.
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2 id="repmgrd-configuration-debian-ubuntu">
|
<sect2 id="repmgrd-configuration-debian-ubuntu">
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>repmgrd</primary>
|
<primary>repmgrd</primary>
|
||||||
|
|||||||
@@ -104,7 +104,7 @@
|
|||||||
server.
|
server.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
For more details, see <xref linkend="configuration-file-service-commands">.
|
For more details, see <xref linkend="configuration-service-commands">.
|
||||||
</para>
|
</para>
|
||||||
</important>
|
</important>
|
||||||
|
|
||||||
@@ -121,18 +121,12 @@
|
|||||||
</simpara>
|
</simpara>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Check that access from applications is minimalized or preferably blocked
|
Check that access from applications is minimalized or preferably blocked
|
||||||
completely, so applications are not unexpectedly interrupted.
|
completely, so applications are not unexpectedly interrupted.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
If an exclusive backup is running on the current primary, &repmgr; will not perform the
|
|
||||||
switchover.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Check there is no significant replication lag on standbys attached to the
|
Check there is no significant replication lag on standbys attached to the
|
||||||
current primary.
|
current primary.
|
||||||
@@ -153,7 +147,6 @@
|
|||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Finally, consider executing <command>repmgr standby switchover</command> with the
|
Finally, consider executing <command>repmgr standby switchover</command> with the
|
||||||
<literal>--dry-run</literal> option; this will perform any necessary checks and inform you about
|
<literal>--dry-run</literal> option; this will perform any necessary checks and inform you about
|
||||||
|
|||||||
@@ -29,18 +29,8 @@
|
|||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara>
|
<simpara>
|
||||||
<application>repmgrd</application> (if running) must be restarted.
|
In the database where the &repmgr; extension is installed, execute
|
||||||
</simpara>
|
<command>ALTER EXTENSION repmgr UPDATE</command>.
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
For major releases, e.g. from <literal>4.0.x</literal> to <literal>4.1</literal>,
|
|
||||||
execute <command>ALTER EXTENSION repmgr UPDATE</command>
|
|
||||||
on the primary node in the database where the &repmgr; extension is installed.
|
|
||||||
</simpara>
|
|
||||||
<simpara>
|
|
||||||
This will update the extension metadata and, if necessary, apply
|
|
||||||
changes to the &repmgr; extension objects.
|
|
||||||
</simpara>
|
</simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
</orderedlist>
|
</orderedlist>
|
||||||
@@ -51,6 +41,10 @@
|
|||||||
release as they may contain upgrade instructions particular to individual versions.
|
release as they may contain upgrade instructions particular to individual versions.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If the <application>repmgrd</application> daemon is in use, we recommend stopping it
|
||||||
|
before upgrading &repmgr;.
|
||||||
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Note that it may be necessary to restart the PostgreSQL server if the upgrade contains
|
Note that it may be necessary to restart the PostgreSQL server if the upgrade contains
|
||||||
changes to the shared object file used by <application>repmgrd</application>; check the
|
changes to the shared object file used by <application>repmgrd</application>; check the
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<!ENTITY repmgrversion "4.1.0">
|
<!ENTITY repmgrversion "4.0.6">
|
||||||
|
|||||||
@@ -46,6 +46,6 @@
|
|||||||
#define ERR_SWITCHOVER_INCOMPLETE 22
|
#define ERR_SWITCHOVER_INCOMPLETE 22
|
||||||
#define ERR_FOLLOW_FAIL 23
|
#define ERR_FOLLOW_FAIL 23
|
||||||
#define ERR_REJOIN_FAIL 24
|
#define ERR_REJOIN_FAIL 24
|
||||||
#define ERR_NODE_STATUS 25
|
#define ERR_CLUSTER_CHECK 25
|
||||||
|
|
||||||
#endif /* _ERRCODE_H_ */
|
#endif /* _ERRCODE_H_ */
|
||||||
|
|||||||
12
log.c
12
log.c
@@ -42,7 +42,7 @@ _stderr_log_with_level(const char *level_name, int level, const char *fmt, va_li
|
|||||||
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
|
||||||
|
|
||||||
int log_type = REPMGR_STDERR;
|
int log_type = REPMGR_STDERR;
|
||||||
int log_level = LOG_INFO;
|
int log_level = LOG_NOTICE;
|
||||||
int last_log_level = LOG_INFO;
|
int last_log_level = LOG_INFO;
|
||||||
int verbose_logging = false;
|
int verbose_logging = false;
|
||||||
int terse_logging = false;
|
int terse_logging = false;
|
||||||
@@ -70,7 +70,7 @@ _stderr_log_with_level(const char *level_name, int level, const char *fmt, va_li
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Store the requested level so that if there's a subsequent log_hint() or
|
* Store the requested level so that if there's a subsequent log_hint() or
|
||||||
* log_detail(), we can suppress that if --terse was specified,
|
* log_detail(), we can suppress that if appropriate.
|
||||||
*/
|
*/
|
||||||
last_log_level = level;
|
last_log_level = level;
|
||||||
|
|
||||||
@@ -329,13 +329,6 @@ logger_set_terse(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
logger_set_level(int new_log_level)
|
|
||||||
{
|
|
||||||
log_level = new_log_level;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
logger_set_min_level(int min_log_level)
|
logger_set_min_level(int min_log_level)
|
||||||
{
|
{
|
||||||
@@ -343,7 +336,6 @@ logger_set_min_level(int min_log_level)
|
|||||||
log_level = min_log_level;
|
log_level = min_log_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
detect_log_level(const char *level)
|
detect_log_level(const char *level)
|
||||||
{
|
{
|
||||||
|
|||||||
1
log.h
1
log.h
@@ -129,7 +129,6 @@ bool logger_shutdown(void);
|
|||||||
void logger_set_verbose(void);
|
void logger_set_verbose(void);
|
||||||
void logger_set_terse(void);
|
void logger_set_terse(void);
|
||||||
void logger_set_min_level(int min_log_level);
|
void logger_set_min_level(int min_log_level);
|
||||||
void logger_set_level(int new_log_level);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
log_detail(const char *fmt,...)
|
log_detail(const char *fmt,...)
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
|
||||||
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
|
||||||
167
repmgr--4.1.sql
167
repmgr--4.1.sql
@@ -1,167 +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
|
|
||||||
);
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
DO $repmgr$
|
|
||||||
DECLARE
|
|
||||||
DECLARE server_version_num INT;
|
|
||||||
BEGIN
|
|
||||||
SELECT setting
|
|
||||||
FROM pg_catalog.pg_settings
|
|
||||||
WHERE name = 'server_version_num'
|
|
||||||
INTO server_version_num;
|
|
||||||
IF server_version_num >= 90400 THEN
|
|
||||||
EXECUTE $repmgr_func$
|
|
||||||
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
|
|
||||||
)
|
|
||||||
$repmgr_func$;
|
|
||||||
ELSE
|
|
||||||
EXECUTE $repmgr_func$
|
|
||||||
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 TEXT NOT NULL,
|
|
||||||
last_wal_standby_location TEXT,
|
|
||||||
replication_lag BIGINT NOT NULL,
|
|
||||||
apply_lag BIGINT NOT NULL
|
|
||||||
)
|
|
||||||
$repmgr_func$;
|
|
||||||
END IF;
|
|
||||||
END$repmgr$;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
/* XXX update upgrade scripts! */
|
|
||||||
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', 'set_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_local_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'get_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION standby_set_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'standby_set_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION standby_get_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'standby_get_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
/* failover functions */
|
|
||||||
|
|
||||||
CREATE FUNCTION notify_follow_primary(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'notify_follow_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_new_primary()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'get_new_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION reset_voting_status()
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'reset_voting_status'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION am_bdr_failover_handler(INT)
|
|
||||||
RETURNS BOOL
|
|
||||||
AS 'MODULE_PATHNAME', 'am_bdr_failover_handler'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION unset_bdr_failover_handler()
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'unset_bdr_failover_handler'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
@@ -83,10 +83,9 @@ do_bdr_register(void)
|
|||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BDR 2 implementation is for 2 nodes only */
|
if (bdr_nodes.node_count > 2)
|
||||||
if (get_bdr_version_num() < 3 && bdr_nodes.node_count > 2)
|
|
||||||
{
|
{
|
||||||
log_error(_("repmgr can only support BDR 2.x clusters with 2 nodes"));
|
log_error(_("repmgr can only support BDR clusters with 2 nodes"));
|
||||||
log_detail(_("this BDR cluster has %i nodes"), bdr_nodes.node_count);
|
log_detail(_("this BDR cluster has %i nodes"), bdr_nodes.node_count);
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
pfree(dbname);
|
pfree(dbname);
|
||||||
@@ -177,7 +176,6 @@ do_bdr_register(void)
|
|||||||
|
|
||||||
if (bdr_node_has_repmgr_set(conn, config_file_options.node_name) == false)
|
if (bdr_node_has_repmgr_set(conn, config_file_options.node_name) == false)
|
||||||
{
|
{
|
||||||
log_debug("bdr_node_has_repmgr_set() = false");
|
|
||||||
bdr_node_set_repmgr_set(conn, config_file_options.node_name);
|
bdr_node_set_repmgr_set(conn, config_file_options.node_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +201,6 @@ do_bdr_register(void)
|
|||||||
if (bdr_nodes.node_count == 0)
|
if (bdr_nodes.node_count == 0)
|
||||||
{
|
{
|
||||||
log_error(_("unable to retrieve any BDR node records"));
|
log_error(_("unable to retrieve any BDR node records"));
|
||||||
log_detail("%s", PQerrorMessage(conn));
|
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
@@ -255,35 +252,7 @@ do_bdr_register(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Add the repmgr extension tables to a replication set */
|
/* Add the repmgr extension tables to a replication set */
|
||||||
|
|
||||||
if (get_bdr_version_num() < 3)
|
|
||||||
{
|
|
||||||
add_extension_tables_to_bdr_replication_set(conn);
|
add_extension_tables_to_bdr_replication_set(conn);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* this is the only table we need to replicate */
|
|
||||||
char *replication_set = get_default_bdr_replication_set(conn);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* this probably won't happen, but we need to be sure we're using
|
|
||||||
* the replication set metadata correctly...
|
|
||||||
*/
|
|
||||||
if (conn == NULL)
|
|
||||||
{
|
|
||||||
log_error(_("unable to retrieve default BDR replication set"));
|
|
||||||
log_hint(_("see preceding messages"));
|
|
||||||
log_debug("check query in get_default_bdr_replication_set()");
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_table_in_bdr_replication_set(conn, "nodes", replication_set) == false)
|
|
||||||
{
|
|
||||||
add_table_to_bdr_replication_set(conn, "nodes", replication_set);
|
|
||||||
}
|
|
||||||
|
|
||||||
pfree(replication_set);
|
|
||||||
}
|
|
||||||
|
|
||||||
initPQExpBuffer(&event_details);
|
initPQExpBuffer(&event_details);
|
||||||
|
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ do_cluster_show(void)
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
ItemList warnings = {NULL, NULL};
|
ItemList warnings = {NULL, NULL};
|
||||||
bool success = false;
|
bool success = false;
|
||||||
bool error_found = false;
|
|
||||||
|
|
||||||
/* Connect to local database to obtain cluster connection data */
|
/* Connect to local database to obtain cluster connection data */
|
||||||
log_verbose(LOG_INFO, _("connecting to database"));
|
log_verbose(LOG_INFO, _("connecting to database"));
|
||||||
@@ -219,7 +218,6 @@ do_cluster_show(void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(&details, "- failed");
|
appendPQExpBuffer(&details, "- failed");
|
||||||
error_found = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,7 +281,6 @@ do_cluster_show(void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(&details, "- failed");
|
appendPQExpBuffer(&details, "- failed");
|
||||||
error_found = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,27 +292,17 @@ do_cluster_show(void)
|
|||||||
if (cell->node_info->node_status == NODE_STATUS_UP)
|
if (cell->node_info->node_status == NODE_STATUS_UP)
|
||||||
{
|
{
|
||||||
if (cell->node_info->active == true)
|
if (cell->node_info->active == true)
|
||||||
{
|
|
||||||
appendPQExpBuffer(&details, "* running");
|
appendPQExpBuffer(&details, "* running");
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
appendPQExpBuffer(&details, "! running");
|
appendPQExpBuffer(&details, "! running");
|
||||||
error_found = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* node is unreachable */
|
/* node is unreachable */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (cell->node_info->active == true)
|
if (cell->node_info->active == true)
|
||||||
{
|
|
||||||
appendPQExpBuffer(&details, "? unreachable");
|
appendPQExpBuffer(&details, "? unreachable");
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
appendPQExpBuffer(&details, "- failed");
|
appendPQExpBuffer(&details, "- failed");
|
||||||
error_found = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -323,7 +310,6 @@ do_cluster_show(void)
|
|||||||
{
|
{
|
||||||
/* this should never happen */
|
/* this should never happen */
|
||||||
appendPQExpBuffer(&details, "? unknown node type");
|
appendPQExpBuffer(&details, "? unknown node type");
|
||||||
error_found = true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -428,6 +414,7 @@ do_cluster_show(void)
|
|||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
|
|
||||||
/* emit any warnings */
|
/* emit any warnings */
|
||||||
|
|
||||||
if (warnings.head != NULL && runtime_options.terse == false && runtime_options.output_mode != OM_CSV)
|
if (warnings.head != NULL && runtime_options.terse == false && runtime_options.output_mode != OM_CSV)
|
||||||
{
|
{
|
||||||
ItemListCell *cell = NULL;
|
ItemListCell *cell = NULL;
|
||||||
@@ -438,20 +425,6 @@ do_cluster_show(void)
|
|||||||
printf(_(" - %s\n"), cell->string);
|
printf(_(" - %s\n"), cell->string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If warnings were noted, even if they're not displayed (e.g. in --csv node),
|
|
||||||
* that means something's not right so we need to emit a non-zero exit code.
|
|
||||||
*/
|
|
||||||
if (warnings.head != NULL)
|
|
||||||
{
|
|
||||||
error_found = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error_found == true)
|
|
||||||
{
|
|
||||||
exit(ERR_NODE_STATUS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -463,7 +436,6 @@ do_cluster_show(void)
|
|||||||
* --all
|
* --all
|
||||||
* --node-[id|name]
|
* --node-[id|name]
|
||||||
* --event
|
* --event
|
||||||
* --csv
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -508,12 +480,8 @@ do_cluster_event(void)
|
|||||||
strncpy(headers_event[EV_TIMESTAMP].title, _("Timestamp"), MAXLEN);
|
strncpy(headers_event[EV_TIMESTAMP].title, _("Timestamp"), MAXLEN);
|
||||||
strncpy(headers_event[EV_DETAILS].title, _("Details"), MAXLEN);
|
strncpy(headers_event[EV_DETAILS].title, _("Details"), MAXLEN);
|
||||||
|
|
||||||
/*
|
/* if --terse provided, simply omit the "Details" column */
|
||||||
* If --terse or --csv provided, simply omit the "Details" column.
|
if (runtime_options.terse == true)
|
||||||
* In --csv mode we'd need to quote/escape the contents "Details" column,
|
|
||||||
* which is doable but which will remain a TODO for now.
|
|
||||||
*/
|
|
||||||
if (runtime_options.terse == true || runtime_options.output_mode == OM_CSV)
|
|
||||||
column_count --;
|
column_count --;
|
||||||
|
|
||||||
for (i = 0; i < column_count; i++)
|
for (i = 0; i < column_count; i++)
|
||||||
@@ -536,8 +504,6 @@ do_cluster_event(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtime_options.output_mode == OM_TEXT)
|
|
||||||
{
|
|
||||||
for (i = 0; i < column_count; i++)
|
for (i = 0; i < column_count; i++)
|
||||||
{
|
{
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
@@ -565,25 +531,11 @@ do_cluster_event(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < PQntuples(res); i++)
|
for (i = 0; i < PQntuples(res); i++)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
if (runtime_options.output_mode == OM_CSV)
|
|
||||||
{
|
|
||||||
for (j = 0; j < column_count; j++)
|
|
||||||
{
|
|
||||||
printf("%s", PQgetvalue(res, i, j));
|
|
||||||
if ((j + 1) < column_count)
|
|
||||||
{
|
|
||||||
printf(",");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf(" ");
|
printf(" ");
|
||||||
for (j = 0; j < column_count; j++)
|
for (j = 0; j < column_count; j++)
|
||||||
{
|
{
|
||||||
@@ -594,7 +546,6 @@ do_cluster_event(void)
|
|||||||
if (j < (column_count - 1))
|
if (j < (column_count - 1))
|
||||||
printf(" | ");
|
printf(" | ");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
@@ -603,7 +554,6 @@ do_cluster_event(void)
|
|||||||
|
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
|
|
||||||
if (runtime_options.output_mode == OM_TEXT)
|
|
||||||
puts("");
|
puts("");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -746,7 +696,7 @@ do_cluster_crosscheck(void)
|
|||||||
|
|
||||||
if (error_found == true)
|
if (error_found == true)
|
||||||
{
|
{
|
||||||
exit(ERR_NODE_STATUS);
|
exit(ERR_CLUSTER_CHECK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -836,7 +786,7 @@ do_cluster_matrix()
|
|||||||
|
|
||||||
if (error_found == true)
|
if (error_found == true)
|
||||||
{
|
{
|
||||||
exit(ERR_NODE_STATUS);
|
exit(ERR_CLUSTER_CHECK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1397,7 +1347,6 @@ do_cluster_help(void)
|
|||||||
printf(_(" %s [OPTIONS] cluster matrix\n"), progname());
|
printf(_(" %s [OPTIONS] cluster matrix\n"), progname());
|
||||||
printf(_(" %s [OPTIONS] cluster crosscheck\n"), progname());
|
printf(_(" %s [OPTIONS] cluster crosscheck\n"), progname());
|
||||||
printf(_(" %s [OPTIONS] cluster event\n"), progname());
|
printf(_(" %s [OPTIONS] cluster event\n"), progname());
|
||||||
printf(_(" %s [OPTIONS] cluster cleanup\n"), progname());
|
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
printf(_("CLUSTER SHOW\n"));
|
printf(_("CLUSTER SHOW\n"));
|
||||||
@@ -1437,7 +1386,6 @@ do_cluster_help(void)
|
|||||||
printf(_(" --event filter specific event\n"));
|
printf(_(" --event filter specific event\n"));
|
||||||
printf(_(" --node-id restrict entries to node with this ID\n"));
|
printf(_(" --node-id restrict entries to node with this ID\n"));
|
||||||
printf(_(" --node-name restrict entries to node with this name\n"));
|
printf(_(" --node-name restrict entries to node with this name\n"));
|
||||||
printf(_(" --csv emit output as CSV\n"));
|
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
printf(_("CLUSTER CLEANUP\n"));
|
printf(_("CLUSTER CLEANUP\n"));
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ static CheckStatus do_node_check_downstream(PGconn *conn, OutputMode mode, Check
|
|||||||
static CheckStatus do_node_check_replication_lag(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
static CheckStatus do_node_check_replication_lag(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
||||||
static CheckStatus do_node_check_role(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
static CheckStatus do_node_check_role(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_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);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NODE STATUS
|
* NODE STATUS
|
||||||
@@ -170,17 +169,11 @@ do_node_status(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* "archive_mode" is not "off", i.e. one of "on", "always" */
|
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
PQExpBufferData archiving_status;
|
PQExpBufferData archiving_status;
|
||||||
char archive_command[MAXLEN] = "";
|
char archive_command[MAXLEN] = "";
|
||||||
|
|
||||||
initPQExpBuffer(&archiving_status);
|
initPQExpBuffer(&archiving_status);
|
||||||
|
|
||||||
/*
|
|
||||||
* if the node is a standby, and "archive_mode" is "on", archiving will
|
|
||||||
* actually be disabled.
|
|
||||||
*/
|
|
||||||
if (recovery_type == RECTYPE_STANDBY)
|
if (recovery_type == RECTYPE_STANDBY)
|
||||||
{
|
{
|
||||||
if (guc_set(conn, "archive_mode", "=", "on"))
|
if (guc_set(conn, "archive_mode", "=", "on"))
|
||||||
@@ -258,55 +251,6 @@ do_node_status(void)
|
|||||||
"disabled");
|
"disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for attached nodes */
|
|
||||||
{
|
|
||||||
NodeInfoList downstream_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
|
||||||
NodeInfoListCell *node_cell = NULL;
|
|
||||||
ItemList missing_nodes = {NULL, NULL};
|
|
||||||
int missing_nodes_count = 0;
|
|
||||||
int expected_nodes_count = 0;
|
|
||||||
|
|
||||||
get_downstream_node_records(conn, config_file_options.node_id, &downstream_nodes);
|
|
||||||
|
|
||||||
/* if a witness node is present, we'll need to remove this from the total */
|
|
||||||
expected_nodes_count = downstream_nodes.node_count;
|
|
||||||
|
|
||||||
for (node_cell = downstream_nodes.head; node_cell; node_cell = node_cell->next)
|
|
||||||
{
|
|
||||||
/* skip witness server */
|
|
||||||
if (node_cell->node_info->type == WITNESS)
|
|
||||||
{
|
|
||||||
expected_nodes_count --;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_downstream_node_attached(conn, node_cell->node_info->node_name) == false)
|
|
||||||
{
|
|
||||||
missing_nodes_count++;
|
|
||||||
item_list_append_format(&missing_nodes,
|
|
||||||
"%s (ID: %i)",
|
|
||||||
node_cell->node_info->node_name,
|
|
||||||
node_cell->node_info->node_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (missing_nodes_count)
|
|
||||||
{
|
|
||||||
ItemListCell *missing_cell = NULL;
|
|
||||||
|
|
||||||
item_list_append_format(&warnings,
|
|
||||||
_("- %i of %i downstream nodes not attached:"),
|
|
||||||
missing_nodes_count,
|
|
||||||
expected_nodes_count);
|
|
||||||
|
|
||||||
for (missing_cell = missing_nodes.head; missing_cell; missing_cell = missing_cell->next)
|
|
||||||
{
|
|
||||||
item_list_append_format(&warnings,
|
|
||||||
" - %s\n", missing_cell->string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server_version_num < 90400)
|
if (server_version_num < 90400)
|
||||||
{
|
{
|
||||||
key_value_list_set(&node_status,
|
key_value_list_set(&node_status,
|
||||||
@@ -542,31 +486,18 @@ do_node_status(void)
|
|||||||
|
|
||||||
termPQExpBuffer(&output);
|
termPQExpBuffer(&output);
|
||||||
|
|
||||||
if (warnings.head != NULL && runtime_options.terse == false && runtime_options.output_mode == OM_TEXT)
|
if (runtime_options.output_mode == OM_TEXT && warnings.head != NULL && runtime_options.terse == false)
|
||||||
{
|
{
|
||||||
log_warning(_("following issue(s) were detected:"));
|
log_warning(_("following issue(s) were detected:"));
|
||||||
print_item_list(&warnings);
|
print_item_list(&warnings);
|
||||||
log_hint(_("execute \"repmgr node check\" for more details"));
|
log_hint(_("execute \"repmgr node check\" for more details"));
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_node_info_list(&missing_slots);
|
|
||||||
key_value_list_free(&node_status);
|
key_value_list_free(&node_status);
|
||||||
item_list_free(&warnings);
|
item_list_free(&warnings);
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
|
|
||||||
/*
|
|
||||||
* If warnings were noted, even if they're not displayed (e.g. in --csv node),
|
|
||||||
* that means something's not right so we need to emit a non-zero exit code.
|
|
||||||
*/
|
|
||||||
if (warnings.head != NULL)
|
|
||||||
{
|
|
||||||
exit(ERR_NODE_STATUS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns information about the running state of the node.
|
* Returns information about the running state of the node.
|
||||||
* For internal use during "standby switchover".
|
* For internal use during "standby switchover".
|
||||||
@@ -697,7 +628,6 @@ do_node_check(void)
|
|||||||
CheckStatusList status_list = {NULL, NULL};
|
CheckStatusList status_list = {NULL, NULL};
|
||||||
CheckStatusListCell *cell = NULL;
|
CheckStatusListCell *cell = NULL;
|
||||||
|
|
||||||
bool issue_detected = false;
|
|
||||||
|
|
||||||
/* for internal use */
|
/* for internal use */
|
||||||
if (runtime_options.has_passfile == true)
|
if (runtime_options.has_passfile == true)
|
||||||
@@ -782,17 +712,6 @@ do_node_check(void)
|
|||||||
exit(return_code);
|
exit(return_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtime_options.missing_slots == true)
|
|
||||||
{
|
|
||||||
return_code = do_node_check_missing_slots(conn,
|
|
||||||
runtime_options.output_mode,
|
|
||||||
&node_info,
|
|
||||||
NULL);
|
|
||||||
PQfinish(conn);
|
|
||||||
exit(return_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (runtime_options.output_mode == OM_NAGIOS)
|
if (runtime_options.output_mode == OM_NAGIOS)
|
||||||
{
|
{
|
||||||
log_error(_("--nagios can only be used with a specific check"));
|
log_error(_("--nagios can only be used with a specific check"));
|
||||||
@@ -806,23 +725,11 @@ do_node_check(void)
|
|||||||
initPQExpBuffer(&output);
|
initPQExpBuffer(&output);
|
||||||
|
|
||||||
/* order functions are called is also output order */
|
/* order functions are called is also output order */
|
||||||
if (do_node_check_role(conn, runtime_options.output_mode, &node_info, &status_list) != CHECK_STATUS_OK)
|
(void) do_node_check_role(conn, runtime_options.output_mode, &node_info, &status_list);
|
||||||
issue_detected = true;
|
(void) do_node_check_replication_lag(conn, runtime_options.output_mode, &node_info, &status_list);
|
||||||
|
(void) do_node_check_archive_ready(conn, runtime_options.output_mode, &status_list);
|
||||||
if (do_node_check_replication_lag(conn, runtime_options.output_mode, &node_info, &status_list) != CHECK_STATUS_OK)
|
(void) do_node_check_downstream(conn, runtime_options.output_mode, &status_list);
|
||||||
issue_detected = true;
|
(void) do_node_check_slots(conn, runtime_options.output_mode, &node_info, &status_list);
|
||||||
|
|
||||||
if (do_node_check_archive_ready(conn, runtime_options.output_mode, &status_list) != CHECK_STATUS_OK)
|
|
||||||
issue_detected = true;
|
|
||||||
|
|
||||||
if (do_node_check_downstream(conn, runtime_options.output_mode, &status_list) != CHECK_STATUS_OK)
|
|
||||||
issue_detected = true;
|
|
||||||
|
|
||||||
if (do_node_check_slots(conn, runtime_options.output_mode, &node_info, &status_list) != CHECK_STATUS_OK)
|
|
||||||
issue_detected = true;
|
|
||||||
|
|
||||||
if (do_node_check_missing_slots(conn, runtime_options.output_mode, &node_info, &status_list) != CHECK_STATUS_OK)
|
|
||||||
issue_detected = true;
|
|
||||||
|
|
||||||
if (runtime_options.output_mode == OM_CSV)
|
if (runtime_options.output_mode == OM_CSV)
|
||||||
{
|
{
|
||||||
@@ -879,11 +786,6 @@ do_node_check(void)
|
|||||||
check_status_list_free(&status_list);
|
check_status_list_free(&status_list);
|
||||||
|
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
|
|
||||||
if (issue_detected == true)
|
|
||||||
{
|
|
||||||
exit(ERR_NODE_STATUS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1145,7 +1047,6 @@ do_node_check_downstream(PGconn *conn, OutputMode mode, CheckStatusList *list_ou
|
|||||||
|
|
||||||
for (cell = downstream_nodes.head; cell; cell = cell->next)
|
for (cell = downstream_nodes.head; cell; cell = cell->next)
|
||||||
{
|
{
|
||||||
/* skip witness server */
|
|
||||||
if (cell->node_info->type == WITNESS)
|
if (cell->node_info->type == WITNESS)
|
||||||
{
|
{
|
||||||
expected_nodes_count --;
|
expected_nodes_count --;
|
||||||
@@ -1682,130 +1583,6 @@ do_node_check_slots(PGconn *conn, OutputMode mode, t_node_info *node_info, Check
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static CheckStatus
|
|
||||||
do_node_check_missing_slots(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output)
|
|
||||||
{
|
|
||||||
CheckStatus status = CHECK_STATUS_OK;
|
|
||||||
PQExpBufferData details;
|
|
||||||
NodeInfoList missing_slots = T_NODE_INFO_LIST_INITIALIZER;
|
|
||||||
|
|
||||||
if (mode == OM_CSV && list_output == NULL)
|
|
||||||
{
|
|
||||||
log_error(_("--csv output not provided with --missing-slots option"));
|
|
||||||
PQfinish(conn);
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
|
|
||||||
initPQExpBuffer(&details);
|
|
||||||
|
|
||||||
if (server_version_num < 90400)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&details,
|
|
||||||
_("replication slots not available for this PostgreSQL version"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
get_downstream_nodes_with_missing_slot(conn,
|
|
||||||
config_file_options.node_id,
|
|
||||||
&missing_slots);
|
|
||||||
|
|
||||||
if (missing_slots.node_count == 0)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&details,
|
|
||||||
_("node has no missing replication slots"));
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NodeInfoListCell *missing_slot_cell = NULL;
|
|
||||||
bool first_element = true;
|
|
||||||
|
|
||||||
status = CHECK_STATUS_CRITICAL;
|
|
||||||
|
|
||||||
appendPQExpBuffer(&details,
|
|
||||||
_("%i replication slots are missing"),
|
|
||||||
missing_slots.node_count);
|
|
||||||
|
|
||||||
if (missing_slots.node_count)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&details, ": ");
|
|
||||||
|
|
||||||
for (missing_slot_cell = missing_slots.head; missing_slot_cell; missing_slot_cell = missing_slot_cell->next)
|
|
||||||
{
|
|
||||||
if (first_element == true)
|
|
||||||
{
|
|
||||||
first_element = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&details, ", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
appendPQExpBuffer(&details, "%s", missing_slot_cell->node_info->slot_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mode)
|
|
||||||
{
|
|
||||||
case OM_NAGIOS:
|
|
||||||
{
|
|
||||||
printf("REPMGR_MISSING_SLOTS %s: %s | missing_slots=%i",
|
|
||||||
output_check_status(status),
|
|
||||||
details.data,
|
|
||||||
missing_slots.node_count);
|
|
||||||
|
|
||||||
if (missing_slots.node_count)
|
|
||||||
{
|
|
||||||
NodeInfoListCell *missing_slot_cell = NULL;
|
|
||||||
bool first_element = true;
|
|
||||||
|
|
||||||
printf(";");
|
|
||||||
|
|
||||||
for (missing_slot_cell = missing_slots.head; missing_slot_cell; missing_slot_cell = missing_slot_cell->next)
|
|
||||||
{
|
|
||||||
if (first_element == true)
|
|
||||||
{
|
|
||||||
first_element = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf(",");
|
|
||||||
}
|
|
||||||
printf("%s", missing_slot_cell->node_info->slot_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OM_CSV:
|
|
||||||
case OM_TEXT:
|
|
||||||
if (list_output != NULL)
|
|
||||||
{
|
|
||||||
check_status_list_set(list_output,
|
|
||||||
"Replication slots",
|
|
||||||
status,
|
|
||||||
details.data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("%s (%s)\n",
|
|
||||||
output_check_status(status),
|
|
||||||
details.data);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
clear_node_info_list(&missing_slots);
|
|
||||||
|
|
||||||
termPQExpBuffer(&details);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
do_node_service(void)
|
do_node_service(void)
|
||||||
{
|
{
|
||||||
@@ -2359,19 +2136,19 @@ do_node_rejoin(void)
|
|||||||
{
|
{
|
||||||
log_verbose(LOG_INFO, _("waiting for node %i to respond to pings; %i of max %i attempts"),
|
log_verbose(LOG_INFO, _("waiting for node %i to respond to pings; %i of max %i attempts"),
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
i + 1, config_file_options.node_rejoin_timeout);
|
i + 1, config_file_options.standby_reconnect_timeout);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_debug("sleeping 1 second waiting for node %i to respond to pings; %i of max %i attempts",
|
log_debug("sleeping 1 second waiting for node %i to respond to pings; %i of max %i attempts",
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
i + 1, config_file_options.node_rejoin_timeout);
|
i + 1, config_file_options.standby_reconnect_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; i < config_file_options.node_rejoin_timeout; i++)
|
for (; i < config_file_options.standby_reconnect_timeout; i++)
|
||||||
{
|
{
|
||||||
success = is_downstream_node_attached(upstream_conn, config_file_options.node_name);
|
success = is_downstream_node_attached(upstream_conn, config_file_options.node_name);
|
||||||
|
|
||||||
@@ -2386,13 +2163,13 @@ do_node_rejoin(void)
|
|||||||
{
|
{
|
||||||
log_info(_("waiting for node %i to connect to new primary; %i of max %i attempts"),
|
log_info(_("waiting for node %i to connect to new primary; %i of max %i attempts"),
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
i + 1, config_file_options.node_rejoin_timeout);
|
i + 1, config_file_options.standby_reconnect_timeout);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_debug("sleeping 1 second waiting for node %i to connect to new primary; %i of max %i attempts",
|
log_debug("sleeping 1 second waiting for node %i to connect to new primary; %i of max %i attempts",
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
i + 1, config_file_options.node_rejoin_timeout);
|
i + 1, config_file_options.standby_reconnect_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep(1);
|
sleep(1);
|
||||||
@@ -2887,7 +2664,6 @@ do_node_help(void)
|
|||||||
printf(_(" --replication-lag replication lag in seconds (standbys only)\n"));
|
printf(_(" --replication-lag replication lag in seconds (standbys only)\n"));
|
||||||
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"));
|
|
||||||
|
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
|
|||||||
@@ -1054,7 +1054,6 @@ _do_create_recovery_conf(void)
|
|||||||
local_node_record.slot_name,
|
local_node_record.slot_name,
|
||||||
upstream_node_record.node_name,
|
upstream_node_record.node_name,
|
||||||
upstream_node_id);
|
upstream_node_id);
|
||||||
|
|
||||||
if (runtime_options.force == false && runtime_options.dry_run == false)
|
if (runtime_options.force == false && runtime_options.dry_run == false)
|
||||||
{
|
{
|
||||||
log_error("%s", msg.data);
|
log_error("%s", msg.data);
|
||||||
@@ -1086,7 +1085,7 @@ _do_create_recovery_conf(void)
|
|||||||
initPQExpBuffer(&msg);
|
initPQExpBuffer(&msg);
|
||||||
|
|
||||||
appendPQExpBuffer(&msg,
|
appendPQExpBuffer(&msg,
|
||||||
_("insufficient free replication slots on upstream node \"%s\" (ID: %i)"),
|
_("insufficient free replicaiton slots on upstream node \"%s\" (ID: %i)"),
|
||||||
upstream_node_record.node_name,
|
upstream_node_record.node_name,
|
||||||
upstream_node_id);
|
upstream_node_id);
|
||||||
|
|
||||||
@@ -1142,14 +1141,14 @@ _do_create_recovery_conf(void)
|
|||||||
if (runtime_options.dry_run == true)
|
if (runtime_options.dry_run == true)
|
||||||
{
|
{
|
||||||
char recovery_conf_contents[MAXLEN] = "";
|
char recovery_conf_contents[MAXLEN] = "";
|
||||||
create_recovery_file(&local_node_record, &recovery_conninfo, recovery_conf_contents, false);
|
create_recovery_file(&upstream_node_record, &recovery_conninfo, recovery_conf_contents, false);
|
||||||
|
|
||||||
log_info(_("would create \"recovery.conf\" file in \"%s\""), local_data_directory);
|
log_info(_("would create \"recovery.conf\" file in \"%s\""), local_data_directory);
|
||||||
log_detail(_("\n%s"), recovery_conf_contents);
|
log_detail(_("\n%s"), recovery_conf_contents);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!create_recovery_file(&local_node_record, &recovery_conninfo, local_data_directory, true))
|
if (!create_recovery_file(&upstream_node_record, &recovery_conninfo, local_data_directory, true))
|
||||||
{
|
{
|
||||||
log_error(_("unable to create \"recovery.conf\""));
|
log_error(_("unable to create \"recovery.conf\""));
|
||||||
}
|
}
|
||||||
@@ -1709,16 +1708,11 @@ do_standby_register(void)
|
|||||||
|
|
||||||
termPQExpBuffer(&details);
|
termPQExpBuffer(&details);
|
||||||
|
|
||||||
/*
|
/* if --wait-sync option set, wait for the records to synchronise */
|
||||||
* If --wait-sync option set, wait for the records to synchronise
|
|
||||||
* (unless 0 seconds provided, which disables it, which is the same as
|
|
||||||
* not providing the option). The default value is -1, which means
|
|
||||||
* no timeout.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (PQstatus(conn) == CONNECTION_OK &&
|
if (PQstatus(conn) == CONNECTION_OK &&
|
||||||
runtime_options.wait_register_sync == true &&
|
runtime_options.wait_register_sync == true &&
|
||||||
runtime_options.wait_register_sync_seconds != 0)
|
runtime_options.wait_register_sync_seconds > 0)
|
||||||
{
|
{
|
||||||
bool sync_ok = false;
|
bool sync_ok = false;
|
||||||
int timer = 0;
|
int timer = 0;
|
||||||
@@ -1742,11 +1736,7 @@ do_standby_register(void)
|
|||||||
{
|
{
|
||||||
bool records_match = true;
|
bool records_match = true;
|
||||||
|
|
||||||
/*
|
if (runtime_options.wait_register_sync_seconds && runtime_options.wait_register_sync_seconds == timer)
|
||||||
* If timeout set to a positive value, check if we've reached it and
|
|
||||||
* exit the loop
|
|
||||||
*/
|
|
||||||
if (runtime_options.wait_register_sync_seconds > 0 && runtime_options.wait_register_sync_seconds == timer)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
node_record_status = get_node_record(conn,
|
node_record_status = get_node_record(conn,
|
||||||
@@ -2911,25 +2901,6 @@ do_standby_switchover(void)
|
|||||||
exit(ERR_DB_QUERY);
|
exit(ERR_DB_QUERY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Check that there's no exclusive backups running on the primary.
|
|
||||||
* We don't want to end up damaging the backup and also leaving the server in an
|
|
||||||
* state where there's control data saying it's in backup mode but there's no
|
|
||||||
* backup_label in PGDATA.
|
|
||||||
* If the DBA wants to do the switchover anyway, he should first stop the
|
|
||||||
* backup that's running.
|
|
||||||
*/
|
|
||||||
if (server_in_exclusive_backup_mode(remote_conn) != BACKUP_STATE_NO_BACKUP)
|
|
||||||
{
|
|
||||||
log_error(_("unable to perform a switchover while primary server is in exclusive backup mode"));
|
|
||||||
log_hint(_("stop backup before attempting the switchover"));
|
|
||||||
|
|
||||||
PQfinish(local_conn);
|
|
||||||
PQfinish(remote_conn);
|
|
||||||
|
|
||||||
exit(ERR_SWITCHOVER_FAIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check this standby is attached to the demotion candidate
|
* Check this standby is attached to the demotion candidate
|
||||||
* TODO:
|
* TODO:
|
||||||
@@ -6533,7 +6504,6 @@ do_standby_help(void)
|
|||||||
puts("");
|
puts("");
|
||||||
printf(_(" \"standby clone\" clones a standby from the primary or an upstream node.\n"));
|
printf(_(" \"standby clone\" clones a standby from the primary or an upstream node.\n"));
|
||||||
puts("");
|
puts("");
|
||||||
printf(_(" -d, --dbname=conninfo conninfo of the upstream node to use for cloning.\n"));
|
|
||||||
printf(_(" -c, --fast-checkpoint force fast checkpoint\n"));
|
printf(_(" -c, --fast-checkpoint force fast checkpoint\n"));
|
||||||
printf(_(" --copy-external-config-files[={samepath|pgdata}]\n" \
|
printf(_(" --copy-external-config-files[={samepath|pgdata}]\n" \
|
||||||
" copy configuration files located outside the \n" \
|
" copy configuration files located outside the \n" \
|
||||||
|
|||||||
@@ -310,59 +310,55 @@ do_witness_register(void)
|
|||||||
void
|
void
|
||||||
do_witness_unregister(void)
|
do_witness_unregister(void)
|
||||||
{
|
{
|
||||||
PGconn *local_conn = NULL;
|
PGconn *witness_conn = NULL;
|
||||||
PGconn *primary_conn = NULL;
|
PGconn *primary_conn = NULL;
|
||||||
t_node_info node_record = T_NODE_INFO_INITIALIZER;
|
t_node_info node_record = T_NODE_INFO_INITIALIZER;
|
||||||
RecordStatus record_status = RECORD_NOT_FOUND;
|
RecordStatus record_status = RECORD_NOT_FOUND;
|
||||||
bool node_record_deleted = false;
|
bool node_record_deleted = false;
|
||||||
bool local_node_available = true;
|
bool witness_available = true;
|
||||||
int witness_node_id = UNKNOWN_NODE_ID;
|
|
||||||
|
|
||||||
if (runtime_options.node_id != UNKNOWN_NODE_ID)
|
log_info(_("connecting to witness node \"%s\" (ID: %i)"),
|
||||||
{
|
|
||||||
/* user has specified the witness node id */
|
|
||||||
witness_node_id = runtime_options.node_id;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* assume witness node is local node */
|
|
||||||
witness_node_id = config_file_options.node_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info(_("connecting to node \"%s\" (ID: %i)"),
|
|
||||||
config_file_options.node_name,
|
config_file_options.node_name,
|
||||||
config_file_options.node_id);
|
config_file_options.node_id);
|
||||||
|
|
||||||
local_conn = establish_db_connection_quiet(config_file_options.conninfo);
|
witness_conn = establish_db_connection_quiet(config_file_options.conninfo);
|
||||||
|
|
||||||
if (PQstatus(local_conn) != CONNECTION_OK)
|
if (PQstatus(witness_conn) != CONNECTION_OK)
|
||||||
{
|
{
|
||||||
if (!runtime_options.force)
|
if (!runtime_options.force)
|
||||||
{
|
{
|
||||||
log_error(_("unable to connect to node \"%s\" (ID: %i)"),
|
log_error(_("unable to connect to witness node \"%s\" (ID: %i)"),
|
||||||
config_file_options.node_name,
|
config_file_options.node_name,
|
||||||
config_file_options.node_id);
|
config_file_options.node_id);
|
||||||
log_detail("%s", PQerrorMessage(local_conn));
|
log_detail("%s", PQerrorMessage(witness_conn));
|
||||||
|
log_hint(_("provide -F/--force to remove the witness record if the server is not running"));
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
log_notice(_("unable to connect to witness node \"%s\" (ID: %i), removing node record on cluster primary only"),
|
log_notice(_("unable to connect to witness node \"%s\" (ID: %i), removing node record on cluster primary only"),
|
||||||
config_file_options.node_name,
|
config_file_options.node_name,
|
||||||
config_file_options.node_id);
|
config_file_options.node_id);
|
||||||
local_node_available = false;
|
witness_available = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (local_node_available == true)
|
if (witness_available == true)
|
||||||
{
|
{
|
||||||
primary_conn = get_primary_connection_quiet(local_conn, NULL, NULL);
|
primary_conn = get_primary_connection_quiet(witness_conn, NULL, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Assume user has provided connection details for the primary server
|
* Extract the repmgr user and database names from the conninfo string
|
||||||
|
* provided in repmgr.conf
|
||||||
*/
|
*/
|
||||||
|
get_conninfo_value(config_file_options.conninfo, "user", repmgr_user);
|
||||||
|
get_conninfo_value(config_file_options.conninfo, "dbname", repmgr_db);
|
||||||
|
|
||||||
|
param_set_ine(&source_conninfo, "user", repmgr_user);
|
||||||
|
param_set_ine(&source_conninfo, "dbname", repmgr_db);
|
||||||
|
|
||||||
primary_conn = establish_db_connection_by_params(&source_conninfo, false);
|
primary_conn = establish_db_connection_by_params(&source_conninfo, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PQstatus(primary_conn) != CONNECTION_OK)
|
if (PQstatus(primary_conn) != CONNECTION_OK)
|
||||||
@@ -370,26 +366,26 @@ do_witness_unregister(void)
|
|||||||
log_error(_("unable to connect to primary"));
|
log_error(_("unable to connect to primary"));
|
||||||
log_detail("%s", PQerrorMessage(primary_conn));
|
log_detail("%s", PQerrorMessage(primary_conn));
|
||||||
|
|
||||||
if (local_node_available == true)
|
if (witness_available == true)
|
||||||
{
|
{
|
||||||
PQfinish(local_conn);
|
PQfinish(witness_conn);
|
||||||
}
|
}
|
||||||
else if (runtime_options.connection_param_provided == false)
|
else
|
||||||
{
|
{
|
||||||
log_hint(_("provide connection details for the primary server"));
|
log_hint(_("provide connection details to primary server"));
|
||||||
}
|
}
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check node exists and is really a witness */
|
/* Check node exists and is really a witness */
|
||||||
record_status = get_node_record(primary_conn, witness_node_id, &node_record);
|
record_status = get_node_record(primary_conn, config_file_options.node_id, &node_record);
|
||||||
|
|
||||||
if (record_status != RECORD_FOUND)
|
if (record_status != RECORD_FOUND)
|
||||||
{
|
{
|
||||||
log_error(_("no record found for node %i"), witness_node_id);
|
log_error(_("no record found for node %i"), config_file_options.node_id);
|
||||||
|
|
||||||
if (local_node_available == true)
|
if (witness_available == true)
|
||||||
PQfinish(local_conn);
|
PQfinish(witness_conn);
|
||||||
PQfinish(primary_conn);
|
PQfinish(primary_conn);
|
||||||
|
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
@@ -397,17 +393,11 @@ do_witness_unregister(void)
|
|||||||
|
|
||||||
if (node_record.type != WITNESS)
|
if (node_record.type != WITNESS)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* The node (either explicitly provided with --node-id, or the local node)
|
|
||||||
* is not a witness.
|
|
||||||
*
|
|
||||||
* TODO: scan node list and print hint about identity of known witness servers.
|
|
||||||
*/
|
|
||||||
log_error(_("node %i is not a witness node"), config_file_options.node_id);
|
log_error(_("node %i is not a witness node"), config_file_options.node_id);
|
||||||
log_detail(_("node %i is a %s node"), config_file_options.node_id, get_node_type_string(node_record.type));
|
log_detail(_("node %i is a %s node"), config_file_options.node_id, get_node_type_string(node_record.type));
|
||||||
|
|
||||||
if (local_node_available == true)
|
if (witness_available == true)
|
||||||
PQfinish(local_conn);
|
PQfinish(witness_conn);
|
||||||
PQfinish(primary_conn);
|
PQfinish(primary_conn);
|
||||||
|
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
@@ -416,43 +406,49 @@ do_witness_unregister(void)
|
|||||||
if (runtime_options.dry_run == true)
|
if (runtime_options.dry_run == true)
|
||||||
{
|
{
|
||||||
log_info(_("prerequisites for unregistering the witness node are met"));
|
log_info(_("prerequisites for unregistering the witness node are met"));
|
||||||
if (local_node_available == true)
|
if (witness_available == true)
|
||||||
PQfinish(local_conn);
|
PQfinish(witness_conn);
|
||||||
PQfinish(primary_conn);
|
PQfinish(primary_conn);
|
||||||
|
|
||||||
exit(SUCCESS);
|
exit(SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info(_("unregistering witness node %i"), witness_node_id);
|
log_info(_("unregistering witness node %i"), config_file_options.node_id);
|
||||||
node_record_deleted = delete_node_record(primary_conn,
|
node_record_deleted = delete_node_record(primary_conn,
|
||||||
witness_node_id);
|
config_file_options.node_id);
|
||||||
|
|
||||||
if (node_record_deleted == false)
|
if (node_record_deleted == false)
|
||||||
{
|
{
|
||||||
PQfinish(primary_conn);
|
PQfinish(primary_conn);
|
||||||
|
PQfinish(witness_conn);
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
if (local_node_available == true)
|
/* sync records from primary */
|
||||||
PQfinish(local_conn);
|
if (witness_available == true && witness_copy_node_records(primary_conn, witness_conn) == false)
|
||||||
PQfinish(local_conn);
|
{
|
||||||
|
log_error(_("unable to copy repmgr node records from primary"));
|
||||||
|
PQfinish(primary_conn);
|
||||||
|
PQfinish(witness_conn);
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Log the event */
|
/* Log the event */
|
||||||
create_event_record(primary_conn,
|
create_event_record(primary_conn,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
witness_node_id,
|
config_file_options.node_id,
|
||||||
"witness_unregister",
|
"witness_unregister",
|
||||||
true,
|
true,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
PQfinish(primary_conn);
|
PQfinish(primary_conn);
|
||||||
|
|
||||||
if (local_node_available == true)
|
if (witness_available == true)
|
||||||
PQfinish(local_conn);
|
PQfinish(witness_conn);
|
||||||
|
|
||||||
log_info(_("witness unregistration complete"));
|
log_info(_("witness unregistration complete"));
|
||||||
log_detail(_("witness node with ID %i successfully unregistered"),
|
log_detail(_("witness node with id %i (conninfo: %s) successfully unregistered"),
|
||||||
witness_node_id);
|
config_file_options.node_id, config_file_options.conninfo);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -482,9 +478,6 @@ void do_witness_help(void)
|
|||||||
puts("");
|
puts("");
|
||||||
printf(_(" --dry-run check prerequisites but don't make any changes\n"));
|
printf(_(" --dry-run check prerequisites but don't make any changes\n"));
|
||||||
printf(_(" -F, --force unregister when witness node not running\n"));
|
printf(_(" -F, --force unregister when witness node not running\n"));
|
||||||
printf(_(" --node-id node ID of the witness node (provide if executing on\n"));
|
|
||||||
printf(_(" another node)\n"));
|
|
||||||
|
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ typedef struct
|
|||||||
/* logging options */
|
/* logging options */
|
||||||
char log_level[MAXLEN]; /* overrides setting in repmgr.conf */
|
char log_level[MAXLEN]; /* overrides setting in repmgr.conf */
|
||||||
bool log_to_file;
|
bool log_to_file;
|
||||||
bool quiet;
|
|
||||||
bool terse;
|
bool terse;
|
||||||
bool verbose;
|
bool verbose;
|
||||||
|
|
||||||
@@ -107,7 +106,6 @@ typedef struct
|
|||||||
bool replication_lag;
|
bool replication_lag;
|
||||||
bool role;
|
bool role;
|
||||||
bool slots;
|
bool slots;
|
||||||
bool missing_slots;
|
|
||||||
bool has_passfile;
|
bool has_passfile;
|
||||||
bool replication_connection;
|
bool replication_connection;
|
||||||
|
|
||||||
@@ -139,7 +137,7 @@ typedef struct
|
|||||||
/* general configuration options */ \
|
/* general configuration options */ \
|
||||||
"", false, false, "", false, false, \
|
"", false, false, "", false, false, \
|
||||||
/* logging options */ \
|
/* logging options */ \
|
||||||
"", false, false, false, false, \
|
"", false, false, false, \
|
||||||
/* output options */ \
|
/* output options */ \
|
||||||
false, false, false, \
|
false, false, false, \
|
||||||
/* database connection options */ \
|
/* database connection options */ \
|
||||||
@@ -154,13 +152,13 @@ typedef struct
|
|||||||
/* "standby clone"/"standby follow" options */ \
|
/* "standby clone"/"standby follow" options */ \
|
||||||
NO_UPSTREAM_NODE, \
|
NO_UPSTREAM_NODE, \
|
||||||
/* "standby register" options */ \
|
/* "standby register" options */ \
|
||||||
false, -1, DEFAULT_WAIT_START, \
|
false, 0, DEFAULT_WAIT_START, \
|
||||||
/* "standby switchover" options */ \
|
/* "standby switchover" options */ \
|
||||||
false, false, "", false, \
|
false, false, "", false, \
|
||||||
/* "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, \
|
||||||
/* "node join" options */ \
|
/* "node join" options */ \
|
||||||
"", \
|
"", \
|
||||||
/* "node service" options */ \
|
/* "node service" options */ \
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
t_conninfo_param_list default_conninfo = T_CONNINFO_PARAM_LIST_INITIALIZER;
|
t_conninfo_param_list default_conninfo = T_CONNINFO_PARAM_LIST_INITIALIZER;
|
||||||
|
|
||||||
int optindex = 0;
|
int optindex;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
char *repmgr_command = NULL;
|
char *repmgr_command = NULL;
|
||||||
@@ -108,7 +108,6 @@ main(int argc, char **argv)
|
|||||||
char *dummy_action = "";
|
char *dummy_action = "";
|
||||||
|
|
||||||
bool help_option = false;
|
bool help_option = false;
|
||||||
bool option_error_found = false;
|
|
||||||
|
|
||||||
set_progname(argv[0]);
|
set_progname(argv[0]);
|
||||||
|
|
||||||
@@ -179,10 +178,7 @@ main(int argc, char **argv)
|
|||||||
strncpy(runtime_options.username, pw->pw_name, MAXLEN);
|
strncpy(runtime_options.username, pw->pw_name, MAXLEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make getopt emitting errors */
|
while ((c = getopt_long(argc, argv, "?Vb:f:FwWd:h:p:U:R:S:D:ck:L:tvC:", long_options,
|
||||||
opterr = 1;
|
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "?Vb:f:FwWd:h:p:U:R:S:D:ck:L:qtvC:", long_options,
|
|
||||||
&optindex)) != -1)
|
&optindex)) != -1)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -200,7 +196,13 @@ main(int argc, char **argv)
|
|||||||
case OPT_HELP: /* --help */
|
case OPT_HELP: /* --help */
|
||||||
help_option = true;
|
help_option = true;
|
||||||
break;
|
break;
|
||||||
|
case '?':
|
||||||
|
/* Actual help option given */
|
||||||
|
if (strcmp(argv[optind - 1], "-?") == 0)
|
||||||
|
{
|
||||||
|
help_option = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -471,10 +473,6 @@ main(int argc, char **argv)
|
|||||||
runtime_options.slots = true;
|
runtime_options.slots = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPT_MISSING_SLOTS:
|
|
||||||
runtime_options.missing_slots = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPT_HAS_PASSFILE:
|
case OPT_HAS_PASSFILE:
|
||||||
runtime_options.has_passfile = true;
|
runtime_options.has_passfile = true;
|
||||||
break;
|
break;
|
||||||
@@ -574,12 +572,6 @@ main(int argc, char **argv)
|
|||||||
logger_output_mode = OM_DAEMON;
|
logger_output_mode = OM_DAEMON;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
/* --quiet */
|
|
||||||
case 'q':
|
|
||||||
runtime_options.quiet = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* --terse */
|
/* --terse */
|
||||||
case 't':
|
case 't':
|
||||||
runtime_options.terse = true;
|
runtime_options.terse = true;
|
||||||
@@ -635,24 +627,9 @@ main(int argc, char **argv)
|
|||||||
_("--recovery-min-apply-delay is now a configuration file parameter, \"recovery_min_apply_delay\""));
|
_("--recovery-min-apply-delay is now a configuration file parameter, \"recovery_min_apply_delay\""));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ':': /* missing option argument */
|
|
||||||
option_error_found = true;
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
/* Actual help option given? */
|
|
||||||
if (strcmp(argv[optind - 1], "-?") == 0)
|
|
||||||
{
|
|
||||||
help_option = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* otherwise fall through to default */
|
|
||||||
default: /* invalid option */
|
|
||||||
option_error_found = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If -d/--dbname appears to be a conninfo string, validate by attempting
|
* If -d/--dbname appears to be a conninfo string, validate by attempting
|
||||||
* to parse it (and if successful, store the parsed parameters)
|
* to parse it (and if successful, store the parsed parameters)
|
||||||
@@ -753,10 +730,9 @@ main(int argc, char **argv)
|
|||||||
if (cli_errors.head != NULL)
|
if (cli_errors.head != NULL)
|
||||||
{
|
{
|
||||||
free_conninfo_params(&source_conninfo);
|
free_conninfo_params(&source_conninfo);
|
||||||
exit_with_cli_errors(&cli_errors, NULL);
|
exit_with_cli_errors(&cli_errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*----------
|
/*----------
|
||||||
* Determine the node type and action; following are valid:
|
* Determine the node type and action; following are valid:
|
||||||
*
|
*
|
||||||
@@ -1003,30 +979,9 @@ main(int argc, char **argv)
|
|||||||
if (cli_errors.head != NULL)
|
if (cli_errors.head != NULL)
|
||||||
{
|
{
|
||||||
free_conninfo_params(&source_conninfo);
|
free_conninfo_params(&source_conninfo);
|
||||||
|
exit_with_cli_errors(&cli_errors);
|
||||||
exit_with_cli_errors(&cli_errors, valid_repmgr_command_found == true ? repmgr_command : NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* no errors detected by repmgr, but getopt might have */
|
|
||||||
if (option_error_found == true)
|
|
||||||
{
|
|
||||||
if (valid_repmgr_command_found == true)
|
|
||||||
{
|
|
||||||
printf(_("Try \"%s --help\" or \"%s %s --help\" for more information.\n"),
|
|
||||||
progname(),
|
|
||||||
progname(),
|
|
||||||
repmgr_command);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf(_("Try \"repmgr --help\" for more information.\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
free_conninfo_params(&source_conninfo);
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print any warnings about inappropriate command line options, unless
|
* Print any warnings about inappropriate command line options, unless
|
||||||
* -t/--terse set
|
* -t/--terse set
|
||||||
@@ -1122,17 +1077,6 @@ main(int argc, char **argv)
|
|||||||
logger_set_min_level(LOG_INFO);
|
logger_set_min_level(LOG_INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If -q/--quiet supplied, suppress any non-ERROR log output.
|
|
||||||
* This overrides everything else; we'll leave it up to the user to deal with the
|
|
||||||
* consequences of e.g. running --dry-run together with -q/--quiet.
|
|
||||||
*/
|
|
||||||
if (runtime_options.quiet == true)
|
|
||||||
{
|
|
||||||
logger_set_level(LOG_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Node configuration information is not needed for all actions, with
|
* Node configuration information is not needed for all actions, with
|
||||||
@@ -1519,7 +1463,6 @@ check_cli_parameters(const int action)
|
|||||||
{
|
{
|
||||||
case PRIMARY_UNREGISTER:
|
case PRIMARY_UNREGISTER:
|
||||||
case STANDBY_UNREGISTER:
|
case STANDBY_UNREGISTER:
|
||||||
case WITNESS_UNREGISTER:
|
|
||||||
case CLUSTER_EVENT:
|
case CLUSTER_EVENT:
|
||||||
case CLUSTER_MATRIX:
|
case CLUSTER_MATRIX:
|
||||||
case CLUSTER_CROSSCHECK:
|
case CLUSTER_CROSSCHECK:
|
||||||
@@ -1560,7 +1503,6 @@ check_cli_parameters(const int action)
|
|||||||
case STANDBY_CLONE:
|
case STANDBY_CLONE:
|
||||||
case STANDBY_REGISTER:
|
case STANDBY_REGISTER:
|
||||||
case STANDBY_FOLLOW:
|
case STANDBY_FOLLOW:
|
||||||
case BDR_REGISTER:
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
item_list_append_format(&cli_warnings,
|
item_list_append_format(&cli_warnings,
|
||||||
@@ -1903,7 +1845,7 @@ do_help(void)
|
|||||||
printf(_(" %s [OPTIONS] standby {register|unregister|clone|promote|follow|switchover}\n"), progname());
|
printf(_(" %s [OPTIONS] standby {register|unregister|clone|promote|follow|switchover}\n"), progname());
|
||||||
printf(_(" %s [OPTIONS] bdr {register|unregister}\n"), progname());
|
printf(_(" %s [OPTIONS] bdr {register|unregister}\n"), progname());
|
||||||
printf(_(" %s [OPTIONS] node {status|check|rejoin|service}\n"), progname());
|
printf(_(" %s [OPTIONS] node {status|check|rejoin|service}\n"), progname());
|
||||||
printf(_(" %s [OPTIONS] cluster {show|event|matrix|crosscheck|cleanup}\n"), progname());
|
printf(_(" %s [OPTIONS] cluster {show|event|matrix|crosscheck}\n"), progname());
|
||||||
printf(_(" %s [OPTIONS] witness {register|unregister}\n"), progname());
|
printf(_(" %s [OPTIONS] witness {register|unregister}\n"), progname());
|
||||||
|
|
||||||
puts("");
|
puts("");
|
||||||
@@ -1952,7 +1894,6 @@ do_help(void)
|
|||||||
printf(_(" --dry-run show what would happen for action, but don't execute it\n"));
|
printf(_(" --dry-run show what would happen for action, but don't execute it\n"));
|
||||||
printf(_(" -L, --log-level set log level (overrides configuration file; default: NOTICE)\n"));
|
printf(_(" -L, --log-level set log level (overrides configuration file; default: NOTICE)\n"));
|
||||||
printf(_(" --log-to-file log to file (or logging facility) defined in repmgr.conf\n"));
|
printf(_(" --log-to-file log to file (or logging facility) defined in repmgr.conf\n"));
|
||||||
printf(_(" -q, --quiet suppress all log output apart from errors\n"));
|
|
||||||
printf(_(" -t, --terse don't display detail, hints and other non-critical output\n"));
|
printf(_(" -t, --terse don't display detail, hints and other non-critical output\n"));
|
||||||
printf(_(" -v, --verbose display additional log output (useful for debugging)\n"));
|
printf(_(" -v, --verbose display additional log output (useful for debugging)\n"));
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,6 @@
|
|||||||
#define OPT_REMOTE_NODE_ID 1038
|
#define OPT_REMOTE_NODE_ID 1038
|
||||||
#define OPT_RECOVERY_CONF_ONLY 1039
|
#define OPT_RECOVERY_CONF_ONLY 1039
|
||||||
#define OPT_NO_WAIT 1040
|
#define OPT_NO_WAIT 1040
|
||||||
#define OPT_MISSING_SLOTS 1041
|
|
||||||
|
|
||||||
/* deprecated since 3.3 */
|
/* deprecated since 3.3 */
|
||||||
#define OPT_DATA_DIR 999
|
#define OPT_DATA_DIR 999
|
||||||
@@ -126,7 +125,6 @@ static struct option long_options[] =
|
|||||||
/* logging options */
|
/* logging options */
|
||||||
{"log-level", required_argument, NULL, 'L'},
|
{"log-level", required_argument, NULL, 'L'},
|
||||||
{"log-to-file", no_argument, NULL, OPT_LOG_TO_FILE},
|
{"log-to-file", no_argument, NULL, OPT_LOG_TO_FILE},
|
||||||
{"quiet", no_argument, NULL, 'q'},
|
|
||||||
{"terse", no_argument, NULL, 't'},
|
{"terse", no_argument, NULL, 't'},
|
||||||
{"verbose", no_argument, NULL, 'v'},
|
{"verbose", no_argument, NULL, 'v'},
|
||||||
|
|
||||||
@@ -166,7 +164,6 @@ static struct option long_options[] =
|
|||||||
{"replication-lag", no_argument, NULL, OPT_REPLICATION_LAG},
|
{"replication-lag", no_argument, NULL, OPT_REPLICATION_LAG},
|
||||||
{"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},
|
|
||||||
{"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},
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@
|
|||||||
#log_facility=STDERR # Logging facility: possible values are STDERR, or for
|
#log_facility=STDERR # Logging facility: possible values are STDERR, or for
|
||||||
# syslog integration, one of LOCAL0, LOCAL1, ..., LOCAL7, USER
|
# syslog integration, one of LOCAL0, LOCAL1, ..., LOCAL7, USER
|
||||||
|
|
||||||
#log_file='' # STDERR can be redirected to an arbitrary file
|
#log_file='' # stderr can be redirected to an arbitrary file
|
||||||
#log_status_interval=300 # interval (in seconds) for repmgrd to log a status message
|
#log_status_interval=300 # interval (in seconds) for repmgrd to log a status message
|
||||||
|
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# "standby follow" settings
|
# Standby follow settings
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
# These settings apply when instructing a standby to follow the new primary
|
# These settings apply when instructing a standby to follow the new primary
|
||||||
@@ -219,28 +219,6 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
# for the standby to connect to the primary
|
# for the standby to connect to the primary
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# "standby switchover" settings
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# These settings apply when switching roles between a primary and a standby
|
|
||||||
# ("repmgr standby switchover").
|
|
||||||
|
|
||||||
#standby_reconnect_timeout=60 # The max length of time (in seconds) to wait
|
|
||||||
# for the demoted standby to reconnect to the promoted
|
|
||||||
# primary (note: this value should be equal to or greater
|
|
||||||
# than that set for "node_rejoin_timeout")
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# "node rejoin" settings
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# These settings apply when reintegrating a node into a replication cluster
|
|
||||||
# with "repmgrd_node_rejoin"
|
|
||||||
|
|
||||||
#node_rejoin_timeout=60 # The maximum length of time (in seconds) to wait for
|
|
||||||
# the node to reconnect to the replication cluster
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Barman options
|
# Barman options
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
@@ -258,11 +236,6 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
# These settings are only applied when repmgrd is running. Values shown
|
# These settings are only applied when repmgrd is running. Values shown
|
||||||
# are defaults.
|
# are defaults.
|
||||||
|
|
||||||
#repmgrd_pid_file= # Path of PID file to use for repmgrd; if not set, a PID file will
|
|
||||||
# be generated in a temporary directory specified by the environment
|
|
||||||
# variable $TMPDIR, or if not set, in "/tmp". This value can be overridden
|
|
||||||
# by the command line option "-p/--pid-file"; the command line option
|
|
||||||
# "--no-pid-file" will force PID file creation to be skipped.
|
|
||||||
#failover=manual # one of 'automatic', 'manual'.
|
#failover=manual # one of 'automatic', 'manual'.
|
||||||
# determines what action to take in the event of upstream failure
|
# determines what action to take in the event of upstream failure
|
||||||
#
|
#
|
||||||
@@ -272,7 +245,7 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
# manual attention to reattach it to replication
|
# manual attention to reattach it to replication
|
||||||
# (does not apply to BDR mode)
|
# (does not apply to BDR mode)
|
||||||
|
|
||||||
#priority=100 # indicate a preferred priority for promoting nodes;
|
#priority=100 # indicate a preferred priorty for promoting nodes;
|
||||||
# a value of zero prevents the node being promoted to primary
|
# a value of zero prevents the node being promoted to primary
|
||||||
# (default: 100)
|
# (default: 100)
|
||||||
|
|
||||||
@@ -292,9 +265,8 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
#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,
|
||||||
# before falling back to degraded monitoring
|
# before falling back to degraded monitoring
|
||||||
#repmgrd_standby_startup_timeout=60 # Interval (in seconds) which repmgrd on a standby will wait
|
#standby_reconnect_timeout=60 # Interval (in seconds) which repmgrd on a standby will wait
|
||||||
# for the the local node to restart and become ready to accept connections after
|
# to reconnect to the local node after executing "follow_command"
|
||||||
# executing "follow_command" (defaults to the value set in "standby_reconnect_timeout")
|
|
||||||
|
|
||||||
#monitoring_history=no # Whether to write monitoring data to the "montoring_history" table
|
#monitoring_history=no # Whether to write monitoring data to the "montoring_history" table
|
||||||
#monitor_interval_secs=2 # Interval (in seconds) at which to write monitoring data
|
#monitor_interval_secs=2 # Interval (in seconds) at which to write monitoring data
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# repmgr extension
|
# repmgr extension
|
||||||
comment = 'Replication manager for PostgreSQL'
|
comment = 'Replication manager for PostgreSQL'
|
||||||
default_version = '4.1'
|
default_version = '4.0'
|
||||||
module_pathname = '$libdir/repmgr'
|
module_pathname = '$libdir/repmgr'
|
||||||
relocatable = false
|
relocatable = false
|
||||||
schema = repmgr
|
schema = repmgr
|
||||||
|
|||||||
5
repmgr.h
5
repmgr.h
@@ -49,8 +49,6 @@
|
|||||||
#define REPLICATION_TYPE_BDR 2
|
#define REPLICATION_TYPE_BDR 2
|
||||||
|
|
||||||
#define UNKNOWN_SERVER_VERSION_NUM -1
|
#define UNKNOWN_SERVER_VERSION_NUM -1
|
||||||
#define UNKNOWN_BDR_VERSION_NUM -1
|
|
||||||
|
|
||||||
#define UNKNOWN_TIMELINE_ID -1
|
#define UNKNOWN_TIMELINE_ID -1
|
||||||
#define UNKNOWN_SYSTEM_IDENTIFIER 0
|
#define UNKNOWN_SYSTEM_IDENTIFIER 0
|
||||||
|
|
||||||
@@ -60,8 +58,6 @@
|
|||||||
|
|
||||||
#define VOTING_TERM_NOT_SET -1
|
#define VOTING_TERM_NOT_SET -1
|
||||||
|
|
||||||
#define BDR2_REPLICATION_SET_NAME "repmgr"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* various default values - ensure repmgr.conf.sample is update
|
* various default values - ensure repmgr.conf.sample is update
|
||||||
* if any of these are changed
|
* if any of these are changed
|
||||||
@@ -85,7 +81,6 @@
|
|||||||
#define DEFAULT_PROMOTE_CHECK_TIMEOUT 60 /* seconds */
|
#define DEFAULT_PROMOTE_CHECK_TIMEOUT 60 /* seconds */
|
||||||
#define DEFAULT_PROMOTE_CHECK_INTERVAL 1 /* seconds */
|
#define DEFAULT_PROMOTE_CHECK_INTERVAL 1 /* seconds */
|
||||||
#define DEFAULT_STANDBY_RECONNECT_TIMEOUT 60 /* seconds */
|
#define DEFAULT_STANDBY_RECONNECT_TIMEOUT 60 /* seconds */
|
||||||
#define DEFAULT_NODE_REJOIN_TIMEOUT 60 /* seconds */
|
|
||||||
|
|
||||||
#ifndef RECOVERY_COMMAND_FILE
|
#ifndef RECOVERY_COMMAND_FILE
|
||||||
#define RECOVERY_COMMAND_FILE "recovery.conf"
|
#define RECOVERY_COMMAND_FILE "recovery.conf"
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
#define REPMGR_VERSION_DATE ""
|
#define REPMGR_VERSION_DATE ""
|
||||||
#define REPMGR_VERSION "4.1.0"
|
#define REPMGR_VERSION "4.0.6"
|
||||||
|
|
||||||
|
|||||||
@@ -162,8 +162,8 @@ do_physical_node_check(void)
|
|||||||
if (config_file_options.failover == FAILOVER_AUTOMATIC)
|
if (config_file_options.failover == FAILOVER_AUTOMATIC)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Check that "promote_command" and "follow_command" are defined, otherwise repmgrd
|
* check that promote/follow commands are defined, otherwise repmgrd
|
||||||
* won't be able to perform any useful action in a failover situation.
|
* won't be able to perform any useful action
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool required_param_missing = false;
|
bool required_param_missing = false;
|
||||||
@@ -175,24 +175,14 @@ do_physical_node_check(void)
|
|||||||
if (config_file_options.service_promote_command[0] != '\0')
|
if (config_file_options.service_promote_command[0] != '\0')
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* "service_promote_command" is *not* a substitute for "promote_command";
|
* if repmgrd executes "service_promote_command" directly,
|
||||||
* it is intended for use in those systems (e.g. Debian) where there's a service
|
* repmgr metadata won't get updated
|
||||||
* level promote command (e.g. pg_ctlcluster).
|
|
||||||
*
|
|
||||||
* "promote_command" should either execute "repmgr standby promote" directly, or
|
|
||||||
* a script which executes "repmgr standby promote". This is essential, as the
|
|
||||||
* repmgr metadata is updated by "repmgr standby promote".
|
|
||||||
*
|
|
||||||
* "service_promote_command", if set, will be executed by "repmgr standby promote",
|
|
||||||
* but never by repmgrd.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
log_hint(_("\"service_promote_command\" is set, but can only be executed by \"repmgr standby promote\""));
|
log_hint(_("\"service_promote_command\" is set, but can only be executed by \"repmgr standby promote\""));
|
||||||
}
|
}
|
||||||
|
|
||||||
required_param_missing = true;
|
required_param_missing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config_file_options.follow_command[0] == '\0')
|
if (config_file_options.follow_command[0] == '\0')
|
||||||
{
|
{
|
||||||
log_error(_("\"follow_command\" must be defined in the configuration file"));
|
log_error(_("\"follow_command\" must be defined in the configuration file"));
|
||||||
@@ -1549,15 +1539,8 @@ loop:
|
|||||||
static bool
|
static bool
|
||||||
do_primary_failover(void)
|
do_primary_failover(void)
|
||||||
{
|
{
|
||||||
ElectionResult election_result;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Double-check status of the local connection
|
|
||||||
*/
|
|
||||||
check_connection(&local_node_info, &local_conn);
|
|
||||||
|
|
||||||
/* attempt to initiate voting process */
|
/* attempt to initiate voting process */
|
||||||
election_result = do_election();
|
ElectionResult election_result = do_election();
|
||||||
|
|
||||||
/* TODO add pre-event notification here */
|
/* TODO add pre-event notification here */
|
||||||
failover_state = FAILOVER_STATE_UNKNOWN;
|
failover_state = FAILOVER_STATE_UNKNOWN;
|
||||||
@@ -1958,7 +1941,7 @@ do_upstream_standby_failover(void)
|
|||||||
* completes, so poll for a while until we get a connection.
|
* completes, so poll for a while until we get a connection.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (i = 0; i < config_file_options.repmgrd_standby_startup_timeout; i++)
|
for (i = 0; i < config_file_options.standby_reconnect_timeout; i++)
|
||||||
{
|
{
|
||||||
local_conn = establish_db_connection(local_node_info.conninfo, false);
|
local_conn = establish_db_connection(local_node_info.conninfo, false);
|
||||||
|
|
||||||
@@ -1967,7 +1950,7 @@ do_upstream_standby_failover(void)
|
|||||||
|
|
||||||
log_debug("sleeping 1 second; %i of %i attempts to reconnect to local node",
|
log_debug("sleeping 1 second; %i of %i attempts to reconnect to local node",
|
||||||
i + 1,
|
i + 1,
|
||||||
config_file_options.repmgrd_standby_startup_timeout);
|
config_file_options.standby_reconnect_timeout);
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2073,10 +2056,10 @@ promote_self(void)
|
|||||||
return FAILOVER_STATE_PROMOTION_FAILED;
|
return FAILOVER_STATE_PROMOTION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the presence of this command has been established already */
|
/* the presence of either of this command has been established already */
|
||||||
promote_command = config_file_options.promote_command;
|
promote_command = config_file_options.promote_command;
|
||||||
|
|
||||||
log_info(_("promote_command is:\n \"%s\""),
|
log_debug("promote command is:\n \"%s\"",
|
||||||
promote_command);
|
promote_command);
|
||||||
|
|
||||||
if (log_type == REPMGR_STDERR && *config_file_options.log_file)
|
if (log_type == REPMGR_STDERR && *config_file_options.log_file)
|
||||||
@@ -2408,7 +2391,7 @@ follow_new_primary(int new_primary_id)
|
|||||||
* completes, so poll for a while until we get a connection.
|
* completes, so poll for a while until we get a connection.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (i = 0; i < config_file_options.repmgrd_standby_startup_timeout; i++)
|
for (i = 0; i < config_file_options.standby_reconnect_timeout; i++)
|
||||||
{
|
{
|
||||||
local_conn = establish_db_connection(local_node_info.conninfo, false);
|
local_conn = establish_db_connection(local_node_info.conninfo, false);
|
||||||
|
|
||||||
@@ -2417,7 +2400,7 @@ follow_new_primary(int new_primary_id)
|
|||||||
|
|
||||||
log_debug("sleeping 1 second; %i of %i attempts to reconnect to local node",
|
log_debug("sleeping 1 second; %i of %i attempts to reconnect to local node",
|
||||||
i + 1,
|
i + 1,
|
||||||
config_file_options.repmgrd_standby_startup_timeout);
|
config_file_options.standby_reconnect_timeout);
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
101
repmgrd.c
101
repmgrd.c
@@ -35,10 +35,8 @@
|
|||||||
|
|
||||||
static char *config_file = NULL;
|
static char *config_file = NULL;
|
||||||
static bool verbose = false;
|
static bool verbose = false;
|
||||||
static char pid_file[MAXPGPATH];
|
static char *pid_file = NULL;
|
||||||
static bool daemonize = true;
|
static bool daemonize = false;
|
||||||
static bool show_pid_file = false;
|
|
||||||
static bool no_pid_file = false;
|
|
||||||
|
|
||||||
t_configuration_options config_file_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
t_configuration_options config_file_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
||||||
|
|
||||||
@@ -101,10 +99,8 @@ main(int argc, char **argv)
|
|||||||
{"config-file", required_argument, NULL, 'f'},
|
{"config-file", required_argument, NULL, 'f'},
|
||||||
|
|
||||||
/* daemon options */
|
/* daemon options */
|
||||||
{"daemonize", optional_argument, NULL, 'd'},
|
{"daemonize", no_argument, NULL, 'd'},
|
||||||
{"pid-file", required_argument, NULL, 'p'},
|
{"pid-file", required_argument, NULL, 'p'},
|
||||||
{"show-pid-file", no_argument, NULL, 's'},
|
|
||||||
{"no-pid-file", no_argument, NULL, OPT_NO_PID_FILE},
|
|
||||||
|
|
||||||
/* logging options */
|
/* logging options */
|
||||||
{"log-level", required_argument, NULL, 'L'},
|
{"log-level", required_argument, NULL, 'L'},
|
||||||
@@ -117,6 +113,8 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
set_progname(argv[0]);
|
set_progname(argv[0]);
|
||||||
|
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
/* Disallow running as root */
|
/* Disallow running as root */
|
||||||
if (geteuid() == 0)
|
if (geteuid() == 0)
|
||||||
{
|
{
|
||||||
@@ -130,10 +128,6 @@ main(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
srand(time(NULL));
|
|
||||||
|
|
||||||
memset(pid_file, 0, MAXPGPATH);
|
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "?Vf:L:vdp:m", long_options, &optindex)) != -1)
|
while ((c = getopt_long(argc, argv, "?Vf:L:vdp:m", long_options, &optindex)) != -1)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
@@ -175,22 +169,11 @@ main(int argc, char **argv)
|
|||||||
/* daemon options */
|
/* daemon options */
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
if (optarg != NULL)
|
daemonize = true;
|
||||||
{
|
|
||||||
daemonize = parse_bool(optarg, "-d/--daemonize", &cli_errors);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
strncpy(pid_file, optarg, MAXPGPATH);
|
pid_file = optarg;
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
show_pid_file = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPT_NO_PID_FILE:
|
|
||||||
no_pid_file = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* logging options */
|
/* logging options */
|
||||||
@@ -237,7 +220,7 @@ main(int argc, char **argv)
|
|||||||
/* Exit here already if errors in command line options found */
|
/* Exit here already if errors in command line options found */
|
||||||
if (cli_errors.head != NULL)
|
if (cli_errors.head != NULL)
|
||||||
{
|
{
|
||||||
exit_with_cli_errors(&cli_errors, NULL);
|
exit_with_cli_errors(&cli_errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
startup_event_logged = false;
|
startup_event_logged = false;
|
||||||
@@ -256,58 +239,6 @@ main(int argc, char **argv)
|
|||||||
*/
|
*/
|
||||||
load_config(config_file, verbose, false, &config_file_options, argv[0]);
|
load_config(config_file, verbose, false, &config_file_options, argv[0]);
|
||||||
|
|
||||||
/* Determine pid file location, unless --no-pid-file supplied */
|
|
||||||
|
|
||||||
if (no_pid_file == false)
|
|
||||||
{
|
|
||||||
if (config_file_options.repmgrd_pid_file[0] != '\0')
|
|
||||||
{
|
|
||||||
if (pid_file[0] != '\0')
|
|
||||||
{
|
|
||||||
log_warning(_("\"repmgrd_pid_file\" will be overridden by --pid-file"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strncpy(pid_file, config_file_options.repmgrd_pid_file, MAXPGPATH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no pid file provided - determine location */
|
|
||||||
if (pid_file[0] == '\0')
|
|
||||||
{
|
|
||||||
/* packagers: if feasible, patch PID file path into "package_pid_file" */
|
|
||||||
char package_pid_file[MAXPGPATH] = "";
|
|
||||||
|
|
||||||
if (package_pid_file[0] != '\0')
|
|
||||||
{
|
|
||||||
maxpath_snprintf(pid_file, "%s", package_pid_file);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const char *tmpdir = getenv("TMPDIR");
|
|
||||||
|
|
||||||
if (!tmpdir)
|
|
||||||
tmpdir = "/tmp";
|
|
||||||
|
|
||||||
maxpath_snprintf(pid_file, "%s/repmgrd.pid", tmpdir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* --no-pid-file supplied - overwrite any value provided with --pid-file ... */
|
|
||||||
memset(pid_file, 0, MAXPGPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* If --show-pid-file supplied, output the location (if set) and exit */
|
|
||||||
|
|
||||||
if (show_pid_file == true)
|
|
||||||
{
|
|
||||||
printf("%s\n", pid_file);
|
|
||||||
exit(SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Some configuration file items can be overriden by command line options */
|
/* Some configuration file items can be overriden by command line options */
|
||||||
|
|
||||||
@@ -483,7 +414,7 @@ main(int argc, char **argv)
|
|||||||
daemonize_process();
|
daemonize_process();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid_file[0] != '\0')
|
if (pid_file != NULL)
|
||||||
{
|
{
|
||||||
check_and_create_pid_file(pid_file);
|
check_and_create_pid_file(pid_file);
|
||||||
}
|
}
|
||||||
@@ -738,8 +669,6 @@ show_help(void)
|
|||||||
{
|
{
|
||||||
printf(_("%s: replication management daemon for PostgreSQL\n"), progname());
|
printf(_("%s: replication management daemon for PostgreSQL\n"), progname());
|
||||||
puts("");
|
puts("");
|
||||||
printf(_("%s monitors a cluster of servers and optionally performs failover.\n"), progname());
|
|
||||||
puts("");
|
|
||||||
|
|
||||||
printf(_("Usage:\n"));
|
printf(_("Usage:\n"));
|
||||||
printf(_(" %s [OPTIONS]\n"), progname());
|
printf(_(" %s [OPTIONS]\n"), progname());
|
||||||
@@ -759,14 +688,12 @@ show_help(void)
|
|||||||
|
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
printf(_("Daemon configuration options:\n"));
|
printf(_("General configuration options:\n"));
|
||||||
printf(_(" -d, --daemonize[=true/false]\n"));
|
printf(_(" -d, --daemonize detach process from foreground\n"));
|
||||||
printf(_(" detach process from foreground (default: true)\n"));
|
printf(_(" -p, --pid-file=PATH write a PID file\n"));
|
||||||
printf(_(" -p, --pid-file=PATH use the specified PID file\n"));
|
|
||||||
printf(_(" -s, --show-pid-file show PID file which would be used by the current configuration\n"));
|
|
||||||
printf(_(" --no-pid-file don't write a PID file\n"));
|
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
|
printf(_("%s monitors a cluster of servers and optionally performs failover.\n"), progname());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -875,7 +802,7 @@ terminate(int retval)
|
|||||||
{
|
{
|
||||||
logger_shutdown();
|
logger_shutdown();
|
||||||
|
|
||||||
if (pid_file[0] != '\0')
|
if (pid_file)
|
||||||
{
|
{
|
||||||
unlink(pid_file);
|
unlink(pid_file);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "portability/instr_time.h"
|
#include "portability/instr_time.h"
|
||||||
|
|
||||||
#define OPT_NO_PID_FILE 1000
|
|
||||||
|
|
||||||
extern volatile sig_atomic_t got_SIGHUP;
|
extern volatile sig_atomic_t got_SIGHUP;
|
||||||
extern MonitoringState monitoring_state;
|
extern MonitoringState monitoring_state;
|
||||||
extern instr_time degraded_monitoring_start;
|
extern instr_time degraded_monitoring_start;
|
||||||
@@ -28,6 +26,4 @@ const char *print_monitoring_state(MonitoringState monitoring_state);
|
|||||||
|
|
||||||
void update_registration(PGconn *conn);
|
void update_registration(PGconn *conn);
|
||||||
void terminate(int retval);
|
void terminate(int retval);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _REPMGRD_H_ */
|
#endif /* _REPMGRD_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user