PostgreSQL Source Code  git master
guc_internal.h File Reference
#include "utils/guc.h"
Include dependency graph for guc_internal.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int guc_name_compare (const char *namea, const char *nameb)
 
ConfigVariableProcessConfigFileInternal (GucContext context, bool applySettings, int elevel)
 
void record_config_file_error (const char *errmsg, const char *config_file, int lineno, ConfigVariable **head_p, ConfigVariable **tail_p)
 

Function Documentation

◆ guc_name_compare()

int guc_name_compare ( const char *  namea,
const char *  nameb 
)

Definition at line 1299 of file guc.c.

1300 {
1301  /*
1302  * The temptation to use strcasecmp() here must be resisted, because the
1303  * hash mapping has to remain stable across setlocale() calls. So, build
1304  * our own with a simple ASCII-only downcasing.
1305  */
1306  while (*namea && *nameb)
1307  {
1308  char cha = *namea++;
1309  char chb = *nameb++;
1310 
1311  if (cha >= 'A' && cha <= 'Z')
1312  cha += 'a' - 'A';
1313  if (chb >= 'A' && chb <= 'Z')
1314  chb += 'a' - 'A';
1315  if (cha != chb)
1316  return cha - chb;
1317  }
1318  if (*namea)
1319  return 1; /* a is longer */
1320  if (*nameb)
1321  return -1; /* b is longer */
1322  return 0;
1323 }

Referenced by convert_GUC_name_for_parameter_acl(), find_option(), GetPGVariable(), GetPGVariableResultDesc(), guc_name_match(), guc_var_compare(), and replace_auto_config_value().

◆ ProcessConfigFileInternal()

ConfigVariable* ProcessConfigFileInternal ( GucContext  context,
bool  applySettings,
int  elevel 
)

Definition at line 281 of file guc.c.

282 {
283  bool error = false;
284  bool applying = false;
285  const char *ConfFileWithError;
286  ConfigVariable *item,
287  *head,
288  *tail;
289  HASH_SEQ_STATUS status;
290  GUCHashEntry *hentry;
291 
292  /* Parse the main config file into a list of option names and values */
293  ConfFileWithError = ConfigFileName;
294  head = tail = NULL;
295 
296  if (!ParseConfigFile(ConfigFileName, true,
297  NULL, 0, CONF_FILE_START_DEPTH, elevel,
298  &head, &tail))
299  {
300  /* Syntax error(s) detected in the file, so bail out */
301  error = true;
302  goto bail_out;
303  }
304 
305  /*
306  * Parse the PG_AUTOCONF_FILENAME file, if present, after the main file to
307  * replace any parameters set by ALTER SYSTEM command. Because this file
308  * is in the data directory, we can't read it until the DataDir has been
309  * set.
310  */
311  if (DataDir)
312  {
314  NULL, 0, CONF_FILE_START_DEPTH, elevel,
315  &head, &tail))
316  {
317  /* Syntax error(s) detected in the file, so bail out */
318  error = true;
319  ConfFileWithError = PG_AUTOCONF_FILENAME;
320  goto bail_out;
321  }
322  }
323  else
324  {
325  /*
326  * If DataDir is not set, the PG_AUTOCONF_FILENAME file cannot be
327  * read. In this case, we don't want to accept any settings but
328  * data_directory from postgresql.conf, because they might be
329  * overwritten with settings in the PG_AUTOCONF_FILENAME file which
330  * will be read later. OTOH, since data_directory isn't allowed in the
331  * PG_AUTOCONF_FILENAME file, it will never be overwritten later.
332  */
333  ConfigVariable *newlist = NULL;
334 
335  /*
336  * Prune all items except the last "data_directory" from the list.
337  */
338  for (item = head; item; item = item->next)
339  {
340  if (!item->ignore &&
341  strcmp(item->name, "data_directory") == 0)
342  newlist = item;
343  }
344 
345  if (newlist)
346  newlist->next = NULL;
347  head = tail = newlist;
348 
349  /*
350  * Quick exit if data_directory is not present in file.
351  *
352  * We need not do any further processing, in particular we don't set
353  * PgReloadTime; that will be set soon by subsequent full loading of
354  * the config file.
355  */
356  if (head == NULL)
357  goto bail_out;
358  }
359 
360  /*
361  * Mark all extant GUC variables as not present in the config file. We
362  * need this so that we can tell below which ones have been removed from
363  * the file since we last processed it.
364  */
365  hash_seq_init(&status, guc_hashtab);
366  while ((hentry = (GUCHashEntry *) hash_seq_search(&status)) != NULL)
367  {
368  struct config_generic *gconf = hentry->gucvar;
369 
370  gconf->status &= ~GUC_IS_IN_FILE;
371  }
372 
373  /*
374  * Check if all the supplied option names are valid, as an additional
375  * quasi-syntactic check on the validity of the config file. It is
376  * important that the postmaster and all backends agree on the results of
377  * this phase, else we will have strange inconsistencies about which
378  * processes accept a config file update and which don't. Hence, unknown
379  * custom variable names have to be accepted without complaint. For the
380  * same reason, we don't attempt to validate the options' values here.
381  *
382  * In addition, the GUC_IS_IN_FILE flag is set on each existing GUC
383  * variable mentioned in the file; and we detect duplicate entries in the
384  * file and mark the earlier occurrences as ignorable.
385  */
386  for (item = head; item; item = item->next)
387  {
388  struct config_generic *record;
389 
390  /* Ignore anything already marked as ignorable */
391  if (item->ignore)
392  continue;
393 
394  /*
395  * Try to find the variable; but do not create a custom placeholder if
396  * it's not there already.
397  */
398  record = find_option(item->name, false, true, elevel);
399 
400  if (record)
401  {
402  /* If it's already marked, then this is a duplicate entry */
403  if (record->status & GUC_IS_IN_FILE)
404  {
405  /*
406  * Mark the earlier occurrence(s) as dead/ignorable. We could
407  * avoid the O(N^2) behavior here with some additional state,
408  * but it seems unlikely to be worth the trouble.
409  */
410  ConfigVariable *pitem;
411 
412  for (pitem = head; pitem != item; pitem = pitem->next)
413  {
414  if (!pitem->ignore &&
415  strcmp(pitem->name, item->name) == 0)
416  pitem->ignore = true;
417  }
418  }
419  /* Now mark it as present in file */
420  record->status |= GUC_IS_IN_FILE;
421  }
422  else if (!valid_custom_variable_name(item->name))
423  {
424  /* Invalid non-custom variable, so complain */
425  ereport(elevel,
426  (errcode(ERRCODE_UNDEFINED_OBJECT),
427  errmsg("unrecognized configuration parameter \"%s\" in file \"%s\" line %d",
428  item->name,
429  item->filename, item->sourceline)));
430  item->errmsg = pstrdup("unrecognized configuration parameter");
431  error = true;
432  ConfFileWithError = item->filename;
433  }
434  }
435 
436  /*
437  * If we've detected any errors so far, we don't want to risk applying any
438  * changes.
439  */
440  if (error)
441  goto bail_out;
442 
443  /* Otherwise, set flag that we're beginning to apply changes */
444  applying = true;
445 
446  /*
447  * Check for variables having been removed from the config file, and
448  * revert their reset values (and perhaps also effective values) to the
449  * boot-time defaults. If such a variable can't be changed after startup,
450  * report that and continue.
451  */
453  while ((hentry = (GUCHashEntry *) hash_seq_search(&status)) != NULL)
454  {
455  struct config_generic *gconf = hentry->gucvar;
456  GucStack *stack;
457 
458  if (gconf->reset_source != PGC_S_FILE ||
459  (gconf->status & GUC_IS_IN_FILE))
460  continue;
461  if (gconf->context < PGC_SIGHUP)
462  {
463  /* The removal can't be effective without a restart */
464  gconf->status |= GUC_PENDING_RESTART;
465  ereport(elevel,
466  (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
467  errmsg("parameter \"%s\" cannot be changed without restarting the server",
468  gconf->name)));
469  record_config_file_error(psprintf("parameter \"%s\" cannot be changed without restarting the server",
470  gconf->name),
471  NULL, 0,
472  &head, &tail);
473  error = true;
474  continue;
475  }
476 
477  /* No more to do if we're just doing show_all_file_settings() */
478  if (!applySettings)
479  continue;
480 
481  /*
482  * Reset any "file" sources to "default", else set_config_option will
483  * not override those settings.
484  */
485  if (gconf->reset_source == PGC_S_FILE)
486  gconf->reset_source = PGC_S_DEFAULT;
487  if (gconf->source == PGC_S_FILE)
489  for (stack = gconf->stack; stack; stack = stack->prev)
490  {
491  if (stack->source == PGC_S_FILE)
493  }
494 
495  /* Now we can re-apply the wired-in default (i.e., the boot_val) */
496  if (set_config_option(gconf->name, NULL,
498  GUC_ACTION_SET, true, 0, false) > 0)
499  {
500  /* Log the change if appropriate */
501  if (context == PGC_SIGHUP)
502  ereport(elevel,
503  (errmsg("parameter \"%s\" removed from configuration file, reset to default",
504  gconf->name)));
505  }
506  }
507 
508  /*
509  * Restore any variables determined by environment variables or
510  * dynamically-computed defaults. This is a no-op except in the case
511  * where one of these had been in the config file and is now removed.
512  *
513  * In particular, we *must not* do this during the postmaster's initial
514  * loading of the file, since the timezone functions in particular should
515  * be run only after initialization is complete.
516  *
517  * XXX this is an unmaintainable crock, because we have to know how to set
518  * (or at least what to call to set) every non-PGC_INTERNAL variable that
519  * could potentially have PGC_S_DYNAMIC_DEFAULT or PGC_S_ENV_VAR source.
520  */
521  if (context == PGC_SIGHUP && applySettings)
522  {
525  /* this selects SQL_ASCII in processes not connected to a database */
526  SetConfigOption("client_encoding", GetDatabaseEncodingName(),
528  }
529 
530  /*
531  * Now apply the values from the config file.
532  */
533  for (item = head; item; item = item->next)
534  {
535  char *pre_value = NULL;
536  int scres;
537 
538  /* Ignore anything marked as ignorable */
539  if (item->ignore)
540  continue;
541 
542  /* In SIGHUP cases in the postmaster, we want to report changes */
543  if (context == PGC_SIGHUP && applySettings && !IsUnderPostmaster)
544  {
545  const char *preval = GetConfigOption(item->name, true, false);
546 
547  /* If option doesn't exist yet or is NULL, treat as empty string */
548  if (!preval)
549  preval = "";
550  /* must dup, else might have dangling pointer below */
551  pre_value = pstrdup(preval);
552  }
553 
554  scres = set_config_option(item->name, item->value,
556  GUC_ACTION_SET, applySettings, 0, false);
557  if (scres > 0)
558  {
559  /* variable was updated, so log the change if appropriate */
560  if (pre_value)
561  {
562  const char *post_value = GetConfigOption(item->name, true, false);
563 
564  if (!post_value)
565  post_value = "";
566  if (strcmp(pre_value, post_value) != 0)
567  ereport(elevel,
568  (errmsg("parameter \"%s\" changed to \"%s\"",
569  item->name, item->value)));
570  }
571  item->applied = true;
572  }
573  else if (scres == 0)
574  {
575  error = true;
576  item->errmsg = pstrdup("setting could not be applied");
577  ConfFileWithError = item->filename;
578  }
579  else
580  {
581  /* no error, but variable's active value was not changed */
582  item->applied = true;
583  }
584 
585  /*
586  * We should update source location unless there was an error, since
587  * even if the active value didn't change, the reset value might have.
588  * (In the postmaster, there won't be a difference, but it does matter
589  * in backends.)
590  */
591  if (scres != 0 && applySettings)
592  set_config_sourcefile(item->name, item->filename,
593  item->sourceline);
594 
595  if (pre_value)
596  pfree(pre_value);
597  }
598 
599  /* Remember when we last successfully loaded the config file. */
600  if (applySettings)
602 
603 bail_out:
604  if (error && applySettings)
605  {
606  /* During postmaster startup, any error is fatal */
607  if (context == PGC_POSTMASTER)
608  ereport(ERROR,
609  (errcode(ERRCODE_CONFIG_FILE_ERROR),
610  errmsg("configuration file \"%s\" contains errors",
611  ConfFileWithError)));
612  else if (applying)
613  ereport(elevel,
614  (errcode(ERRCODE_CONFIG_FILE_ERROR),
615  errmsg("configuration file \"%s\" contains errors; unaffected changes were applied",
616  ConfFileWithError)));
617  else
618  ereport(elevel,
619  (errcode(ERRCODE_CONFIG_FILE_ERROR),
620  errmsg("configuration file \"%s\" contains errors; no changes were applied",
621  ConfFileWithError)));
622  }
623 
624  /* Successful or otherwise, return the collected data list */
625  return head;
626 }
TimestampTz PgReloadTime
Definition: timestamp.c:56
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1655
#define CONF_FILE_START_DEPTH
Definition: conffiles.h:17
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1395
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1385
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
bool IsUnderPostmaster
Definition: globals.c:118
char * DataDir
Definition: globals.c:69
struct config_generic * find_option(const char *name, bool create_placeholders, bool skip_errors, int elevel)
Definition: guc.c:1234
static void set_config_sourcefile(const char *name, char *sourcefile, int sourceline)
Definition: guc.c:4249
static bool valid_custom_variable_name(const char *name)
Definition: guc.c:1075
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
Definition: guc.c:4282
static void pg_timezone_abbrev_initialize(void)
Definition: guc.c:1991
const char * GetConfigOption(const char *name, bool missing_ok, bool restrict_privileged)
Definition: guc.c:4305
static void InitializeGUCOptionsFromEnvironment(void)
Definition: guc.c:1588
static void set_guc_source(struct config_generic *gconf, GucSource newsource)
Definition: guc.c:2110
static HTAB * guc_hashtab
Definition: guc.c:211
int set_config_option(const char *name, const char *value, GucContext context, GucSource source, GucAction action, bool changeVal, int elevel, bool is_reload)
Definition: guc.c:3340
#define PG_AUTOCONF_FILENAME
Definition: guc.h:33
@ GUC_ACTION_SET
Definition: guc.h:199
@ PGC_S_DEFAULT
Definition: guc.h:109
@ PGC_S_DYNAMIC_DEFAULT
Definition: guc.h:110
@ PGC_S_FILE
Definition: guc.h:112
bool ParseConfigFile(const char *config_file, bool strict, const char *calling_file, int calling_lineno, int depth, int elevel, ConfigVariable **head_p, ConfigVariable **tail_p)
@ PGC_POSTMASTER
Definition: guc.h:70
@ PGC_SIGHUP
Definition: guc.h:71
@ PGC_BACKEND
Definition: guc.h:73
void record_config_file_error(const char *errmsg, const char *config_file, int lineno, ConfigVariable **head_p, ConfigVariable **tail_p)
char * ConfigFileName
Definition: guc_tables.c:532
#define GUC_IS_IN_FILE
Definition: guc_tables.h:187
#define GUC_PENDING_RESTART
Definition: guc_tables.h:192
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1267
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void pfree(void *pointer)
Definition: mcxt.c:1521
static void bail_out(bool noatexit, const char *fmt,...) pg_attribute_printf(2
Definition: pg_regress.c:253
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
tree context
Definition: radixtree.h:1835
static void error(void)
Definition: sql-dyntest.c:147
char * name
Definition: guc.h:137
bool ignore
Definition: guc.h:142
struct ConfigVariable * next
Definition: guc.h:144
bool applied
Definition: guc.h:143
char * filename
Definition: guc.h:140
int sourceline
Definition: guc.h:141
char * value
Definition: guc.h:138
char * errmsg
Definition: guc.h:139
struct config_generic * gucvar
Definition: guc.c:208
GucContext context
Definition: guc_tables.h:157
const char * name
Definition: guc_tables.h:156
GucStack * stack
Definition: guc_tables.h:171
GucSource source
Definition: guc_tables.h:165
GucSource reset_source
Definition: guc_tables.h:166
struct guc_stack * prev
Definition: guc_tables.h:119
GucSource source
Definition: guc_tables.h:122

References ConfigVariable::applied, bail_out(), CONF_FILE_START_DEPTH, ConfigFileName, context, config_generic::context, DataDir, ereport, errcode(), errmsg(), ConfigVariable::errmsg, ERROR, error(), ConfigVariable::filename, find_option(), GetConfigOption(), GetCurrentTimestamp(), GetDatabaseEncodingName(), GUC_ACTION_SET, guc_hashtab, GUC_IS_IN_FILE, GUC_PENDING_RESTART, GUCHashEntry::gucvar, hash_seq_init(), hash_seq_search(), ConfigVariable::ignore, InitializeGUCOptionsFromEnvironment(), IsUnderPostmaster, ConfigVariable::name, config_generic::name, ConfigVariable::next, ParseConfigFile(), pfree(), PG_AUTOCONF_FILENAME, pg_timezone_abbrev_initialize(), PGC_BACKEND, PGC_POSTMASTER, PGC_S_DEFAULT, PGC_S_DYNAMIC_DEFAULT, PGC_S_FILE, PGC_SIGHUP, PgReloadTime, guc_stack::prev, psprintf(), pstrdup(), record_config_file_error(), config_generic::reset_source, set_config_option(), set_config_sourcefile(), set_guc_source(), SetConfigOption(), guc_stack::source, config_generic::source, ConfigVariable::sourceline, config_generic::stack, config_generic::status, valid_custom_variable_name(), and ConfigVariable::value.

Referenced by show_all_file_settings().

◆ record_config_file_error()

void record_config_file_error ( const char *  errmsg,
const char *  config_file,
int  lineno,
ConfigVariable **  head_p,
ConfigVariable **  tail_p 
)