mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-22 22:56:29 +00:00
Revert "Convert configuration file parsing to use flex"
This reverts commit c6ca183247.
Backing out this patch for now as the Debian build system doesn't
seem to like it, even though it builds just fine on Debian itself.
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -53,6 +53,3 @@ repmgr
|
|||||||
repmgrd
|
repmgrd
|
||||||
repmgr4
|
repmgr4
|
||||||
repmgrd4
|
repmgrd4
|
||||||
|
|
||||||
# generated files
|
|
||||||
configfile-scan.c
|
|
||||||
|
|||||||
3
HISTORY
3
HISTORY
@@ -1,6 +1,3 @@
|
|||||||
4.5 2019-??-??
|
|
||||||
general: parse configuration file using flex (Ian)
|
|
||||||
|
|
||||||
4.4 2019-06-27
|
4.4 2019-06-27
|
||||||
repmgr: improve "daemon status" output (Ian)
|
repmgr: improve "daemon status" output (Ian)
|
||||||
repmgr: add "--siblings-follow" option to "standby promote" (Ian)
|
repmgr: add "--siblings-follow" option to "standby promote" (Ian)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
# Makefile.global.in
|
# Makefile.global.in
|
||||||
# @configure_input@
|
# @configure_input@
|
||||||
|
|
||||||
|
|
||||||
# Can only be built using pgxs
|
# Can only be built using pgxs
|
||||||
USE_PGXS=1
|
USE_PGXS=1
|
||||||
|
|
||||||
@@ -27,11 +26,3 @@ include $(PGXS)
|
|||||||
REPMGR_VERSION=$(shell awk '/^\#define REPMGR_VERSION / { print $3; }' ${repmgr_abs_srcdir}/repmgr_version.h.in | cut -d '"' -f 2)
|
REPMGR_VERSION=$(shell awk '/^\#define REPMGR_VERSION / { print $3; }' ${repmgr_abs_srcdir}/repmgr_version.h.in | cut -d '"' -f 2)
|
||||||
REPMGR_RELEASE_DATE=$(shell awk '/^\#define REPMGR_RELEASE_DATE / { print $3; }' ${repmgr_abs_srcdir}/repmgr_version.h.in | cut -d '"' -f 2)
|
REPMGR_RELEASE_DATE=$(shell awk '/^\#define REPMGR_RELEASE_DATE / { print $3; }' ${repmgr_abs_srcdir}/repmgr_version.h.in | cut -d '"' -f 2)
|
||||||
|
|
||||||
FLEX = flex
|
|
||||||
|
|
||||||
##########################################################################
|
|
||||||
#
|
|
||||||
# Global targets and rules
|
|
||||||
|
|
||||||
%.c: %.l
|
|
||||||
$(FLEX) $(FLEXFLAGS) -o'$@' $<
|
|
||||||
|
|||||||
@@ -54,15 +54,13 @@ $(info Building against PostgreSQL $(MAJORVERSION))
|
|||||||
REPMGR_CLIENT_OBJS = repmgr-client.o \
|
REPMGR_CLIENT_OBJS = repmgr-client.o \
|
||||||
repmgr-action-primary.o repmgr-action-standby.o repmgr-action-witness.o \
|
repmgr-action-primary.o repmgr-action-standby.o repmgr-action-witness.o \
|
||||||
repmgr-action-bdr.o repmgr-action-cluster.o repmgr-action-node.o repmgr-action-daemon.o \
|
repmgr-action-bdr.o repmgr-action-cluster.o repmgr-action-node.o repmgr-action-daemon.o \
|
||||||
configfile.o configfile-scan.o log.o strutil.o controldata.o dirutil.o compat.o dbutils.o sysutils.o
|
configfile.o log.o strutil.o controldata.o dirutil.o compat.o dbutils.o sysutils.o
|
||||||
REPMGRD_OBJS = repmgrd.o repmgrd-physical.o repmgrd-bdr.o configfile.o configfile-scan.o log.o dbutils.o strutil.o controldata.o compat.o sysutils.o
|
REPMGRD_OBJS = repmgrd.o repmgrd-physical.o repmgrd-bdr.o configfile.o log.o dbutils.o strutil.o controldata.o compat.o sysutils.o
|
||||||
DATE=$(shell date "+%Y-%m-%d")
|
DATE=$(shell date "+%Y-%m-%d")
|
||||||
|
|
||||||
repmgr_version.h: repmgr_version.h.in
|
repmgr_version.h: repmgr_version.h.in
|
||||||
sed '0,/REPMGR_VERSION_DATE/s,\(REPMGR_VERSION_DATE\).*,\1 "$(DATE)",' $< >$@
|
sed '0,/REPMGR_VERSION_DATE/s,\(REPMGR_VERSION_DATE\).*,\1 "$(DATE)",' $< >$@
|
||||||
|
|
||||||
configfile-scan.c: configfile-scan.l
|
|
||||||
|
|
||||||
$(REPMGR_CLIENT_OBJS): repmgr-client.h repmgr_version.h
|
$(REPMGR_CLIENT_OBJS): repmgr-client.h repmgr_version.h
|
||||||
|
|
||||||
repmgr: $(REPMGR_CLIENT_OBJS)
|
repmgr: $(REPMGR_CLIENT_OBJS)
|
||||||
|
|||||||
@@ -1,346 +0,0 @@
|
|||||||
/*
|
|
||||||
* Scanner for the configuration file
|
|
||||||
*/
|
|
||||||
|
|
||||||
%{
|
|
||||||
|
|
||||||
#define FRONTEND
|
|
||||||
|
|
||||||
#include "postgres.h"
|
|
||||||
|
|
||||||
#include "repmgr.h"
|
|
||||||
#include "configfile.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* flex emits a yy_fatal_error() function that it calls in response to
|
|
||||||
* critical errors like malloc failure, file I/O errors, and detection of
|
|
||||||
* internal inconsistency. That function prints a message and calls exit().
|
|
||||||
* Mutate it to instead call our handler, which jumps out of the parser.
|
|
||||||
*/
|
|
||||||
#undef fprintf
|
|
||||||
#define fprintf(file, fmt, msg) CONF_flex_fatal(msg)
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
CONF_ID = 1,
|
|
||||||
CONF_STRING = 2,
|
|
||||||
CONF_INTEGER = 3,
|
|
||||||
CONF_REAL = 4,
|
|
||||||
CONF_EQUALS = 5,
|
|
||||||
CONF_UNQUOTED_STRING = 6,
|
|
||||||
CONF_QUALIFIED_ID = 7,
|
|
||||||
CONF_EOL = 99,
|
|
||||||
CONF_ERROR = 100
|
|
||||||
};
|
|
||||||
|
|
||||||
static unsigned int ConfigFileLineno;
|
|
||||||
static const char *CONF_flex_fatal_errmsg;
|
|
||||||
static sigjmp_buf *CONF_flex_fatal_jmp;
|
|
||||||
|
|
||||||
static char *CONF_scanstr(const char *s);
|
|
||||||
static int CONF_flex_fatal(const char *msg);
|
|
||||||
|
|
||||||
%}
|
|
||||||
|
|
||||||
%option 8bit
|
|
||||||
%option never-interactive
|
|
||||||
%option nodefault
|
|
||||||
%option noinput
|
|
||||||
%option nounput
|
|
||||||
%option noyywrap
|
|
||||||
%option warn
|
|
||||||
%option prefix="CONF_yy"
|
|
||||||
|
|
||||||
|
|
||||||
SIGN ("-"|"+")
|
|
||||||
DIGIT [0-9]
|
|
||||||
HEXDIGIT [0-9a-fA-F]
|
|
||||||
|
|
||||||
UNIT_LETTER [a-zA-Z]
|
|
||||||
|
|
||||||
INTEGER {SIGN}?({DIGIT}+|0x{HEXDIGIT}+){UNIT_LETTER}*
|
|
||||||
|
|
||||||
EXPONENT [Ee]{SIGN}?{DIGIT}+
|
|
||||||
REAL {SIGN}?{DIGIT}*"."{DIGIT}*{EXPONENT}?
|
|
||||||
|
|
||||||
LETTER [A-Za-z_\200-\377]
|
|
||||||
LETTER_OR_DIGIT [A-Za-z_0-9\200-\377]
|
|
||||||
|
|
||||||
ID {LETTER}{LETTER_OR_DIGIT}*
|
|
||||||
QUALIFIED_ID {ID}"."{ID}
|
|
||||||
|
|
||||||
UNQUOTED_STRING {LETTER}({LETTER_OR_DIGIT}|[-._:/])*
|
|
||||||
STRING \'([^'\\\n]|\\.|\'\')*\'
|
|
||||||
|
|
||||||
%%
|
|
||||||
|
|
||||||
\n ConfigFileLineno++; return CONF_EOL;
|
|
||||||
[ \t\r]+ /* eat whitespace */
|
|
||||||
#.* /* eat comment (.* matches anything until newline) */
|
|
||||||
|
|
||||||
{ID} return CONF_ID;
|
|
||||||
{QUALIFIED_ID} return CONF_QUALIFIED_ID;
|
|
||||||
{STRING} return CONF_STRING;
|
|
||||||
{UNQUOTED_STRING} return CONF_UNQUOTED_STRING;
|
|
||||||
{INTEGER} return CONF_INTEGER;
|
|
||||||
{REAL} return CONF_REAL;
|
|
||||||
= return CONF_EQUALS;
|
|
||||||
|
|
||||||
. return CONF_ERROR;
|
|
||||||
|
|
||||||
%%
|
|
||||||
|
|
||||||
|
|
||||||
extern bool
|
|
||||||
ProcessConfigFile(FILE *fp, const char *config_file, t_configuration_options *options, ItemList *error_list, ItemList *warning_list)
|
|
||||||
{
|
|
||||||
volatile bool OK = true;
|
|
||||||
volatile YY_BUFFER_STATE lex_buffer = NULL;
|
|
||||||
sigjmp_buf flex_fatal_jmp;
|
|
||||||
int errorcount;
|
|
||||||
int token;
|
|
||||||
|
|
||||||
if (sigsetjmp(flex_fatal_jmp, 1) == 0)
|
|
||||||
{
|
|
||||||
CONF_flex_fatal_jmp = &flex_fatal_jmp;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Regain control after a fatal, internal flex error. It may have
|
|
||||||
* corrupted parser state. Consequently, abandon the file, but trust
|
|
||||||
* that the state remains sane enough for yy_delete_buffer().
|
|
||||||
*/
|
|
||||||
item_list_append_format(error_list,
|
|
||||||
"%s at file \"%s\" line %u",
|
|
||||||
CONF_flex_fatal_errmsg, config_file, ConfigFileLineno);
|
|
||||||
OK = false;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parse
|
|
||||||
*/
|
|
||||||
ConfigFileLineno = 1;
|
|
||||||
errorcount = 0;
|
|
||||||
|
|
||||||
lex_buffer = yy_create_buffer(fp, YY_BUF_SIZE);
|
|
||||||
yy_switch_to_buffer(lex_buffer);
|
|
||||||
|
|
||||||
/* This loop iterates once per logical line */
|
|
||||||
while ((token = yylex()))
|
|
||||||
{
|
|
||||||
char *opt_name = NULL;
|
|
||||||
char *opt_value = NULL;
|
|
||||||
|
|
||||||
if (token == CONF_EOL) /* empty or comment line */
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* first token on line is option name */
|
|
||||||
if (token != CONF_ID && token != CONF_QUALIFIED_ID)
|
|
||||||
goto parse_error;
|
|
||||||
opt_name = pstrdup(yytext);
|
|
||||||
|
|
||||||
/* next we have an optional equal sign; discard if present */
|
|
||||||
token = yylex();
|
|
||||||
if (token == CONF_EQUALS)
|
|
||||||
token = yylex();
|
|
||||||
|
|
||||||
/* now we must have the option value */
|
|
||||||
if (token != CONF_ID &&
|
|
||||||
token != CONF_STRING &&
|
|
||||||
token != CONF_INTEGER &&
|
|
||||||
token != CONF_REAL &&
|
|
||||||
token != CONF_UNQUOTED_STRING)
|
|
||||||
goto parse_error;
|
|
||||||
if (token == CONF_STRING) /* strip quotes and escapes */
|
|
||||||
opt_value = CONF_scanstr(yytext);
|
|
||||||
else
|
|
||||||
opt_value = pstrdup(yytext);
|
|
||||||
|
|
||||||
/* now we'd like an end of line, or possibly EOF */
|
|
||||||
token = yylex();
|
|
||||||
if (token != CONF_EOL)
|
|
||||||
{
|
|
||||||
if (token != 0)
|
|
||||||
goto parse_error;
|
|
||||||
/* treat EOF like \n for line numbering purposes, cf bug 4752 */
|
|
||||||
ConfigFileLineno++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OK, process the option name and value */
|
|
||||||
|
|
||||||
parse_configuration_item(options,
|
|
||||||
error_list,
|
|
||||||
warning_list,
|
|
||||||
opt_name,
|
|
||||||
opt_value);
|
|
||||||
|
|
||||||
/* break out of loop if read EOF, else loop for next line */
|
|
||||||
if (token == 0)
|
|
||||||
break;
|
|
||||||
continue;
|
|
||||||
|
|
||||||
parse_error:
|
|
||||||
/* release storage if we allocated any on this line */
|
|
||||||
if (opt_name)
|
|
||||||
pfree(opt_name);
|
|
||||||
if (opt_value)
|
|
||||||
pfree(opt_value);
|
|
||||||
|
|
||||||
/* report the error */
|
|
||||||
if (token == CONF_EOL || token == 0)
|
|
||||||
{
|
|
||||||
item_list_append_format(error_list,
|
|
||||||
_("syntax error in file \"%s\" line %u, near end of line"),
|
|
||||||
config_file, ConfigFileLineno - 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item_list_append_format(error_list,
|
|
||||||
_("syntax error in file \"%s\" line %u, near token \"%s\""),
|
|
||||||
config_file, ConfigFileLineno, yytext);
|
|
||||||
}
|
|
||||||
OK = false;
|
|
||||||
errorcount++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* To avoid producing too much noise when fed a totally bogus file,
|
|
||||||
* give up after 100 syntax errors per file (an arbitrary number).
|
|
||||||
* Also, if we're only logging the errors at DEBUG level anyway, might
|
|
||||||
* as well give up immediately. (This prevents postmaster children
|
|
||||||
* from bloating the logs with duplicate complaints.)
|
|
||||||
*/
|
|
||||||
if (errorcount >= 100)
|
|
||||||
{
|
|
||||||
fprintf(stderr,
|
|
||||||
_("too many syntax errors found, abandoning file \"%s\"\n"),
|
|
||||||
config_file);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* resync to next end-of-line or EOF */
|
|
||||||
while (token != CONF_EOL && token != 0)
|
|
||||||
token = yylex();
|
|
||||||
/* break out of loop on EOF */
|
|
||||||
if (token == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
yy_delete_buffer(lex_buffer);
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* scanstr
|
|
||||||
*
|
|
||||||
* Strip the quotes surrounding the given string, and collapse any embedded
|
|
||||||
* '' sequences and backslash escapes.
|
|
||||||
*
|
|
||||||
* the string returned is palloc'd and should eventually be pfree'd by the
|
|
||||||
* caller.
|
|
||||||
*/
|
|
||||||
static char *
|
|
||||||
CONF_scanstr(const char *s)
|
|
||||||
{
|
|
||||||
char *newStr;
|
|
||||||
int len,
|
|
||||||
i,
|
|
||||||
j;
|
|
||||||
|
|
||||||
Assert(s != NULL && s[0] == '\'');
|
|
||||||
len = strlen(s);
|
|
||||||
Assert(s != NULL);
|
|
||||||
|
|
||||||
Assert(len >= 2);
|
|
||||||
Assert(s[len - 1] == '\'');
|
|
||||||
|
|
||||||
/* Skip the leading quote; we'll handle the trailing quote below */
|
|
||||||
s++, len--;
|
|
||||||
|
|
||||||
/* Since len still includes trailing quote, this is enough space */
|
|
||||||
newStr = palloc(len);
|
|
||||||
|
|
||||||
for (i = 0, j = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
if (s[i] == '\\')
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
switch (s[i])
|
|
||||||
{
|
|
||||||
case 'b':
|
|
||||||
newStr[j] = '\b';
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
newStr[j] = '\f';
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
newStr[j] = '\n';
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
newStr[j] = '\r';
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
newStr[j] = '\t';
|
|
||||||
break;
|
|
||||||
case '0':
|
|
||||||
case '1':
|
|
||||||
case '2':
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
case '5':
|
|
||||||
case '6':
|
|
||||||
case '7':
|
|
||||||
{
|
|
||||||
int k;
|
|
||||||
long octVal = 0;
|
|
||||||
|
|
||||||
for (k = 0;
|
|
||||||
s[i + k] >= '0' && s[i + k] <= '7' && k < 3;
|
|
||||||
k++)
|
|
||||||
octVal = (octVal << 3) + (s[i + k] - '0');
|
|
||||||
i += k - 1;
|
|
||||||
newStr[j] = ((char) octVal);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
newStr[j] = s[i];
|
|
||||||
break;
|
|
||||||
} /* switch */
|
|
||||||
}
|
|
||||||
else if (s[i] == '\'' && s[i + 1] == '\'')
|
|
||||||
{
|
|
||||||
/* doubled quote becomes just one quote */
|
|
||||||
newStr[j] = s[++i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
newStr[j] = s[i];
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We copied the ending quote to newStr, so replace with \0 */
|
|
||||||
Assert(j > 0 && j <= len);
|
|
||||||
newStr[--j] = '\0';
|
|
||||||
|
|
||||||
return newStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Flex fatal errors bring us here. Stash the error message and jump back to
|
|
||||||
* ParseConfigFp(). Assume all msg arguments point to string constants; this
|
|
||||||
* holds for flex 2.5.31 (earliest we support) and flex 2.5.35 (latest as of
|
|
||||||
* this writing). Otherwise, we would need to copy the message.
|
|
||||||
*
|
|
||||||
* We return "int" since this takes the place of calls to fprintf().
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
CONF_flex_fatal(const char *msg)
|
|
||||||
{
|
|
||||||
CONF_flex_fatal_errmsg = msg;
|
|
||||||
siglongjmp(*CONF_flex_fatal_jmp, 1);
|
|
||||||
return 0; /* keep compiler quiet */
|
|
||||||
}
|
|
||||||
706
configfile.c
706
configfile.c
@@ -266,6 +266,12 @@ static void
|
|||||||
_parse_config(t_configuration_options *options, ItemList *error_list, ItemList *warning_list)
|
_parse_config(t_configuration_options *options, ItemList *error_list, ItemList *warning_list)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
char *s = NULL,
|
||||||
|
buf[MAXLINELENGTH] = "";
|
||||||
|
char name[MAXLEN] = "";
|
||||||
|
char value[MAXLEN] = "";
|
||||||
|
|
||||||
|
bool node_id_found = false;
|
||||||
|
|
||||||
/* Initialize configuration options with sensible defaults */
|
/* Initialize configuration options with sensible defaults */
|
||||||
|
|
||||||
@@ -462,12 +468,365 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) ProcessConfigFile(fp, config_file_path, options, error_list, warning_list);
|
/* Read file */
|
||||||
|
while ((s = fgets(buf, sizeof buf, fp)) != NULL)
|
||||||
|
{
|
||||||
|
bool known_parameter = true;
|
||||||
|
|
||||||
|
/* Parse name/value pair from line */
|
||||||
|
_parse_line(buf, name, value);
|
||||||
|
|
||||||
|
/* Skip blank lines */
|
||||||
|
if (!strlen(name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Skip comments */
|
||||||
|
if (name[0] == '#')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Copy into correct entry in parameters struct */
|
||||||
|
if (strcmp(name, "node_id") == 0)
|
||||||
|
{
|
||||||
|
options->node_id = repmgr_atoi(value, name, error_list, MIN_NODE_ID);
|
||||||
|
node_id_found = true;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "node_name") == 0)
|
||||||
|
{
|
||||||
|
if (strlen(value) < sizeof(options->node_name))
|
||||||
|
strncpy(options->node_name, value, sizeof(options->node_name));
|
||||||
|
else
|
||||||
|
item_list_append_format(error_list,
|
||||||
|
_("value for \"node_name\" must contain fewer than %lu characters"),
|
||||||
|
sizeof(options->node_name));
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "conninfo") == 0)
|
||||||
|
strncpy(options->conninfo, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "data_directory") == 0)
|
||||||
|
{
|
||||||
|
strncpy(options->data_directory, value, MAXPGPATH);
|
||||||
|
canonicalize_path(options->data_directory);
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "config_directory") == 0)
|
||||||
|
{
|
||||||
|
strncpy(options->config_directory, value, MAXPGPATH);
|
||||||
|
canonicalize_path(options->config_directory);
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "replication_user") == 0)
|
||||||
|
{
|
||||||
|
if (strlen(value) < sizeof(options->replication_user))
|
||||||
|
strncpy(options->replication_user, value, sizeof(options->replication_user));
|
||||||
|
else
|
||||||
|
item_list_append_format(error_list,
|
||||||
|
_("value for \"replication_user\" must contain fewer than %lu characters"),
|
||||||
|
sizeof(options->replication_user));
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "pg_bindir") == 0)
|
||||||
|
strncpy(options->pg_bindir, value, MAXPGPATH);
|
||||||
|
else if (strcmp(name, "repmgr_bindir") == 0)
|
||||||
|
strncpy(options->repmgr_bindir, value, MAXPGPATH);
|
||||||
|
|
||||||
|
else if (strcmp(name, "replication_type") == 0)
|
||||||
|
{
|
||||||
|
if (strcmp(value, "physical") == 0)
|
||||||
|
options->replication_type = REPLICATION_TYPE_PHYSICAL;
|
||||||
|
else if (strcmp(value, "bdr") == 0)
|
||||||
|
options->replication_type = REPLICATION_TYPE_BDR;
|
||||||
|
else
|
||||||
|
item_list_append(error_list, _("value for \"replication_type\" must be \"physical\" or \"bdr\""));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* log settings */
|
||||||
|
else if (strcmp(name, "log_file") == 0)
|
||||||
|
strncpy(options->log_file, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "log_level") == 0)
|
||||||
|
strncpy(options->log_level, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "log_facility") == 0)
|
||||||
|
strncpy(options->log_facility, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "log_status_interval") == 0)
|
||||||
|
options->log_status_interval = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
|
||||||
|
/* standby clone settings */
|
||||||
|
else if (strcmp(name, "use_replication_slots") == 0)
|
||||||
|
options->use_replication_slots = parse_bool(value, name, error_list);
|
||||||
|
else if (strcmp(name, "pg_basebackup_options") == 0)
|
||||||
|
strncpy(options->pg_basebackup_options, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "tablespace_mapping") == 0)
|
||||||
|
tablespace_list_append(options, value);
|
||||||
|
else if (strcmp(name, "restore_command") == 0)
|
||||||
|
strncpy(options->restore_command, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "recovery_min_apply_delay") == 0)
|
||||||
|
{
|
||||||
|
parse_time_unit_parameter(name, value, options->recovery_min_apply_delay, error_list);
|
||||||
|
options->recovery_min_apply_delay_provided = true;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "archive_cleanup_command") == 0)
|
||||||
|
strncpy(options->archive_cleanup_command, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "use_primary_conninfo_password") == 0)
|
||||||
|
options->use_primary_conninfo_password = parse_bool(value, name, error_list);
|
||||||
|
else if (strcmp(name, "passfile") == 0)
|
||||||
|
strncpy(options->passfile, value, sizeof(options->passfile));
|
||||||
|
|
||||||
|
/* standby promote settings */
|
||||||
|
else if (strcmp(name, "promote_check_timeout") == 0)
|
||||||
|
options->promote_check_timeout = repmgr_atoi(value, name, error_list, 1);
|
||||||
|
|
||||||
|
else if (strcmp(name, "promote_check_interval") == 0)
|
||||||
|
options->promote_check_interval = repmgr_atoi(value, name, error_list, 1);
|
||||||
|
|
||||||
|
/* standby follow settings */
|
||||||
|
else if (strcmp(name, "primary_follow_timeout") == 0)
|
||||||
|
options->primary_follow_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
else if (strcmp(name, "standby_follow_timeout") == 0)
|
||||||
|
options->standby_follow_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
|
||||||
|
/* standby switchover settings */
|
||||||
|
else if (strcmp(name, "shutdown_check_timeout") == 0)
|
||||||
|
options->shutdown_check_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
else if (strcmp(name, "standby_reconnect_timeout") == 0)
|
||||||
|
options->standby_reconnect_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
else if (strcmp(name, "wal_receive_check_timeout") == 0)
|
||||||
|
options->wal_receive_check_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 */
|
||||||
|
else if (strcmp(name, "archive_ready_warning") == 0)
|
||||||
|
options->archive_ready_warning = repmgr_atoi(value, name, error_list, 1);
|
||||||
|
else if (strcmp(name, "archive_ready_critical") == 0)
|
||||||
|
options->archive_ready_critical = repmgr_atoi(value, name, error_list, 1);
|
||||||
|
else if (strcmp(name, "replication_lag_warning") == 0)
|
||||||
|
options->replication_lag_warning = repmgr_atoi(value, name, error_list, 1);
|
||||||
|
else if (strcmp(name, "replication_lag_critical") == 0)
|
||||||
|
options->replication_lag_critical = repmgr_atoi(value, name, error_list, 1);
|
||||||
|
|
||||||
|
/* repmgrd settings */
|
||||||
|
else if (strcmp(name, "failover") == 0)
|
||||||
|
{
|
||||||
|
if (strcmp(value, "manual") == 0)
|
||||||
|
{
|
||||||
|
options->failover = FAILOVER_MANUAL;
|
||||||
|
}
|
||||||
|
else if (strcmp(value, "automatic") == 0)
|
||||||
|
{
|
||||||
|
options->failover = FAILOVER_AUTOMATIC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item_list_append(error_list,
|
||||||
|
_("value for \"failover\" must be \"automatic\" or \"manual\"\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "priority") == 0)
|
||||||
|
options->priority = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
else if (strcmp(name, "location") == 0)
|
||||||
|
strncpy(options->location, value, sizeof(options->location));
|
||||||
|
else if (strcmp(name, "promote_command") == 0)
|
||||||
|
strncpy(options->promote_command, value, sizeof(options->promote_command));
|
||||||
|
else if (strcmp(name, "follow_command") == 0)
|
||||||
|
strncpy(options->follow_command, value, sizeof(options->follow_command));
|
||||||
|
else if (strcmp(name, "reconnect_attempts") == 0)
|
||||||
|
options->reconnect_attempts = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
else if (strcmp(name, "reconnect_interval") == 0)
|
||||||
|
options->reconnect_interval = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
else if (strcmp(name, "monitor_interval_secs") == 0)
|
||||||
|
options->monitor_interval_secs = repmgr_atoi(value, name, error_list, 1);
|
||||||
|
else if (strcmp(name, "monitoring_history") == 0)
|
||||||
|
options->monitoring_history = parse_bool(value, name, error_list);
|
||||||
|
else if (strcmp(name, "degraded_monitoring_timeout") == 0)
|
||||||
|
options->degraded_monitoring_timeout = repmgr_atoi(value, name, error_list, -1);
|
||||||
|
else if (strcmp(name, "async_query_timeout") == 0)
|
||||||
|
options->async_query_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
else if (strcmp(name, "primary_notification_timeout") == 0)
|
||||||
|
options->primary_notification_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
else if (strcmp(name, "repmgrd_standby_startup_timeout") == 0)
|
||||||
|
options->repmgrd_standby_startup_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
else if (strcmp(name, "repmgrd_pid_file") == 0)
|
||||||
|
strncpy(options->repmgrd_pid_file, value, MAXPGPATH);
|
||||||
|
else if (strcmp(name, "standby_disconnect_on_failover") == 0)
|
||||||
|
options->standby_disconnect_on_failover = parse_bool(value, name, error_list);
|
||||||
|
else if (strcmp(name, "sibling_nodes_disconnect_timeout") == 0)
|
||||||
|
options->sibling_nodes_disconnect_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
else if (strcmp(name, "connection_check_type") == 0)
|
||||||
|
{
|
||||||
|
if (strcasecmp(value, "ping") == 0)
|
||||||
|
{
|
||||||
|
options->connection_check_type = CHECK_PING;
|
||||||
|
}
|
||||||
|
else if (strcasecmp(value, "connection") == 0)
|
||||||
|
{
|
||||||
|
options->connection_check_type = CHECK_CONNECTION;
|
||||||
|
}
|
||||||
|
else if (strcasecmp(value, "query") == 0)
|
||||||
|
{
|
||||||
|
options->connection_check_type = CHECK_QUERY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item_list_append(error_list,
|
||||||
|
_("value for \"connection_check_type\" must be \"ping\", \"connection\" or \"query\"\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "primary_visibility_consensus") == 0)
|
||||||
|
options->primary_visibility_consensus = parse_bool(value, name, error_list);
|
||||||
|
else if (strcmp(name, "failover_validation_command") == 0)
|
||||||
|
strncpy(options->failover_validation_command, value, sizeof(options->failover_validation_command));
|
||||||
|
else if (strcmp(name, "election_rerun_interval") == 0)
|
||||||
|
options->election_rerun_interval = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
else if (strcmp(name, "child_nodes_check_interval") == 0)
|
||||||
|
options->child_nodes_check_interval = repmgr_atoi(value, name, error_list, 1);
|
||||||
|
else if (strcmp(name, "child_nodes_disconnect_command") == 0)
|
||||||
|
snprintf(options->child_nodes_disconnect_command, sizeof(options->child_nodes_disconnect_command), "%s", value);
|
||||||
|
else if (strcmp(name, "child_nodes_disconnect_min_count") == 0)
|
||||||
|
options->child_nodes_disconnect_min_count = repmgr_atoi(value, name, error_list, -1);
|
||||||
|
else if (strcmp(name, "child_nodes_connected_min_count") == 0)
|
||||||
|
options->child_nodes_connected_min_count = repmgr_atoi(value, name, error_list, -1);
|
||||||
|
else if (strcmp(name, "child_nodes_connected_include_witness") == 0)
|
||||||
|
options->child_nodes_connected_include_witness = parse_bool(value, name, error_list);
|
||||||
|
else if (strcmp(name, "child_nodes_disconnect_timeout") == 0)
|
||||||
|
options->child_nodes_disconnect_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
|
||||||
|
/* witness settings */
|
||||||
|
else if (strcmp(name, "witness_sync_interval") == 0)
|
||||||
|
options->witness_sync_interval = repmgr_atoi(value, name, error_list, 1);
|
||||||
|
|
||||||
|
/* BDR settings */
|
||||||
|
else if (strcmp(name, "bdr_local_monitoring_only") == 0)
|
||||||
|
options->bdr_local_monitoring_only = parse_bool(value, name, error_list);
|
||||||
|
else if (strcmp(name, "bdr_recovery_timeout") == 0)
|
||||||
|
options->bdr_recovery_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
|
||||||
|
/* service settings */
|
||||||
|
else if (strcmp(name, "pg_ctl_options") == 0)
|
||||||
|
strncpy(options->pg_ctl_options, value, sizeof(options->pg_ctl_options));
|
||||||
|
else if (strcmp(name, "service_start_command") == 0)
|
||||||
|
strncpy(options->service_start_command, value, sizeof(options->service_start_command));
|
||||||
|
else if (strcmp(name, "service_stop_command") == 0)
|
||||||
|
strncpy(options->service_stop_command, value, sizeof(options->service_stop_command));
|
||||||
|
else if (strcmp(name, "service_restart_command") == 0)
|
||||||
|
strncpy(options->service_restart_command, value, sizeof(options->service_restart_command));
|
||||||
|
else if (strcmp(name, "service_reload_command") == 0)
|
||||||
|
strncpy(options->service_reload_command, value, sizeof(options->service_reload_command));
|
||||||
|
else if (strcmp(name, "service_promote_command") == 0)
|
||||||
|
strncpy(options->service_promote_command, value, sizeof(options->service_promote_command));
|
||||||
|
|
||||||
|
/* repmgrd service settings */
|
||||||
|
else if (strcmp(name, "repmgrd_service_start_command") == 0)
|
||||||
|
strncpy(options->repmgrd_service_start_command, value, sizeof(options->repmgrd_service_start_command));
|
||||||
|
else if (strcmp(name, "repmgrd_service_stop_command") == 0)
|
||||||
|
strncpy(options->repmgrd_service_stop_command, value, sizeof(options->repmgrd_service_stop_command));
|
||||||
|
|
||||||
|
|
||||||
|
/* event notification settings */
|
||||||
|
else if (strcmp(name, "event_notification_command") == 0)
|
||||||
|
strncpy(options->event_notification_command, value, sizeof(options->event_notification_command));
|
||||||
|
else if (strcmp(name, "event_notifications") == 0)
|
||||||
|
{
|
||||||
|
/* store unparsed value for comparison when reloading config */
|
||||||
|
strncpy(options->event_notifications_orig, value, sizeof(options->event_notifications_orig));
|
||||||
|
parse_event_notifications_list(options, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* barman settings */
|
||||||
|
else if (strcmp(name, "barman_host") == 0)
|
||||||
|
strncpy(options->barman_host, value, sizeof(options->barman_host));
|
||||||
|
else if (strcmp(name, "barman_server") == 0)
|
||||||
|
strncpy(options->barman_server, value, sizeof(options->barman_server));
|
||||||
|
else if (strcmp(name, "barman_config") == 0)
|
||||||
|
strncpy(options->barman_config, value, sizeof(options->barman_config));
|
||||||
|
|
||||||
|
/* rsync/ssh settings */
|
||||||
|
else if (strcmp(name, "rsync_options") == 0)
|
||||||
|
strncpy(options->rsync_options, value, sizeof(options->rsync_options));
|
||||||
|
else if (strcmp(name, "ssh_options") == 0)
|
||||||
|
strncpy(options->ssh_options, value, sizeof(options->ssh_options));
|
||||||
|
|
||||||
|
/* undocumented settings for testing */
|
||||||
|
else if (strcmp(name, "promote_delay") == 0)
|
||||||
|
options->promote_delay = repmgr_atoi(value, name, error_list, 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Following parameters have been deprecated or renamed from 3.x -
|
||||||
|
* issue a warning
|
||||||
|
*/
|
||||||
|
else if (strcmp(name, "cluster") == 0)
|
||||||
|
{
|
||||||
|
item_list_append(warning_list,
|
||||||
|
_("parameter \"cluster\" is deprecated and will be ignored"));
|
||||||
|
known_parameter = false;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "node") == 0)
|
||||||
|
{
|
||||||
|
item_list_append(warning_list,
|
||||||
|
_("parameter \"node\" has been renamed to \"node_id\""));
|
||||||
|
known_parameter = false;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "upstream_node") == 0)
|
||||||
|
{
|
||||||
|
item_list_append(warning_list,
|
||||||
|
_("parameter \"upstream_node\" has been removed; use \"--upstream-node-id\" when cloning a standby"));
|
||||||
|
known_parameter = false;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "loglevel") == 0)
|
||||||
|
{
|
||||||
|
item_list_append(warning_list,
|
||||||
|
_("parameter \"loglevel\" has been renamed to \"log_level\""));
|
||||||
|
known_parameter = false;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "logfacility") == 0)
|
||||||
|
{
|
||||||
|
item_list_append(warning_list,
|
||||||
|
_("parameter \"logfacility\" has been renamed to \"log_facility\""));
|
||||||
|
known_parameter = false;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "logfile") == 0)
|
||||||
|
{
|
||||||
|
item_list_append(warning_list,
|
||||||
|
_("parameter \"logfile\" has been renamed to \"log_file\""));
|
||||||
|
known_parameter = false;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "master_reponse_timeout") == 0)
|
||||||
|
{
|
||||||
|
item_list_append(warning_list,
|
||||||
|
_("parameter \"master_reponse_timeout\" has been removed; use \"async_query_timeout\" instead"));
|
||||||
|
known_parameter = false;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "retry_promote_interval_secs") == 0)
|
||||||
|
{
|
||||||
|
item_list_append(warning_list,
|
||||||
|
_("parameter \"retry_promote_interval_secs\" has been removed; use \"primary_notification_timeout\" instead"));
|
||||||
|
known_parameter = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
known_parameter = false;
|
||||||
|
log_warning(_("%s/%s: unknown name/value pair provided; ignoring"), name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Raise an error if a known parameter is provided with an empty
|
||||||
|
* value. Currently there's no reason why empty parameters are needed;
|
||||||
|
* if we want to accept those, we'd need to add stricter default
|
||||||
|
* checking, as currently e.g. an empty `node_id` value will be converted
|
||||||
|
* to '0'.
|
||||||
|
*/
|
||||||
|
if (known_parameter == true && !strlen(value))
|
||||||
|
{
|
||||||
|
char error_message_buf[MAXLEN] = "";
|
||||||
|
|
||||||
|
maxlen_snprintf(error_message_buf,
|
||||||
|
_("\"%s\": no value provided"),
|
||||||
|
name);
|
||||||
|
|
||||||
|
item_list_append(error_list, error_message_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
/* check required parameters */
|
/* check required parameters */
|
||||||
if (options->node_id == UNKNOWN_NODE_ID)
|
if (node_id_found == false)
|
||||||
{
|
{
|
||||||
item_list_append(error_list, _("\"node_id\": required parameter was not found"));
|
item_list_append(error_list, _("\"node_id\": required parameter was not found"));
|
||||||
}
|
}
|
||||||
@@ -560,349 +919,6 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
parse_configuration_item(t_configuration_options *options, ItemList *error_list, ItemList *warning_list, const char *name, const char *value)
|
|
||||||
{
|
|
||||||
bool known_parameter = true;
|
|
||||||
|
|
||||||
if (strcmp(name, "node_id") == 0)
|
|
||||||
{
|
|
||||||
options->node_id = repmgr_atoi(value, name, error_list, MIN_NODE_ID);
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "node_name") == 0)
|
|
||||||
{
|
|
||||||
if (strlen(value) < sizeof(options->node_name))
|
|
||||||
strncpy(options->node_name, value, sizeof(options->node_name));
|
|
||||||
else
|
|
||||||
item_list_append_format(error_list,
|
|
||||||
_("value for \"node_name\" must contain fewer than %lu characters"),
|
|
||||||
sizeof(options->node_name));
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "conninfo") == 0)
|
|
||||||
{
|
|
||||||
strncpy(options->conninfo, value, MAXLEN);
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "data_directory") == 0)
|
|
||||||
{
|
|
||||||
strncpy(options->data_directory, value, MAXPGPATH);
|
|
||||||
canonicalize_path(options->data_directory);
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "config_directory") == 0)
|
|
||||||
{
|
|
||||||
strncpy(options->config_directory, value, MAXPGPATH);
|
|
||||||
canonicalize_path(options->config_directory);
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "replication_user") == 0)
|
|
||||||
{
|
|
||||||
if (strlen(value) < sizeof(options->replication_user))
|
|
||||||
strncpy(options->replication_user, value, sizeof(options->replication_user));
|
|
||||||
else
|
|
||||||
item_list_append_format(error_list,
|
|
||||||
_("value for \"replication_user\" must contain fewer than %lu characters"),
|
|
||||||
sizeof(options->replication_user));
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "pg_bindir") == 0)
|
|
||||||
strncpy(options->pg_bindir, value, MAXPGPATH);
|
|
||||||
else if (strcmp(name, "repmgr_bindir") == 0)
|
|
||||||
strncpy(options->repmgr_bindir, value, MAXPGPATH);
|
|
||||||
|
|
||||||
else if (strcmp(name, "replication_type") == 0)
|
|
||||||
{
|
|
||||||
if (strcmp(value, "physical") == 0)
|
|
||||||
options->replication_type = REPLICATION_TYPE_PHYSICAL;
|
|
||||||
else if (strcmp(value, "bdr") == 0)
|
|
||||||
options->replication_type = REPLICATION_TYPE_BDR;
|
|
||||||
else
|
|
||||||
item_list_append(error_list, _("value for \"replication_type\" must be \"physical\" or \"bdr\""));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* log settings */
|
|
||||||
else if (strcmp(name, "log_file") == 0)
|
|
||||||
strncpy(options->log_file, value, MAXLEN);
|
|
||||||
else if (strcmp(name, "log_level") == 0)
|
|
||||||
strncpy(options->log_level, value, MAXLEN);
|
|
||||||
else if (strcmp(name, "log_facility") == 0)
|
|
||||||
strncpy(options->log_facility, value, MAXLEN);
|
|
||||||
else if (strcmp(name, "log_status_interval") == 0)
|
|
||||||
options->log_status_interval = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
|
|
||||||
/* standby clone settings */
|
|
||||||
else if (strcmp(name, "use_replication_slots") == 0)
|
|
||||||
options->use_replication_slots = parse_bool(value, name, error_list);
|
|
||||||
else if (strcmp(name, "pg_basebackup_options") == 0)
|
|
||||||
strncpy(options->pg_basebackup_options, value, MAXLEN);
|
|
||||||
else if (strcmp(name, "tablespace_mapping") == 0)
|
|
||||||
tablespace_list_append(options, value);
|
|
||||||
else if (strcmp(name, "restore_command") == 0)
|
|
||||||
strncpy(options->restore_command, value, MAXLEN);
|
|
||||||
else if (strcmp(name, "recovery_min_apply_delay") == 0)
|
|
||||||
{
|
|
||||||
parse_time_unit_parameter(name, value, options->recovery_min_apply_delay, error_list);
|
|
||||||
options->recovery_min_apply_delay_provided = true;
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "archive_cleanup_command") == 0)
|
|
||||||
strncpy(options->archive_cleanup_command, value, MAXLEN);
|
|
||||||
else if (strcmp(name, "use_primary_conninfo_password") == 0)
|
|
||||||
options->use_primary_conninfo_password = parse_bool(value, name, error_list);
|
|
||||||
else if (strcmp(name, "passfile") == 0)
|
|
||||||
strncpy(options->passfile, value, sizeof(options->passfile));
|
|
||||||
|
|
||||||
/* standby promote settings */
|
|
||||||
else if (strcmp(name, "promote_check_timeout") == 0)
|
|
||||||
options->promote_check_timeout = repmgr_atoi(value, name, error_list, 1);
|
|
||||||
|
|
||||||
else if (strcmp(name, "promote_check_interval") == 0)
|
|
||||||
options->promote_check_interval = repmgr_atoi(value, name, error_list, 1);
|
|
||||||
|
|
||||||
/* standby follow settings */
|
|
||||||
else if (strcmp(name, "primary_follow_timeout") == 0)
|
|
||||||
options->primary_follow_timeout = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
else if (strcmp(name, "standby_follow_timeout") == 0)
|
|
||||||
options->standby_follow_timeout = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
|
|
||||||
/* standby switchover settings */
|
|
||||||
else if (strcmp(name, "shutdown_check_timeout") == 0)
|
|
||||||
options->shutdown_check_timeout = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
else if (strcmp(name, "standby_reconnect_timeout") == 0)
|
|
||||||
options->standby_reconnect_timeout = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
else if (strcmp(name, "wal_receive_check_timeout") == 0)
|
|
||||||
options->wal_receive_check_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 */
|
|
||||||
else if (strcmp(name, "archive_ready_warning") == 0)
|
|
||||||
options->archive_ready_warning = repmgr_atoi(value, name, error_list, 1);
|
|
||||||
else if (strcmp(name, "archive_ready_critical") == 0)
|
|
||||||
options->archive_ready_critical = repmgr_atoi(value, name, error_list, 1);
|
|
||||||
else if (strcmp(name, "replication_lag_warning") == 0)
|
|
||||||
options->replication_lag_warning = repmgr_atoi(value, name, error_list, 1);
|
|
||||||
else if (strcmp(name, "replication_lag_critical") == 0)
|
|
||||||
options->replication_lag_critical = repmgr_atoi(value, name, error_list, 1);
|
|
||||||
|
|
||||||
/* repmgrd settings */
|
|
||||||
else if (strcmp(name, "failover") == 0)
|
|
||||||
{
|
|
||||||
if (strcmp(value, "manual") == 0)
|
|
||||||
{
|
|
||||||
options->failover = FAILOVER_MANUAL;
|
|
||||||
}
|
|
||||||
else if (strcmp(value, "automatic") == 0)
|
|
||||||
{
|
|
||||||
options->failover = FAILOVER_AUTOMATIC;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item_list_append(error_list,
|
|
||||||
_("value for \"failover\" must be \"automatic\" or \"manual\"\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "priority") == 0)
|
|
||||||
options->priority = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
else if (strcmp(name, "location") == 0)
|
|
||||||
strncpy(options->location, value, sizeof(options->location));
|
|
||||||
else if (strcmp(name, "promote_command") == 0)
|
|
||||||
strncpy(options->promote_command, value, sizeof(options->promote_command));
|
|
||||||
else if (strcmp(name, "follow_command") == 0)
|
|
||||||
strncpy(options->follow_command, value, sizeof(options->follow_command));
|
|
||||||
else if (strcmp(name, "reconnect_attempts") == 0)
|
|
||||||
options->reconnect_attempts = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
else if (strcmp(name, "reconnect_interval") == 0)
|
|
||||||
options->reconnect_interval = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
else if (strcmp(name, "monitor_interval_secs") == 0)
|
|
||||||
options->monitor_interval_secs = repmgr_atoi(value, name, error_list, 1);
|
|
||||||
else if (strcmp(name, "monitoring_history") == 0)
|
|
||||||
options->monitoring_history = parse_bool(value, name, error_list);
|
|
||||||
else if (strcmp(name, "degraded_monitoring_timeout") == 0)
|
|
||||||
options->degraded_monitoring_timeout = repmgr_atoi(value, name, error_list, -1);
|
|
||||||
else if (strcmp(name, "async_query_timeout") == 0)
|
|
||||||
options->async_query_timeout = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
else if (strcmp(name, "primary_notification_timeout") == 0)
|
|
||||||
options->primary_notification_timeout = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
else if (strcmp(name, "repmgrd_standby_startup_timeout") == 0)
|
|
||||||
options->repmgrd_standby_startup_timeout = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
else if (strcmp(name, "repmgrd_pid_file") == 0)
|
|
||||||
strncpy(options->repmgrd_pid_file, value, MAXPGPATH);
|
|
||||||
else if (strcmp(name, "standby_disconnect_on_failover") == 0)
|
|
||||||
options->standby_disconnect_on_failover = parse_bool(value, name, error_list);
|
|
||||||
else if (strcmp(name, "sibling_nodes_disconnect_timeout") == 0)
|
|
||||||
options->sibling_nodes_disconnect_timeout = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
else if (strcmp(name, "connection_check_type") == 0)
|
|
||||||
{
|
|
||||||
if (strcasecmp(value, "ping") == 0)
|
|
||||||
{
|
|
||||||
options->connection_check_type = CHECK_PING;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(value, "connection") == 0)
|
|
||||||
{
|
|
||||||
options->connection_check_type = CHECK_CONNECTION;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(value, "query") == 0)
|
|
||||||
{
|
|
||||||
options->connection_check_type = CHECK_QUERY;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item_list_append(error_list,
|
|
||||||
_("value for \"connection_check_type\" must be \"ping\", \"connection\" or \"query\"\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "primary_visibility_consensus") == 0)
|
|
||||||
options->primary_visibility_consensus = parse_bool(value, name, error_list);
|
|
||||||
else if (strcmp(name, "failover_validation_command") == 0)
|
|
||||||
strncpy(options->failover_validation_command, value, sizeof(options->failover_validation_command));
|
|
||||||
else if (strcmp(name, "election_rerun_interval") == 0)
|
|
||||||
options->election_rerun_interval = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
else if (strcmp(name, "child_nodes_check_interval") == 0)
|
|
||||||
options->child_nodes_check_interval = repmgr_atoi(value, name, error_list, 1);
|
|
||||||
else if (strcmp(name, "child_nodes_disconnect_command") == 0)
|
|
||||||
snprintf(options->child_nodes_disconnect_command, sizeof(options->child_nodes_disconnect_command), "%s", value);
|
|
||||||
else if (strcmp(name, "child_nodes_disconnect_min_count") == 0)
|
|
||||||
options->child_nodes_disconnect_min_count = repmgr_atoi(value, name, error_list, -1);
|
|
||||||
else if (strcmp(name, "child_nodes_connected_min_count") == 0)
|
|
||||||
options->child_nodes_connected_min_count = repmgr_atoi(value, name, error_list, -1);
|
|
||||||
else if (strcmp(name, "child_nodes_connected_include_witness") == 0)
|
|
||||||
options->child_nodes_connected_include_witness = parse_bool(value, name, error_list);
|
|
||||||
else if (strcmp(name, "child_nodes_disconnect_timeout") == 0)
|
|
||||||
options->child_nodes_disconnect_timeout = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
|
|
||||||
/* witness settings */
|
|
||||||
else if (strcmp(name, "witness_sync_interval") == 0)
|
|
||||||
options->witness_sync_interval = repmgr_atoi(value, name, error_list, 1);
|
|
||||||
|
|
||||||
/* BDR settings */
|
|
||||||
else if (strcmp(name, "bdr_local_monitoring_only") == 0)
|
|
||||||
options->bdr_local_monitoring_only = parse_bool(value, name, error_list);
|
|
||||||
else if (strcmp(name, "bdr_recovery_timeout") == 0)
|
|
||||||
options->bdr_recovery_timeout = repmgr_atoi(value, name, error_list, 0);
|
|
||||||
|
|
||||||
/* service settings */
|
|
||||||
else if (strcmp(name, "pg_ctl_options") == 0)
|
|
||||||
strncpy(options->pg_ctl_options, value, sizeof(options->pg_ctl_options));
|
|
||||||
else if (strcmp(name, "service_start_command") == 0)
|
|
||||||
strncpy(options->service_start_command, value, sizeof(options->service_start_command));
|
|
||||||
else if (strcmp(name, "service_stop_command") == 0)
|
|
||||||
strncpy(options->service_stop_command, value, sizeof(options->service_stop_command));
|
|
||||||
else if (strcmp(name, "service_restart_command") == 0)
|
|
||||||
strncpy(options->service_restart_command, value, sizeof(options->service_restart_command));
|
|
||||||
else if (strcmp(name, "service_reload_command") == 0)
|
|
||||||
strncpy(options->service_reload_command, value, sizeof(options->service_reload_command));
|
|
||||||
else if (strcmp(name, "service_promote_command") == 0)
|
|
||||||
strncpy(options->service_promote_command, value, sizeof(options->service_promote_command));
|
|
||||||
|
|
||||||
/* repmgrd service settings */
|
|
||||||
else if (strcmp(name, "repmgrd_service_start_command") == 0)
|
|
||||||
strncpy(options->repmgrd_service_start_command, value, sizeof(options->repmgrd_service_start_command));
|
|
||||||
else if (strcmp(name, "repmgrd_service_stop_command") == 0)
|
|
||||||
strncpy(options->repmgrd_service_stop_command, value, sizeof(options->repmgrd_service_stop_command));
|
|
||||||
|
|
||||||
|
|
||||||
/* event notification settings */
|
|
||||||
else if (strcmp(name, "event_notification_command") == 0)
|
|
||||||
strncpy(options->event_notification_command, value, sizeof(options->event_notification_command));
|
|
||||||
else if (strcmp(name, "event_notifications") == 0)
|
|
||||||
{
|
|
||||||
/* store unparsed value for comparison when reloading config */
|
|
||||||
strncpy(options->event_notifications_orig, value, sizeof(options->event_notifications_orig));
|
|
||||||
parse_event_notifications_list(options, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* barman settings */
|
|
||||||
else if (strcmp(name, "barman_host") == 0)
|
|
||||||
strncpy(options->barman_host, value, sizeof(options->barman_host));
|
|
||||||
else if (strcmp(name, "barman_server") == 0)
|
|
||||||
strncpy(options->barman_server, value, sizeof(options->barman_server));
|
|
||||||
else if (strcmp(name, "barman_config") == 0)
|
|
||||||
strncpy(options->barman_config, value, sizeof(options->barman_config));
|
|
||||||
|
|
||||||
/* rsync/ssh settings */
|
|
||||||
else if (strcmp(name, "rsync_options") == 0)
|
|
||||||
strncpy(options->rsync_options, value, sizeof(options->rsync_options));
|
|
||||||
else if (strcmp(name, "ssh_options") == 0)
|
|
||||||
strncpy(options->ssh_options, value, sizeof(options->ssh_options));
|
|
||||||
|
|
||||||
/* undocumented settings for testing */
|
|
||||||
else if (strcmp(name, "promote_delay") == 0)
|
|
||||||
options->promote_delay = repmgr_atoi(value, name, error_list, 1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Following parameters have been deprecated or renamed from 3.x -
|
|
||||||
* issue a warning
|
|
||||||
*/
|
|
||||||
else if (strcmp(name, "cluster") == 0)
|
|
||||||
{
|
|
||||||
item_list_append(warning_list,
|
|
||||||
_("parameter \"cluster\" is deprecated and will be ignored"));
|
|
||||||
known_parameter = false;
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "node") == 0)
|
|
||||||
{
|
|
||||||
item_list_append(warning_list,
|
|
||||||
_("parameter \"node\" has been renamed to \"node_id\""));
|
|
||||||
known_parameter = false;
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "upstream_node") == 0)
|
|
||||||
{
|
|
||||||
item_list_append(warning_list,
|
|
||||||
_("parameter \"upstream_node\" has been removed; use \"--upstream-node-id\" when cloning a standby"));
|
|
||||||
known_parameter = false;
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "loglevel") == 0)
|
|
||||||
{
|
|
||||||
item_list_append(warning_list,
|
|
||||||
_("parameter \"loglevel\" has been renamed to \"log_level\""));
|
|
||||||
known_parameter = false;
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "logfacility") == 0)
|
|
||||||
{
|
|
||||||
item_list_append(warning_list,
|
|
||||||
_("parameter \"logfacility\" has been renamed to \"log_facility\""));
|
|
||||||
known_parameter = false;
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "logfile") == 0)
|
|
||||||
{
|
|
||||||
item_list_append(warning_list,
|
|
||||||
_("parameter \"logfile\" has been renamed to \"log_file\""));
|
|
||||||
known_parameter = false;
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "master_reponse_timeout") == 0)
|
|
||||||
{
|
|
||||||
item_list_append(warning_list,
|
|
||||||
_("parameter \"master_reponse_timeout\" has been removed; use \"async_query_timeout\" instead"));
|
|
||||||
known_parameter = false;
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "retry_promote_interval_secs") == 0)
|
|
||||||
{
|
|
||||||
item_list_append(warning_list,
|
|
||||||
_("parameter \"retry_promote_interval_secs\" has been removed; use \"primary_notification_timeout\" instead"));
|
|
||||||
known_parameter = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
known_parameter = false;
|
|
||||||
log_warning(_("%s/%s: unknown name/value pair provided; ignoring"), name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Raise an error if a known parameter is provided with an empty
|
|
||||||
* value. Currently there's no reason why empty parameters are needed;
|
|
||||||
* if we want to accept those, we'd need to add stricter default
|
|
||||||
* checking, as currently e.g. an empty `node_id` value will be converted
|
|
||||||
* to '0'.
|
|
||||||
*/
|
|
||||||
if (known_parameter == true && !strlen(value))
|
|
||||||
{
|
|
||||||
char error_message_buf[MAXLEN] = "";
|
|
||||||
|
|
||||||
maxlen_snprintf(error_message_buf,
|
|
||||||
_("\"%s\": no value provided"),
|
|
||||||
name);
|
|
||||||
|
|
||||||
item_list_append(error_list, error_message_buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -317,8 +317,6 @@ const char *progname(void);
|
|||||||
void load_config(const char *config_file, bool verbose, bool terse, t_configuration_options *options, char *argv0);
|
void load_config(const char *config_file, bool verbose, bool terse, t_configuration_options *options, char *argv0);
|
||||||
bool reload_config(t_configuration_options *orig_options, t_server_type server_type);
|
bool reload_config(t_configuration_options *orig_options, t_server_type server_type);
|
||||||
|
|
||||||
void parse_configuration_item(t_configuration_options *options, ItemList *error_list, ItemList *warning_list, const char *name, const char *value);
|
|
||||||
|
|
||||||
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,
|
bool parse_bool(const char *s,
|
||||||
@@ -344,7 +342,4 @@ void exit_with_cli_errors(ItemList *error_list, const char *repmgr_command);
|
|||||||
void print_item_list(ItemList *item_list);
|
void print_item_list(ItemList *item_list);
|
||||||
const char *print_connection_check_type(ConnectionCheckType type);
|
const char *print_connection_check_type(ConnectionCheckType type);
|
||||||
|
|
||||||
|
|
||||||
extern bool ProcessConfigFile(FILE *fp, const char *config_file, t_configuration_options *options, ItemList *error_list, ItemList *warning_list);
|
|
||||||
|
|
||||||
#endif /* _REPMGR_CONFIGFILE_H_ */
|
#endif /* _REPMGR_CONFIGFILE_H_ */
|
||||||
|
|||||||
@@ -24,33 +24,6 @@
|
|||||||
<sect2>
|
<sect2>
|
||||||
<title>General enhancements</title>
|
<title>General enhancements</title>
|
||||||
<para>
|
<para>
|
||||||
<itemizedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The &repmgr; configuration file is now parsed using
|
|
||||||
<command>flex</command>, meaning it will be parsed in
|
|
||||||
the same way as PostgreSQL parses its own configuration
|
|
||||||
files.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This makes configuration file parsing more robust
|
|
||||||
and consistent.
|
|
||||||
</para>
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
This change makes configuration file parsing somewhat stricter
|
|
||||||
than previously. When upgrading, be sure to check your
|
|
||||||
configuration file syntax.
|
|
||||||
<!-- XXX add notes in upgrade section -->
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In particular, all string values containing spaces
|
|
||||||
<emphasis>must</emphasis> be contained within single quotes.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|||||||
Reference in New Issue
Block a user