Skip to content

Commit b00a16b

Browse files
committed
Make invalid primary_slot_name follow standard GUC error reporting.
Previously, if primary_slot_name was set to an invalid slot name and the configuration file was reloaded, both the postmaster and all other backend processes reported a WARNING. With many processes running, this could produce a flood of duplicate messages. The problem was that the GUC check hook for primary_slot_name reported errors at WARNING level via ereport(). This commit changes the check hook to use GUC_check_errdetail() and GUC_check_errhint() for error reporting. As with other GUC parameters, this causes non-postmaster processes to log the message at DEBUG3, so by default, only the postmaster's message appears in the log file. Backpatch to all supported versions. Author: Fujii Masao <masao.fujii@gmail.com> Reviewed-by: Chao Li <lic@highgo.com> Reviewed-by: Amit Kapila <amit.kapila16@gmail.com> Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de> Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com> Discussion: https://postgr.es/m/CAHGQGwFud-cvthCTfusBfKHBS6Jj6kdAPTdLWKvP2qjUX6L_wA@mail.gmail.com Backpatch-through: 13
1 parent 7d7ebdb commit b00a16b

File tree

3 files changed

+58
-16
lines changed

3 files changed

+58
-16
lines changed

src/backend/replication/slot.c

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -166,31 +166,62 @@ ReplicationSlotsShmemInit(void)
166166
/*
167167
* Check whether the passed slot name is valid and report errors at elevel.
168168
*
169+
* See comments for ReplicationSlotValidateNameInternal().
170+
*/
171+
bool
172+
ReplicationSlotValidateName(const char *name, int elevel)
173+
{
174+
int err_code;
175+
char *err_msg = NULL;
176+
char *err_hint = NULL;
177+
178+
if (!ReplicationSlotValidateNameInternal(name, &err_code, &err_msg,
179+
&err_hint))
180+
{
181+
ereport(elevel,
182+
errcode(err_code),
183+
errmsg_internal("%s", err_msg),
184+
(err_hint != NULL) ? errhint("%s", err_hint) : 0);
185+
186+
pfree(err_msg);
187+
if (err_hint != NULL)
188+
pfree(err_hint);
189+
return false;
190+
}
191+
192+
return true;
193+
}
194+
195+
/*
196+
* Check whether the passed slot name is valid.
197+
*
169198
* Slot names may consist out of [a-z0-9_]{1,NAMEDATALEN-1} which should allow
170199
* the name to be used as a directory name on every supported OS.
171200
*
172-
* Returns whether the directory name is valid or not if elevel < ERROR.
201+
* Returns true if the slot name is valid. Otherwise, returns false and stores
202+
* the error code, error message, and optional hint in err_code, err_msg, and
203+
* err_hint, respectively. The caller is responsible for freeing err_msg and
204+
* err_hint, which are palloc'd.
173205
*/
174206
bool
175-
ReplicationSlotValidateName(const char *name, int elevel)
207+
ReplicationSlotValidateNameInternal(const char *name, int *err_code,
208+
char **err_msg, char **err_hint)
176209
{
177210
const char *cp;
178211

179212
if (strlen(name) == 0)
180213
{
181-
ereport(elevel,
182-
(errcode(ERRCODE_INVALID_NAME),
183-
errmsg("replication slot name \"%s\" is too short",
184-
name)));
214+
*err_code = ERRCODE_INVALID_NAME;
215+
*err_msg = psprintf(_("replication slot name \"%s\" is too short"), name);
216+
*err_hint = NULL;
185217
return false;
186218
}
187219

188220
if (strlen(name) >= NAMEDATALEN)
189221
{
190-
ereport(elevel,
191-
(errcode(ERRCODE_NAME_TOO_LONG),
192-
errmsg("replication slot name \"%s\" is too long",
193-
name)));
222+
*err_code = ERRCODE_NAME_TOO_LONG;
223+
*err_msg = psprintf(_("replication slot name \"%s\" is too long"), name);
224+
*err_hint = NULL;
194225
return false;
195226
}
196227

@@ -200,11 +231,9 @@ ReplicationSlotValidateName(const char *name, int elevel)
200231
|| (*cp >= '0' && *cp <= '9')
201232
|| (*cp == '_')))
202233
{
203-
ereport(elevel,
204-
(errcode(ERRCODE_INVALID_NAME),
205-
errmsg("replication slot name \"%s\" contains invalid character",
206-
name),
207-
errhint("Replication slot names may only contain lower case letters, numbers, and the underscore character.")));
234+
*err_code = ERRCODE_INVALID_NAME;
235+
*err_msg = psprintf(_("replication slot name \"%s\" contains invalid character"), name);
236+
*err_hint = psprintf(_("Replication slot names may only contain lower case letters, numbers, and the underscore character."));
208237
return false;
209238
}
210239
}

src/backend/utils/misc/guc.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12128,9 +12128,20 @@ assign_recovery_target_lsn(const char *newval, void *extra)
1212812128
static bool
1212912129
check_primary_slot_name(char **newval, void **extra, GucSource source)
1213012130
{
12131+
int err_code;
12132+
char *err_msg = NULL;
12133+
char *err_hint = NULL;
12134+
1213112135
if (*newval && strcmp(*newval, "") != 0 &&
12132-
!ReplicationSlotValidateName(*newval, WARNING))
12136+
!ReplicationSlotValidateNameInternal(*newval, &err_code, &err_msg,
12137+
&err_hint))
12138+
{
12139+
GUC_check_errcode(err_code);
12140+
GUC_check_errdetail("%s", err_msg);
12141+
if (err_hint != NULL)
12142+
GUC_check_errhint("%s", err_hint);
1213312143
return false;
12144+
}
1213412145

1213512146
return true;
1213612147
}

src/include/replication/slot.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ extern void ReplicationSlotMarkDirty(void);
203203

204204
/* misc stuff */
205205
extern bool ReplicationSlotValidateName(const char *name, int elevel);
206+
extern bool ReplicationSlotValidateNameInternal(const char *name,
207+
int *err_code, char **err_msg, char **err_hint);
206208
extern void ReplicationSlotReserveWal(void);
207209
extern void ReplicationSlotsComputeRequiredXmin(bool already_locked);
208210
extern void ReplicationSlotsComputeRequiredLSN(void);

0 commit comments

Comments
 (0)