1
0
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:
Tom Lane
2022-09-13 11:05:07 -04:00
parent 257eb57b50
commit 0a20ff54f5
59 changed files with 7466 additions and 7128 deletions

View File

@@ -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