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 1302 of file guc.c.

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

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 284 of file guc.c.

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