mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Split up guc.c for better build speed and ease of maintenance.
guc.c has grown to be one of our largest .c files, making it a bottleneck for compilation. It's also acquired a bunch of knowledge that'd be better kept elsewhere, because of our not very good habit of putting variable-specific check hooks here. Hence, split it up along these lines: * guc.c itself retains just the core GUC housekeeping mechanisms. * New file guc_funcs.c contains the SET/SHOW interfaces and some SQL-accessible functions for GUC manipulation. * New file guc_tables.c contains the data arrays that define the built-in GUC variables, along with some already-exported constant tables. * GUC check/assign/show hook functions are moved to the variable's home module, whenever that's clearly identifiable. A few hard- to-classify hooks ended up in commands/variable.c, which was already a home for miscellaneous GUC hook functions. To avoid cluttering a lot more header files with #include "guc.h", I also invented a new header file utils/guc_hooks.h and put all the GUC hook functions' declarations there, regardless of their originating module. That allowed removal of #include "guc.h" from some existing headers. The fallout from that (hopefully all caught here) demonstrates clearly why such inclusions are best minimized: there are a lot of files that, for example, were getting array.h at two or more levels of remove, despite not having any connection at all to GUCs in themselves. There is some very minor code beautification here, such as renaming a couple of inconsistently-named hook functions and improving some comments. But mostly this just moves code from point A to point B and deals with the ensuing needs for #include adjustments and exporting a few functions that previously weren't exported. Patch by me, per a suggestion from Andres Freund; thanks also to Michael Paquier for the idea to invent guc_funcs.c. Discussion: https://postgr.es/m/587607.1662836699@sss.pgh.pa.us
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
#include "utils/acl.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/datum.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/index_selfuncs.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/rel.h"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "commands/defrem.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
|
||||
@@ -97,7 +97,8 @@
|
||||
#include "storage/smgr.h"
|
||||
#include "storage/spin.h"
|
||||
#include "storage/sync.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/guc_tables.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/ps_status.h"
|
||||
#include "utils/relmapper.h"
|
||||
@@ -105,6 +106,7 @@
|
||||
#include "utils/snapmgr.h"
|
||||
#include "utils/timeout.h"
|
||||
#include "utils/timestamp.h"
|
||||
#include "utils/varlena.h"
|
||||
|
||||
extern uint32 bootstrap_data_checksum_version;
|
||||
|
||||
@@ -160,6 +162,12 @@ int CheckPointSegments;
|
||||
static double CheckPointDistanceEstimate = 0;
|
||||
static double PrevCheckPointDistance = 0;
|
||||
|
||||
/*
|
||||
* Track whether there were any deferred checks for custom resource managers
|
||||
* specified in wal_consistency_checking.
|
||||
*/
|
||||
static bool check_wal_consistency_checking_deferred = false;
|
||||
|
||||
/*
|
||||
* GUC support
|
||||
*/
|
||||
@@ -4304,6 +4312,172 @@ check_wal_buffers(int *newval, void **extra, GucSource source)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for wal_consistency_checking
|
||||
*/
|
||||
bool
|
||||
check_wal_consistency_checking(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
char *rawstring;
|
||||
List *elemlist;
|
||||
ListCell *l;
|
||||
bool newwalconsistency[RM_MAX_ID + 1];
|
||||
|
||||
/* Initialize the array */
|
||||
MemSet(newwalconsistency, 0, (RM_MAX_ID + 1) * sizeof(bool));
|
||||
|
||||
/* Need a modifiable copy of string */
|
||||
rawstring = pstrdup(*newval);
|
||||
|
||||
/* Parse string into list of identifiers */
|
||||
if (!SplitIdentifierString(rawstring, ',', &elemlist))
|
||||
{
|
||||
/* syntax error in list */
|
||||
GUC_check_errdetail("List syntax is invalid.");
|
||||
pfree(rawstring);
|
||||
list_free(elemlist);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach(l, elemlist)
|
||||
{
|
||||
char *tok = (char *) lfirst(l);
|
||||
int rmid;
|
||||
|
||||
/* Check for 'all'. */
|
||||
if (pg_strcasecmp(tok, "all") == 0)
|
||||
{
|
||||
for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
|
||||
if (RmgrIdExists(rmid) && GetRmgr(rmid).rm_mask != NULL)
|
||||
newwalconsistency[rmid] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if the token matches any known resource manager. */
|
||||
bool found = false;
|
||||
|
||||
for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
|
||||
{
|
||||
if (RmgrIdExists(rmid) && GetRmgr(rmid).rm_mask != NULL &&
|
||||
pg_strcasecmp(tok, GetRmgr(rmid).rm_name) == 0)
|
||||
{
|
||||
newwalconsistency[rmid] = true;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
/*
|
||||
* During startup, it might be a not-yet-loaded custom
|
||||
* resource manager. Defer checking until
|
||||
* InitializeWalConsistencyChecking().
|
||||
*/
|
||||
if (!process_shared_preload_libraries_done)
|
||||
{
|
||||
check_wal_consistency_checking_deferred = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
|
||||
pfree(rawstring);
|
||||
list_free(elemlist);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pfree(rawstring);
|
||||
list_free(elemlist);
|
||||
|
||||
/* assign new value */
|
||||
*extra = guc_malloc(ERROR, (RM_MAX_ID + 1) * sizeof(bool));
|
||||
memcpy(*extra, newwalconsistency, (RM_MAX_ID + 1) * sizeof(bool));
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for wal_consistency_checking
|
||||
*/
|
||||
void
|
||||
assign_wal_consistency_checking(const char *newval, void *extra)
|
||||
{
|
||||
/*
|
||||
* If some checks were deferred, it's possible that the checks will fail
|
||||
* later during InitializeWalConsistencyChecking(). But in that case, the
|
||||
* postmaster will exit anyway, so it's safe to proceed with the
|
||||
* assignment.
|
||||
*
|
||||
* Any built-in resource managers specified are assigned immediately,
|
||||
* which affects WAL created before shared_preload_libraries are
|
||||
* processed. Any custom resource managers specified won't be assigned
|
||||
* until after shared_preload_libraries are processed, but that's OK
|
||||
* because WAL for a custom resource manager can't be written before the
|
||||
* module is loaded anyway.
|
||||
*/
|
||||
wal_consistency_checking = extra;
|
||||
}
|
||||
|
||||
/*
|
||||
* InitializeWalConsistencyChecking: run after loading custom resource managers
|
||||
*
|
||||
* If any unknown resource managers were specified in the
|
||||
* wal_consistency_checking GUC, processing was deferred. Now that
|
||||
* shared_preload_libraries have been loaded, process wal_consistency_checking
|
||||
* again.
|
||||
*/
|
||||
void
|
||||
InitializeWalConsistencyChecking(void)
|
||||
{
|
||||
Assert(process_shared_preload_libraries_done);
|
||||
|
||||
if (check_wal_consistency_checking_deferred)
|
||||
{
|
||||
struct config_generic *guc;
|
||||
|
||||
guc = find_option("wal_consistency_checking", false, false, ERROR);
|
||||
|
||||
check_wal_consistency_checking_deferred = false;
|
||||
|
||||
set_config_option_ext("wal_consistency_checking",
|
||||
wal_consistency_checking_string,
|
||||
guc->scontext, guc->source, guc->srole,
|
||||
GUC_ACTION_SET, true, ERROR, false);
|
||||
|
||||
/* checking should not be deferred again */
|
||||
Assert(!check_wal_consistency_checking_deferred);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC show_hook for archive_command
|
||||
*/
|
||||
const char *
|
||||
show_archive_command(void)
|
||||
{
|
||||
if (XLogArchivingActive())
|
||||
return XLogArchiveCommand;
|
||||
else
|
||||
return "(disabled)";
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC show_hook for in_hot_standby
|
||||
*/
|
||||
const char *
|
||||
show_in_hot_standby(void)
|
||||
{
|
||||
/*
|
||||
* We display the actual state based on shared memory, so that this GUC
|
||||
* reports up-to-date state if examined intra-query. The underlying
|
||||
* variable (in_hot_standby_guc) changes only when we transmit a new value
|
||||
* to the client.
|
||||
*/
|
||||
return RecoveryInProgress() ? "on" : "off";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the control file, set respective GUCs.
|
||||
*
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#include "storage/bufmgr.h"
|
||||
#include "storage/shmem.h"
|
||||
#include "storage/smgr.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/hsearch.h"
|
||||
|
||||
/*
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "pgstat.h"
|
||||
#include "postmaster/bgwriter.h"
|
||||
#include "postmaster/startup.h"
|
||||
#include "replication/slot.h"
|
||||
#include "replication/walreceiver.h"
|
||||
#include "storage/fd.h"
|
||||
#include "storage/ipc.h"
|
||||
@@ -57,7 +58,9 @@
|
||||
#include "storage/procarray.h"
|
||||
#include "storage/spin.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/datetime.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/pg_lsn.h"
|
||||
#include "utils/ps_status.h"
|
||||
#include "utils/pg_rusage.h"
|
||||
|
||||
@@ -4616,3 +4619,315 @@ RecoveryRequiresIntParameter(const char *param_name, int currValue, int minValue
|
||||
errhint("You can restart the server after making the necessary configuration changes.")));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* GUC check_hook for primary_slot_name
|
||||
*/
|
||||
bool
|
||||
check_primary_slot_name(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
if (*newval && strcmp(*newval, "") != 0 &&
|
||||
!ReplicationSlotValidateName(*newval, WARNING))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Recovery target settings: Only one of the several recovery_target* settings
|
||||
* may be set. Setting a second one results in an error. The global variable
|
||||
* recoveryTarget tracks which kind of recovery target was chosen. Other
|
||||
* variables store the actual target value (for example a string or a xid).
|
||||
* The assign functions of the parameters check whether a competing parameter
|
||||
* was already set. But we want to allow setting the same parameter multiple
|
||||
* times. We also want to allow unsetting a parameter and setting a different
|
||||
* one, so we unset recoveryTarget when the parameter is set to an empty
|
||||
* string.
|
||||
*
|
||||
* XXX this code is broken by design. Throwing an error from a GUC assign
|
||||
* hook breaks fundamental assumptions of guc.c. So long as all the variables
|
||||
* for which this can happen are PGC_POSTMASTER, the consequences are limited,
|
||||
* since we'd just abort postmaster startup anyway. Nonetheless it's likely
|
||||
* that we have odd behaviors such as unexpected GUC ordering dependencies.
|
||||
*/
|
||||
|
||||
static void
|
||||
pg_attribute_noreturn()
|
||||
error_multiple_recovery_targets(void)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("multiple recovery targets specified"),
|
||||
errdetail("At most one of recovery_target, recovery_target_lsn, recovery_target_name, recovery_target_time, recovery_target_xid may be set.")));
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for recovery_target
|
||||
*/
|
||||
bool
|
||||
check_recovery_target(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
if (strcmp(*newval, "immediate") != 0 && strcmp(*newval, "") != 0)
|
||||
{
|
||||
GUC_check_errdetail("The only allowed value is \"immediate\".");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for recovery_target
|
||||
*/
|
||||
void
|
||||
assign_recovery_target(const char *newval, void *extra)
|
||||
{
|
||||
if (recoveryTarget != RECOVERY_TARGET_UNSET &&
|
||||
recoveryTarget != RECOVERY_TARGET_IMMEDIATE)
|
||||
error_multiple_recovery_targets();
|
||||
|
||||
if (newval && strcmp(newval, "") != 0)
|
||||
recoveryTarget = RECOVERY_TARGET_IMMEDIATE;
|
||||
else
|
||||
recoveryTarget = RECOVERY_TARGET_UNSET;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for recovery_target_lsn
|
||||
*/
|
||||
bool
|
||||
check_recovery_target_lsn(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
if (strcmp(*newval, "") != 0)
|
||||
{
|
||||
XLogRecPtr lsn;
|
||||
XLogRecPtr *myextra;
|
||||
bool have_error = false;
|
||||
|
||||
lsn = pg_lsn_in_internal(*newval, &have_error);
|
||||
if (have_error)
|
||||
return false;
|
||||
|
||||
myextra = (XLogRecPtr *) guc_malloc(ERROR, sizeof(XLogRecPtr));
|
||||
*myextra = lsn;
|
||||
*extra = (void *) myextra;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for recovery_target_lsn
|
||||
*/
|
||||
void
|
||||
assign_recovery_target_lsn(const char *newval, void *extra)
|
||||
{
|
||||
if (recoveryTarget != RECOVERY_TARGET_UNSET &&
|
||||
recoveryTarget != RECOVERY_TARGET_LSN)
|
||||
error_multiple_recovery_targets();
|
||||
|
||||
if (newval && strcmp(newval, "") != 0)
|
||||
{
|
||||
recoveryTarget = RECOVERY_TARGET_LSN;
|
||||
recoveryTargetLSN = *((XLogRecPtr *) extra);
|
||||
}
|
||||
else
|
||||
recoveryTarget = RECOVERY_TARGET_UNSET;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for recovery_target_name
|
||||
*/
|
||||
bool
|
||||
check_recovery_target_name(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
/* Use the value of newval directly */
|
||||
if (strlen(*newval) >= MAXFNAMELEN)
|
||||
{
|
||||
GUC_check_errdetail("%s is too long (maximum %d characters).",
|
||||
"recovery_target_name", MAXFNAMELEN - 1);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for recovery_target_name
|
||||
*/
|
||||
void
|
||||
assign_recovery_target_name(const char *newval, void *extra)
|
||||
{
|
||||
if (recoveryTarget != RECOVERY_TARGET_UNSET &&
|
||||
recoveryTarget != RECOVERY_TARGET_NAME)
|
||||
error_multiple_recovery_targets();
|
||||
|
||||
if (newval && strcmp(newval, "") != 0)
|
||||
{
|
||||
recoveryTarget = RECOVERY_TARGET_NAME;
|
||||
recoveryTargetName = newval;
|
||||
}
|
||||
else
|
||||
recoveryTarget = RECOVERY_TARGET_UNSET;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for recovery_target_time
|
||||
*
|
||||
* The interpretation of the recovery_target_time string can depend on the
|
||||
* time zone setting, so we need to wait until after all GUC processing is
|
||||
* done before we can do the final parsing of the string. This check function
|
||||
* only does a parsing pass to catch syntax errors, but we store the string
|
||||
* and parse it again when we need to use it.
|
||||
*/
|
||||
bool
|
||||
check_recovery_target_time(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
if (strcmp(*newval, "") != 0)
|
||||
{
|
||||
/* reject some special values */
|
||||
if (strcmp(*newval, "now") == 0 ||
|
||||
strcmp(*newval, "today") == 0 ||
|
||||
strcmp(*newval, "tomorrow") == 0 ||
|
||||
strcmp(*newval, "yesterday") == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* parse timestamp value (see also timestamptz_in())
|
||||
*/
|
||||
{
|
||||
char *str = *newval;
|
||||
fsec_t fsec;
|
||||
struct pg_tm tt,
|
||||
*tm = &tt;
|
||||
int tz;
|
||||
int dtype;
|
||||
int nf;
|
||||
int dterr;
|
||||
char *field[MAXDATEFIELDS];
|
||||
int ftype[MAXDATEFIELDS];
|
||||
char workbuf[MAXDATELEN + MAXDATEFIELDS];
|
||||
TimestampTz timestamp;
|
||||
|
||||
dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
|
||||
field, ftype, MAXDATEFIELDS, &nf);
|
||||
if (dterr == 0)
|
||||
dterr = DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz);
|
||||
if (dterr != 0)
|
||||
return false;
|
||||
if (dtype != DTK_DATE)
|
||||
return false;
|
||||
|
||||
if (tm2timestamp(tm, fsec, &tz, ×tamp) != 0)
|
||||
{
|
||||
GUC_check_errdetail("timestamp out of range: \"%s\"", str);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for recovery_target_time
|
||||
*/
|
||||
void
|
||||
assign_recovery_target_time(const char *newval, void *extra)
|
||||
{
|
||||
if (recoveryTarget != RECOVERY_TARGET_UNSET &&
|
||||
recoveryTarget != RECOVERY_TARGET_TIME)
|
||||
error_multiple_recovery_targets();
|
||||
|
||||
if (newval && strcmp(newval, "") != 0)
|
||||
recoveryTarget = RECOVERY_TARGET_TIME;
|
||||
else
|
||||
recoveryTarget = RECOVERY_TARGET_UNSET;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for recovery_target_timeline
|
||||
*/
|
||||
bool
|
||||
check_recovery_target_timeline(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
RecoveryTargetTimeLineGoal rttg;
|
||||
RecoveryTargetTimeLineGoal *myextra;
|
||||
|
||||
if (strcmp(*newval, "current") == 0)
|
||||
rttg = RECOVERY_TARGET_TIMELINE_CONTROLFILE;
|
||||
else if (strcmp(*newval, "latest") == 0)
|
||||
rttg = RECOVERY_TARGET_TIMELINE_LATEST;
|
||||
else
|
||||
{
|
||||
rttg = RECOVERY_TARGET_TIMELINE_NUMERIC;
|
||||
|
||||
errno = 0;
|
||||
strtoul(*newval, NULL, 0);
|
||||
if (errno == EINVAL || errno == ERANGE)
|
||||
{
|
||||
GUC_check_errdetail("recovery_target_timeline is not a valid number.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
myextra = (RecoveryTargetTimeLineGoal *) guc_malloc(ERROR, sizeof(RecoveryTargetTimeLineGoal));
|
||||
*myextra = rttg;
|
||||
*extra = (void *) myextra;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for recovery_target_timeline
|
||||
*/
|
||||
void
|
||||
assign_recovery_target_timeline(const char *newval, void *extra)
|
||||
{
|
||||
recoveryTargetTimeLineGoal = *((RecoveryTargetTimeLineGoal *) extra);
|
||||
if (recoveryTargetTimeLineGoal == RECOVERY_TARGET_TIMELINE_NUMERIC)
|
||||
recoveryTargetTLIRequested = (TimeLineID) strtoul(newval, NULL, 0);
|
||||
else
|
||||
recoveryTargetTLIRequested = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for recovery_target_xid
|
||||
*/
|
||||
bool
|
||||
check_recovery_target_xid(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
if (strcmp(*newval, "") != 0)
|
||||
{
|
||||
TransactionId xid;
|
||||
TransactionId *myextra;
|
||||
|
||||
errno = 0;
|
||||
xid = (TransactionId) strtou64(*newval, NULL, 0);
|
||||
if (errno == EINVAL || errno == ERANGE)
|
||||
return false;
|
||||
|
||||
myextra = (TransactionId *) guc_malloc(ERROR, sizeof(TransactionId));
|
||||
*myextra = xid;
|
||||
*extra = (void *) myextra;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for recovery_target_xid
|
||||
*/
|
||||
void
|
||||
assign_recovery_target_xid(const char *newval, void *extra)
|
||||
{
|
||||
if (recoveryTarget != RECOVERY_TARGET_UNSET &&
|
||||
recoveryTarget != RECOVERY_TARGET_XID)
|
||||
error_multiple_recovery_targets();
|
||||
|
||||
if (newval && strcmp(newval, "") != 0)
|
||||
{
|
||||
recoveryTarget = RECOVERY_TARGET_XID;
|
||||
recoveryTargetXid = *((TransactionId *) extra);
|
||||
}
|
||||
else
|
||||
recoveryTarget = RECOVERY_TARGET_UNSET;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "storage/ipc.h"
|
||||
#include "storage/reinit.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/ps_status.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/resowner.h"
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
#include "utils/aclchk_internal.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/rel.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
#include "utils/acl.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/catcache.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/inval.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/memutils.h"
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "catalog/pg_parameter_acl.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/pg_locale.h"
|
||||
#include "utils/rel.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "storage/predicate.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/inval.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/memutils.h"
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#include "utils/acl.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/inval.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/memutils.h"
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
#include "utils/acl.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/rel.h"
|
||||
|
||||
@@ -55,9 +55,11 @@
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/bytea.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/inval.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/plancache.h"
|
||||
#include "utils/rel.h"
|
||||
#include "utils/snapmgr.h"
|
||||
#include "utils/syscache.h"
|
||||
@@ -6499,6 +6501,20 @@ done:
|
||||
table->after_trig_events = qs->events;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for session_replication_role
|
||||
*/
|
||||
void
|
||||
assign_session_replication_role(int newval, void *extra)
|
||||
{
|
||||
/*
|
||||
* Must flush the plan cache when changing replication role; but don't
|
||||
* flush unnecessarily.
|
||||
*/
|
||||
if (SessionReplicationRole != newval)
|
||||
ResetPlanCache();
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL function pg_trigger_depth()
|
||||
*/
|
||||
|
||||
@@ -22,15 +22,23 @@
|
||||
#include "access/parallel.h"
|
||||
#include "access/xact.h"
|
||||
#include "access/xlog.h"
|
||||
#include "access/xlogprefetcher.h"
|
||||
#include "catalog/pg_authid.h"
|
||||
#include "commands/variable.h"
|
||||
#include "common/string.h"
|
||||
#include "mb/pg_wchar.h"
|
||||
#include "miscadmin.h"
|
||||
#include "postmaster/postmaster.h"
|
||||
#include "postmaster/syslogger.h"
|
||||
#include "storage/bufmgr.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/backend_status.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/datetime.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/snapmgr.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/timestamp.h"
|
||||
#include "utils/tzparser.h"
|
||||
#include "utils/varlena.h"
|
||||
|
||||
/*
|
||||
@@ -466,6 +474,56 @@ show_log_timezone(void)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TIMEZONE_ABBREVIATIONS
|
||||
*/
|
||||
|
||||
/*
|
||||
* GUC check_hook for assign_timezone_abbreviations
|
||||
*/
|
||||
bool
|
||||
check_timezone_abbreviations(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
/*
|
||||
* The boot_val for timezone_abbreviations is NULL. When we see that we
|
||||
* just do nothing. If the value isn't overridden from the config file
|
||||
* then pg_timezone_abbrev_initialize() will eventually replace it with
|
||||
* "Default". This hack has two purposes: to avoid wasting cycles loading
|
||||
* values that might soon be overridden from the config file, and to avoid
|
||||
* trying to read the timezone abbrev files during InitializeGUCOptions().
|
||||
* The latter doesn't work in an EXEC_BACKEND subprocess because
|
||||
* my_exec_path hasn't been set yet and so we can't locate PGSHAREDIR.
|
||||
*/
|
||||
if (*newval == NULL)
|
||||
{
|
||||
Assert(source == PGC_S_DEFAULT);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* OK, load the file and produce a malloc'd TimeZoneAbbrevTable */
|
||||
*extra = load_tzoffsets(*newval);
|
||||
|
||||
/* tzparser.c returns NULL on failure, reporting via GUC_check_errmsg */
|
||||
if (!*extra)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for assign_timezone_abbreviations
|
||||
*/
|
||||
void
|
||||
assign_timezone_abbreviations(const char *newval, void *extra)
|
||||
{
|
||||
/* Do nothing for the boot_val default of NULL */
|
||||
if (!extra)
|
||||
return;
|
||||
|
||||
InstallTimeZoneAbbrevs((TimeZoneAbbrevTable *) extra);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SET TRANSACTION READ ONLY and SET TRANSACTION READ WRITE
|
||||
*
|
||||
@@ -522,7 +580,7 @@ check_transaction_read_only(bool *newval, void **extra, GucSource source)
|
||||
* As in check_transaction_read_only, allow it if not inside a transaction.
|
||||
*/
|
||||
bool
|
||||
check_XactIsoLevel(int *newval, void **extra, GucSource source)
|
||||
check_transaction_isolation(int *newval, void **extra, GucSource source)
|
||||
{
|
||||
int newXactIsoLevel = *newval;
|
||||
|
||||
@@ -933,3 +991,212 @@ show_role(void)
|
||||
/* Otherwise we can just use the GUC string */
|
||||
return role_string ? role_string : "none";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PATH VARIABLES
|
||||
*
|
||||
* check_canonical_path is used for log_directory and some other GUCs where
|
||||
* all we want to do is canonicalize the represented path name.
|
||||
*/
|
||||
|
||||
bool
|
||||
check_canonical_path(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
/*
|
||||
* Since canonicalize_path never enlarges the string, we can just modify
|
||||
* newval in-place. But watch out for NULL, which is the default value
|
||||
* for external_pid_file.
|
||||
*/
|
||||
if (*newval)
|
||||
canonicalize_path(*newval);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MISCELLANEOUS
|
||||
*/
|
||||
|
||||
/*
|
||||
* GUC check_hook for application_name
|
||||
*/
|
||||
bool
|
||||
check_application_name(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
char *clean;
|
||||
|
||||
/* Only allow clean ASCII chars in the application name */
|
||||
clean = pg_clean_ascii(*newval, MCXT_ALLOC_NO_OOM);
|
||||
if (!clean)
|
||||
return false;
|
||||
|
||||
clean = guc_strdup(WARNING, clean);
|
||||
if (!clean)
|
||||
return false;
|
||||
|
||||
*newval = clean;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for application_name
|
||||
*/
|
||||
void
|
||||
assign_application_name(const char *newval, void *extra)
|
||||
{
|
||||
/* Update the pg_stat_activity view */
|
||||
pgstat_report_appname(newval);
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for cluster_name
|
||||
*/
|
||||
bool
|
||||
check_cluster_name(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
char *clean;
|
||||
|
||||
/* Only allow clean ASCII chars in the cluster name */
|
||||
clean = pg_clean_ascii(*newval, MCXT_ALLOC_NO_OOM);
|
||||
if (!clean)
|
||||
return false;
|
||||
|
||||
clean = guc_strdup(WARNING, clean);
|
||||
if (!clean)
|
||||
return false;
|
||||
|
||||
*newval = clean;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for maintenance_io_concurrency
|
||||
*/
|
||||
void
|
||||
assign_maintenance_io_concurrency(int newval, void *extra)
|
||||
{
|
||||
#ifdef USE_PREFETCH
|
||||
/*
|
||||
* Reconfigure recovery prefetching, because a setting it depends on
|
||||
* changed.
|
||||
*/
|
||||
maintenance_io_concurrency = newval;
|
||||
if (AmStartupProcess())
|
||||
XLogPrefetchReconfigure();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* These show hooks just exist because we want to show the values in octal.
|
||||
*/
|
||||
|
||||
/*
|
||||
* GUC show_hook for data_directory_mode
|
||||
*/
|
||||
const char *
|
||||
show_data_directory_mode(void)
|
||||
{
|
||||
static char buf[12];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%04o", data_directory_mode);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC show_hook for log_file_mode
|
||||
*/
|
||||
const char *
|
||||
show_log_file_mode(void)
|
||||
{
|
||||
static char buf[12];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%04o", Log_file_mode);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC show_hook for unix_socket_permissions
|
||||
*/
|
||||
const char *
|
||||
show_unix_socket_permissions(void)
|
||||
{
|
||||
static char buf[12];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%04o", Unix_socket_permissions);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* These check hooks do nothing more than reject non-default settings
|
||||
* in builds that don't support them.
|
||||
*/
|
||||
|
||||
bool
|
||||
check_bonjour(bool *newval, void **extra, GucSource source)
|
||||
{
|
||||
#ifndef USE_BONJOUR
|
||||
if (*newval)
|
||||
{
|
||||
GUC_check_errmsg("Bonjour is not supported by this build");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
check_default_with_oids(bool *newval, void **extra, GucSource source)
|
||||
{
|
||||
if (*newval)
|
||||
{
|
||||
/* check the GUC's definition for an explanation */
|
||||
GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED);
|
||||
GUC_check_errmsg("tables declared WITH OIDS are not supported");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
check_effective_io_concurrency(int *newval, void **extra, GucSource source)
|
||||
{
|
||||
#ifndef USE_PREFETCH
|
||||
if (*newval != 0)
|
||||
{
|
||||
GUC_check_errdetail("effective_io_concurrency must be set to 0 on platforms that lack posix_fadvise().");
|
||||
return false;
|
||||
}
|
||||
#endif /* USE_PREFETCH */
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
check_maintenance_io_concurrency(int *newval, void **extra, GucSource source)
|
||||
{
|
||||
#ifndef USE_PREFETCH
|
||||
if (*newval != 0)
|
||||
{
|
||||
GUC_check_errdetail("maintenance_io_concurrency must be set to 0 on platforms that lack posix_fadvise().");
|
||||
return false;
|
||||
}
|
||||
#endif /* USE_PREFETCH */
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
check_ssl(bool *newval, void **extra, GucSource source)
|
||||
{
|
||||
#ifndef USE_SSL
|
||||
if (*newval)
|
||||
{
|
||||
GUC_check_errmsg("SSL is not supported by this build");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
#include "miscadmin.h"
|
||||
#include "port/pg_bswap.h"
|
||||
#include "storage/ipc.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/memutils.h"
|
||||
|
||||
/*
|
||||
@@ -1914,6 +1914,108 @@ pq_settcpusertimeout(int timeout, Port *port)
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for tcp_keepalives_idle
|
||||
*/
|
||||
void
|
||||
assign_tcp_keepalives_idle(int newval, void *extra)
|
||||
{
|
||||
/*
|
||||
* The kernel API provides no way to test a value without setting it; and
|
||||
* once we set it we might fail to unset it. So there seems little point
|
||||
* in fully implementing the check-then-assign GUC API for these
|
||||
* variables. Instead we just do the assignment on demand.
|
||||
* pq_setkeepalivesidle reports any problems via ereport(LOG).
|
||||
*
|
||||
* This approach means that the GUC value might have little to do with the
|
||||
* actual kernel value, so we use a show_hook that retrieves the kernel
|
||||
* value rather than trusting GUC's copy.
|
||||
*/
|
||||
(void) pq_setkeepalivesidle(newval, MyProcPort);
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC show_hook for tcp_keepalives_idle
|
||||
*/
|
||||
const char *
|
||||
show_tcp_keepalives_idle(void)
|
||||
{
|
||||
/* See comments in assign_tcp_keepalives_idle */
|
||||
static char nbuf[16];
|
||||
|
||||
snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesidle(MyProcPort));
|
||||
return nbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for tcp_keepalives_interval
|
||||
*/
|
||||
void
|
||||
assign_tcp_keepalives_interval(int newval, void *extra)
|
||||
{
|
||||
/* See comments in assign_tcp_keepalives_idle */
|
||||
(void) pq_setkeepalivesinterval(newval, MyProcPort);
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC show_hook for tcp_keepalives_interval
|
||||
*/
|
||||
const char *
|
||||
show_tcp_keepalives_interval(void)
|
||||
{
|
||||
/* See comments in assign_tcp_keepalives_idle */
|
||||
static char nbuf[16];
|
||||
|
||||
snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesinterval(MyProcPort));
|
||||
return nbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for tcp_keepalives_count
|
||||
*/
|
||||
void
|
||||
assign_tcp_keepalives_count(int newval, void *extra)
|
||||
{
|
||||
/* See comments in assign_tcp_keepalives_idle */
|
||||
(void) pq_setkeepalivescount(newval, MyProcPort);
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC show_hook for tcp_keepalives_count
|
||||
*/
|
||||
const char *
|
||||
show_tcp_keepalives_count(void)
|
||||
{
|
||||
/* See comments in assign_tcp_keepalives_idle */
|
||||
static char nbuf[16];
|
||||
|
||||
snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivescount(MyProcPort));
|
||||
return nbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for tcp_user_timeout
|
||||
*/
|
||||
void
|
||||
assign_tcp_user_timeout(int newval, void *extra)
|
||||
{
|
||||
/* See comments in assign_tcp_keepalives_idle */
|
||||
(void) pq_settcpusertimeout(newval, MyProcPort);
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC show_hook for tcp_user_timeout
|
||||
*/
|
||||
const char *
|
||||
show_tcp_user_timeout(void)
|
||||
{
|
||||
/* See comments in assign_tcp_keepalives_idle */
|
||||
static char nbuf[16];
|
||||
|
||||
snprintf(nbuf, sizeof(nbuf), "%d", pq_gettcpusertimeout(MyProcPort));
|
||||
return nbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the client is still connected.
|
||||
*/
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "partitioning/partbounds.h"
|
||||
#include "partitioning/partdesc.h"
|
||||
#include "partitioning/partprune.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/datum.h"
|
||||
#include "utils/fmgroids.h"
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include "storage/fd.h"
|
||||
#include "storage/ipc.h"
|
||||
#include "storage/pg_shmem.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/pidfile.h"
|
||||
|
||||
|
||||
@@ -570,6 +570,23 @@ GetHugePageSize(Size *hugepagesize, int *mmap_flags)
|
||||
#endif /* MAP_HUGETLB */
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for huge_page_size
|
||||
*/
|
||||
bool
|
||||
check_huge_page_size(int *newval, void **extra, GucSource source)
|
||||
{
|
||||
#if !(defined(MAP_HUGE_MASK) && defined(MAP_HUGE_SHIFT))
|
||||
/* Recent enough Linux only, for now. See GetHugePageSize(). */
|
||||
if (*newval != 0)
|
||||
{
|
||||
GUC_check_errdetail("huge_page_size must be 0 on this platform.");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates an anonymous mmap()ed shared memory segment.
|
||||
*
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include "storage/dsm.h"
|
||||
#include "storage/ipc.h"
|
||||
#include "storage/pg_shmem.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
|
||||
|
||||
/*
|
||||
* Early in a process's life, Windows asynchronously creates threads for the
|
||||
@@ -619,3 +621,17 @@ GetHugePageSize(Size *hugepagesize, int *mmap_flags)
|
||||
if (mmap_flags)
|
||||
*mmap_flags = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for huge_page_size
|
||||
*/
|
||||
bool
|
||||
check_huge_page_size(int *newval, void **extra, GucSource source)
|
||||
{
|
||||
if (*newval != 0)
|
||||
{
|
||||
GUC_check_errdetail("huge_page_size must be 0 on this platform.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
#include "tcop/tcopprot.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/fmgrprotos.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/ps_status.h"
|
||||
@@ -3374,3 +3375,29 @@ AutoVacuumShmemInit(void)
|
||||
else
|
||||
Assert(found);
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for autovacuum_work_mem
|
||||
*/
|
||||
bool
|
||||
check_autovacuum_work_mem(int *newval, void **extra, GucSource source)
|
||||
{
|
||||
/*
|
||||
* -1 indicates fallback.
|
||||
*
|
||||
* If we haven't yet changed the boot_val default of -1, just let it be.
|
||||
* Autovacuum will look to maintenance_work_mem instead.
|
||||
*/
|
||||
if (*newval == -1)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* We clamp manually-set values to at least 1MB. Since
|
||||
* maintenance_work_mem is always set to at least this value, do the same
|
||||
* here.
|
||||
*/
|
||||
if (*newval < 1024)
|
||||
*newval = 1024;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "access/xlogdefs.h"
|
||||
#include "nodes/makefuncs.h"
|
||||
#include "nodes/parsenodes.h"
|
||||
#include "nodes/replnodes.h"
|
||||
#include "replication/walsender.h"
|
||||
#include "replication/walsender_private.h"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "nodes/parsenodes.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "parser/scansup.h"
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
#include "storage/proc.h"
|
||||
#include "tcop/tcopprot.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/ps_status.h"
|
||||
|
||||
/* User-settable parameters for sync rep */
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "nodes/pg_list.h"
|
||||
#include "replication/syncrep.h"
|
||||
|
||||
/* Result of parsing is returned in one of these two variables */
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "lib/stringinfo.h"
|
||||
#include "nodes/pg_list.h"
|
||||
|
||||
/*
|
||||
* NB: include syncrep_gram.h only AFTER including syncrep.h, because syncrep.h
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "executor/instrument.h"
|
||||
#include "storage/buf_internals.h"
|
||||
#include "storage/bufmgr.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/resowner_private.h"
|
||||
|
||||
@@ -483,6 +483,24 @@ InitLocalBuffers(void)
|
||||
NLocBuffer = nbufs;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for temp_buffers
|
||||
*/
|
||||
bool
|
||||
check_temp_buffers(int *newval, void **extra, GucSource source)
|
||||
{
|
||||
/*
|
||||
* Once local buffers have been initialized, it's too late to change this.
|
||||
* However, if this is only a test call, allow it.
|
||||
*/
|
||||
if (source != PGC_S_TEST && NLocBuffer && NLocBuffer != *newval)
|
||||
{
|
||||
GUC_check_errdetail("\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GetLocalBufferStorage - allocate memory for a local buffer
|
||||
*
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "storage/procsignal.h"
|
||||
#include "storage/sinvaladt.h"
|
||||
#include "storage/spin.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/snapmgr.h"
|
||||
|
||||
/* GUCs */
|
||||
|
||||
@@ -1685,8 +1685,8 @@ GetSerializableTransactionSnapshot(Snapshot snapshot)
|
||||
/*
|
||||
* Can't use serializable mode while recovery is still active, as it is,
|
||||
* for example, on a hot standby. We could get here despite the check in
|
||||
* check_XactIsoLevel() if default_transaction_isolation is set to
|
||||
* serializable, so phrase the hint accordingly.
|
||||
* check_transaction_isolation() if default_transaction_isolation is set
|
||||
* to serializable, so phrase the hint accordingly.
|
||||
*/
|
||||
if (RecoveryInProgress())
|
||||
ereport(ERROR,
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "tcop/pquery.h"
|
||||
#include "tcop/tcopprot.h"
|
||||
#include "tcop/utility.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/ps_status.h"
|
||||
@@ -3505,6 +3506,58 @@ assign_max_stack_depth(int newval, void *extra)
|
||||
max_stack_depth_bytes = newval_bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for client_connection_check_interval
|
||||
*/
|
||||
bool
|
||||
check_client_connection_check_interval(int *newval, void **extra, GucSource source)
|
||||
{
|
||||
if (!WaitEventSetCanReportClosed() && *newval != 0)
|
||||
{
|
||||
GUC_check_errdetail("client_connection_check_interval must be set to 0 on this platform.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for log_parser_stats, log_planner_stats, log_executor_stats
|
||||
*
|
||||
* This function and check_log_stats interact to prevent their variables from
|
||||
* being set in a disallowed combination. This is a hack that doesn't really
|
||||
* work right; for example it might fail while applying pg_db_role_setting
|
||||
* values even though the final state would have been acceptable. However,
|
||||
* since these variables are legacy settings with little production usage,
|
||||
* we tolerate that.
|
||||
*/
|
||||
bool
|
||||
check_stage_log_stats(bool *newval, void **extra, GucSource source)
|
||||
{
|
||||
if (*newval && log_statement_stats)
|
||||
{
|
||||
GUC_check_errdetail("Cannot enable parameter when \"log_statement_stats\" is true.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for log_statement_stats
|
||||
*/
|
||||
bool
|
||||
check_log_stats(bool *newval, void **extra, GucSource source)
|
||||
{
|
||||
if (*newval &&
|
||||
(log_parser_stats || log_planner_stats || log_executor_stats))
|
||||
{
|
||||
GUC_check_errdetail("Cannot enable \"log_statement_stats\" when "
|
||||
"\"log_parser_stats\", \"log_planner_stats\", "
|
||||
"or \"log_executor_stats\" is true.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set_debug_options --- apply "-d N" command line option
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "catalog/pg_type.h"
|
||||
#include "tsearch/ts_cache.h"
|
||||
#include "tsearch/ts_utils.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include "mb/pg_wchar.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/formatting.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/hsearch.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/memutils.h"
|
||||
|
||||
@@ -123,6 +123,7 @@
|
||||
#include "statistics/statistics.h"
|
||||
#include "storage/bufmgr.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/date.h"
|
||||
#include "utils/datum.h"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/detoast.h"
|
||||
#include "access/htup_details.h"
|
||||
#include "catalog/pg_collation.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "common/hashfn.h"
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "regex/regex.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/bytea.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/pg_locale.h"
|
||||
|
||||
5
src/backend/utils/cache/ts_cache.c
vendored
5
src/backend/utils/cache/ts_cache.c
vendored
@@ -42,6 +42,7 @@
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/catcache.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/inval.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/memutils.h"
|
||||
@@ -584,7 +585,7 @@ getTSCurrentConfig(bool emitError)
|
||||
|
||||
/* GUC check_hook for default_text_search_config */
|
||||
bool
|
||||
check_TSCurrentConfig(char **newval, void **extra, GucSource source)
|
||||
check_default_text_search_config(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
/*
|
||||
* If we aren't inside a transaction, or connected to a database, we
|
||||
@@ -645,7 +646,7 @@ check_TSCurrentConfig(char **newval, void **extra, GucSource source)
|
||||
|
||||
/* GUC assign_hook for default_text_search_config */
|
||||
void
|
||||
assign_TSCurrentConfig(const char *newval, void *extra)
|
||||
assign_default_text_search_config(const char *newval, void *extra)
|
||||
{
|
||||
/* Just reset the cache to force a lookup on first use */
|
||||
TSCurrentConfigCache = InvalidOid;
|
||||
|
||||
@@ -79,9 +79,10 @@
|
||||
#include "storage/ipc.h"
|
||||
#include "storage/proc.h"
|
||||
#include "tcop/tcopprot.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/ps_status.h"
|
||||
#include "utils/varlena.h"
|
||||
|
||||
|
||||
/* In this module, access gettext() via err_gettext() */
|
||||
@@ -113,6 +114,9 @@ char *Log_destination_string = NULL;
|
||||
bool syslog_sequence_numbers = true;
|
||||
bool syslog_split_messages = true;
|
||||
|
||||
/* Processed form of backtrace_symbols GUC */
|
||||
static char *backtrace_symbol_list;
|
||||
|
||||
#ifdef HAVE_SYSLOG
|
||||
|
||||
/*
|
||||
@@ -1957,14 +1961,159 @@ DebugFileOpen(void)
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_SYSLOG
|
||||
/*
|
||||
* GUC check_hook for backtrace_functions
|
||||
*
|
||||
* We split the input string, where commas separate function names
|
||||
* and certain whitespace chars are ignored, into a \0-separated (and
|
||||
* \0\0-terminated) list of function names. This formulation allows
|
||||
* easy scanning when an error is thrown while avoiding the use of
|
||||
* non-reentrant strtok(), as well as keeping the output data in a
|
||||
* single palloc() chunk.
|
||||
*/
|
||||
bool
|
||||
check_backtrace_functions(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
int newvallen = strlen(*newval);
|
||||
char *someval;
|
||||
int validlen;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
/*
|
||||
* Allow characters that can be C identifiers and commas as separators, as
|
||||
* well as some whitespace for readability.
|
||||
*/
|
||||
validlen = strspn(*newval,
|
||||
"0123456789_"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
", \n\t");
|
||||
if (validlen != newvallen)
|
||||
{
|
||||
GUC_check_errdetail("invalid character");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*newval[0] == '\0')
|
||||
{
|
||||
*extra = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate space for the output and create the copy. We could discount
|
||||
* whitespace chars to save some memory, but it doesn't seem worth the
|
||||
* trouble.
|
||||
*/
|
||||
someval = guc_malloc(ERROR, newvallen + 1 + 1);
|
||||
for (i = 0, j = 0; i < newvallen; i++)
|
||||
{
|
||||
if ((*newval)[i] == ',')
|
||||
someval[j++] = '\0'; /* next item */
|
||||
else if ((*newval)[i] == ' ' ||
|
||||
(*newval)[i] == '\n' ||
|
||||
(*newval)[i] == '\t')
|
||||
; /* ignore these */
|
||||
else
|
||||
someval[j++] = (*newval)[i]; /* copy anything else */
|
||||
}
|
||||
|
||||
/* two \0s end the setting */
|
||||
someval[j] = '\0';
|
||||
someval[j + 1] = '\0';
|
||||
|
||||
*extra = someval;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set or update the parameters for syslog logging
|
||||
* GUC assign_hook for backtrace_functions
|
||||
*/
|
||||
void
|
||||
set_syslog_parameters(const char *ident, int facility)
|
||||
assign_backtrace_functions(const char *newval, void *extra)
|
||||
{
|
||||
backtrace_symbol_list = (char *) extra;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for log_destination
|
||||
*/
|
||||
bool
|
||||
check_log_destination(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
char *rawstring;
|
||||
List *elemlist;
|
||||
ListCell *l;
|
||||
int newlogdest = 0;
|
||||
int *myextra;
|
||||
|
||||
/* Need a modifiable copy of string */
|
||||
rawstring = pstrdup(*newval);
|
||||
|
||||
/* Parse string into list of identifiers */
|
||||
if (!SplitIdentifierString(rawstring, ',', &elemlist))
|
||||
{
|
||||
/* syntax error in list */
|
||||
GUC_check_errdetail("List syntax is invalid.");
|
||||
pfree(rawstring);
|
||||
list_free(elemlist);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach(l, elemlist)
|
||||
{
|
||||
char *tok = (char *) lfirst(l);
|
||||
|
||||
if (pg_strcasecmp(tok, "stderr") == 0)
|
||||
newlogdest |= LOG_DESTINATION_STDERR;
|
||||
else if (pg_strcasecmp(tok, "csvlog") == 0)
|
||||
newlogdest |= LOG_DESTINATION_CSVLOG;
|
||||
else if (pg_strcasecmp(tok, "jsonlog") == 0)
|
||||
newlogdest |= LOG_DESTINATION_JSONLOG;
|
||||
#ifdef HAVE_SYSLOG
|
||||
else if (pg_strcasecmp(tok, "syslog") == 0)
|
||||
newlogdest |= LOG_DESTINATION_SYSLOG;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
else if (pg_strcasecmp(tok, "eventlog") == 0)
|
||||
newlogdest |= LOG_DESTINATION_EVENTLOG;
|
||||
#endif
|
||||
else
|
||||
{
|
||||
GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
|
||||
pfree(rawstring);
|
||||
list_free(elemlist);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
pfree(rawstring);
|
||||
list_free(elemlist);
|
||||
|
||||
myextra = (int *) guc_malloc(ERROR, sizeof(int));
|
||||
*myextra = newlogdest;
|
||||
*extra = (void *) myextra;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for log_destination
|
||||
*/
|
||||
void
|
||||
assign_log_destination(const char *newval, void *extra)
|
||||
{
|
||||
Log_destination = *((int *) extra);
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for syslog_ident
|
||||
*/
|
||||
void
|
||||
assign_syslog_ident(const char *newval, void *extra)
|
||||
{
|
||||
#ifdef HAVE_SYSLOG
|
||||
/*
|
||||
* guc.c is likely to call us repeatedly with same parameters, so don't
|
||||
* thrash the syslog connection unnecessarily. Also, we do not re-open
|
||||
@@ -1975,8 +2124,7 @@ set_syslog_parameters(const char *ident, int facility)
|
||||
* on guc.c's. This may be overly paranoid, but it ensures that we cannot
|
||||
* accidentally free a string that syslog is still using.
|
||||
*/
|
||||
if (syslog_ident == NULL || strcmp(syslog_ident, ident) != 0 ||
|
||||
syslog_facility != facility)
|
||||
if (syslog_ident == NULL || strcmp(syslog_ident, newval) != 0)
|
||||
{
|
||||
if (openlog_done)
|
||||
{
|
||||
@@ -1984,12 +2132,37 @@ set_syslog_parameters(const char *ident, int facility)
|
||||
openlog_done = false;
|
||||
}
|
||||
free(syslog_ident);
|
||||
syslog_ident = strdup(ident);
|
||||
syslog_ident = strdup(newval);
|
||||
/* if the strdup fails, we will cope in write_syslog() */
|
||||
syslog_facility = facility;
|
||||
}
|
||||
#endif
|
||||
/* Without syslog support, just ignore it */
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC assign_hook for syslog_facility
|
||||
*/
|
||||
void
|
||||
assign_syslog_facility(int newval, void *extra)
|
||||
{
|
||||
#ifdef HAVE_SYSLOG
|
||||
/*
|
||||
* As above, don't thrash the syslog connection unnecessarily.
|
||||
*/
|
||||
if (syslog_facility != newval)
|
||||
{
|
||||
if (openlog_done)
|
||||
{
|
||||
closelog();
|
||||
openlog_done = false;
|
||||
}
|
||||
syslog_facility = newval;
|
||||
}
|
||||
#endif
|
||||
/* Without syslog support, just ignore it */
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYSLOG
|
||||
|
||||
/*
|
||||
* Write a message line to syslog
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
#include "utils/acl.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/pg_locale.h"
|
||||
#include "utils/portal.h"
|
||||
@@ -563,6 +563,54 @@ InitializeMaxBackends(void)
|
||||
elog(ERROR, "too many backends configured");
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for max_connections
|
||||
*/
|
||||
bool
|
||||
check_max_connections(int *newval, void **extra, GucSource source)
|
||||
{
|
||||
if (*newval + autovacuum_max_workers + 1 +
|
||||
max_worker_processes + max_wal_senders > MAX_BACKENDS)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for autovacuum_max_workers
|
||||
*/
|
||||
bool
|
||||
check_autovacuum_max_workers(int *newval, void **extra, GucSource source)
|
||||
{
|
||||
if (MaxConnections + *newval + 1 +
|
||||
max_worker_processes + max_wal_senders > MAX_BACKENDS)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for max_worker_processes
|
||||
*/
|
||||
bool
|
||||
check_max_worker_processes(int *newval, void **extra, GucSource source)
|
||||
{
|
||||
if (MaxConnections + autovacuum_max_workers + 1 +
|
||||
*newval + max_wal_senders > MAX_BACKENDS)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GUC check_hook for max_wal_senders
|
||||
*/
|
||||
bool
|
||||
check_max_wal_senders(int *newval, void **extra, GucSource source)
|
||||
{
|
||||
if (MaxConnections + autovacuum_max_workers + 1 +
|
||||
max_worker_processes + *newval > MAX_BACKENDS)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Early initialization of a backend (either standalone or under postmaster).
|
||||
* This happens even before InitPostgres.
|
||||
|
||||
@@ -17,6 +17,8 @@ override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS)
|
||||
OBJS = \
|
||||
guc.o \
|
||||
guc-file.o \
|
||||
guc_funcs.o \
|
||||
guc_tables.o \
|
||||
help_config.o \
|
||||
pg_config.o \
|
||||
pg_controldata.o \
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1047
src/backend/utils/misc/guc_funcs.c
Normal file
1047
src/backend/utils/misc/guc_funcs.c
Normal file
File diff suppressed because it is too large
Load Diff
4875
src/backend/utils/misc/guc_tables.c
Normal file
4875
src/backend/utils/misc/guc_tables.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user