Commit f84308f1 authored by Peter Eisentraut's avatar Peter Eisentraut

Make configuration parameters fall back to their default values when they

are removed from the configuration file.

Joachim Wieland
parent eee22892
......@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.234 2007/02/09 03:35:33 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.235 2007/03/12 22:09:27 petere Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1513,6 +1513,9 @@ CommitTransaction(void)
/* NOTIFY commit must come before lower-level cleanup */
AtCommit_Notify();
/* GUC processing could abort transaction */
AtEOXact_GUC(true, false);
/*
* Update flat files if we changed pg_database, pg_authid or
* pg_auth_members. This should be the last step before commit.
......@@ -1623,7 +1626,6 @@ CommitTransaction(void)
/* Check we've released all catcache entries */
AtEOXact_CatCache(true);
AtEOXact_GUC(true, false);
AtEOXact_SPI(true);
AtEOXact_on_commit_actions(true);
AtEOXact_Namespace(true);
......
......@@ -4,7 +4,7 @@
*
* Copyright (c) 2000-2007, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.47 2007/02/10 14:58:55 petere Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.48 2007/03/12 22:09:27 petere Exp $
*/
%{
......@@ -54,6 +54,8 @@ static bool ParseConfigFile(const char *config_file, const char *calling_file,
static void free_name_value_list(struct name_value_pair * list);
static char *GUC_scanstr(const char *s);
static char *custom_variable_classes_backup;
%}
%option 8bit
......@@ -116,6 +118,10 @@ ProcessConfigFile(GucContext context)
{
int elevel;
struct name_value_pair *item, *head, *tail;
int i;
bool *in_conffile = NULL;
const char *var;
bool success = false;
Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
......@@ -132,6 +138,18 @@ ProcessConfigFile(GucContext context)
head = tail = NULL;
/*
* We do not know whether we will read the configuration file
* without error. If we encounter an error we have to restore the
* previous value of the custom_variable_classes variable for
* consistency. Therefore we have to save its value.
*/
var = GetConfigOption("custom_variable_classes");
if (var)
custom_variable_classes_backup = pstrdup(var);
set_config_option("custom_variable_classes", NULL, context,
PGC_S_DEFAULT, false, true);
if (!ParseConfigFile(ConfigFileName, NULL,
0, context, elevel,
&head, &tail))
......@@ -140,20 +158,198 @@ ProcessConfigFile(GucContext context)
/* Check if all options are valid */
for (item = head; item; item = item->next)
{
char *sep = strchr(item->name, GUC_QUALIFIER_SEPARATOR);
if (sep && !is_custom_class(item->name, sep - item->name))
{
ereport(elevel,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("unrecognized configuration parameter \"%s\"",
item->name)));
goto cleanup_list;
}
if (!set_config_option(item->name, item->value, context,
PGC_S_FILE, false, false))
goto cleanup_list;
}
/* If we got here all the options checked out okay, so apply them. */
/*
* Mark all variables as not showing up in the config file. The
* allocation has to take place after ParseConfigFile() since this
* function can change num_guc_variables due to custom variables.
* It would be easier to add a new field or status bit to struct
* conf_generic, but that way we would expose internal information
* that is just needed here in the following few lines. The price
* to pay for this separation are a few more loops over the set of
* configuration options, but those are expected to be rather few
* and we only have to pay the cost at SIGHUP. We initialize
* in_conffile only here because set_config_option() makes
* guc_variables grow with custom variables.
*/
in_conffile = guc_malloc(elevel, num_guc_variables * sizeof(bool));
if (!in_conffile)
goto cleanup_list;
for (i = 0; i < num_guc_variables; i++)
in_conffile[i] = false;
for (item = head; item; item = item->next)
{
/*
* After set_config_option() the variable name item->name is
* known to exist.
*/
Assert(guc_get_index(item->name) >= 0);
in_conffile[guc_get_index(item->name)] = true;
}
for (i = 0; i < num_guc_variables; i++)
{
struct config_generic *gconf = guc_variables[i];
if (!in_conffile[i] && strchr(gconf->name, GUC_QUALIFIER_SEPARATOR))
{
/* handle custom variables here */
int j;
/*
* guc_delete_variable will re-sort the array of
* configuration options and decrease num_guc_variables by
* one.
*/
guc_delete_custom_variable(gconf->name);
/*
* Since the array is always sorted we just have to shift
* all boolean values after position i by one position to
* the left.
*/
for (j = i; j < num_guc_variables; j++)
in_conffile[j] = in_conffile[j+1];
/*
* Decrease the loop variable to re-test the entry at the
* current position that is now a different one.
*/
i--;
continue;
}
else if (!in_conffile[i] && gconf->source == PGC_S_FILE)
{
if (gconf->context < PGC_SIGHUP)
ereport(elevel,
(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
errmsg("parameter \"%s\" cannot be changed after server start; configuration file change ignored",
gconf->name)));
else
{
/* prepare */
GucStack *stack;
if (gconf->reset_source == PGC_S_FILE)
gconf->reset_source = PGC_S_DEFAULT;
for (stack = gconf->stack; stack; stack = stack->prev)
if (stack->source == PGC_S_FILE)
stack->source = PGC_S_DEFAULT;
/* apply the default */
set_config_option(gconf->name, NULL, context,
PGC_S_DEFAULT, false, true);
}
}
else if (!in_conffile[i] && gconf->reset_source == PGC_S_FILE)
{
/*------
* Change the reset_val to default_val. Here's an
* example: In the configuration file we have
*
* seq_page_cost = 3.00
*
* Now we execute in a session
*
* SET seq_page_cost TO 4.00;
*
* Then we remove this option from the configuration file
* and send SIGHUP. Now when you execute
*
* RESET seq_page_cost;
*
* it should fall back to 1.00 (the default value for
* seq_page_cost) and not to 3.00 (which is the current
* reset_val).
*/
switch (gconf->vartype)
{
case PGC_BOOL:
{
struct config_bool *conf;
conf = (struct config_bool *) gconf;
conf->reset_val = conf->boot_val;
break;
}
case PGC_INT:
{
struct config_int *conf;
conf = (struct config_int *) gconf;
conf->reset_val = conf->boot_val;
break;
}
case PGC_REAL:
{
struct config_real *conf;
conf = (struct config_real *) gconf;
conf->reset_val = conf->boot_val;
break;
}
case PGC_STRING:
{
struct config_string *conf;
conf = (struct config_string *) gconf;
/*
* We can cast away the const here because we
* won't free the address. It is protected by
* set_string_field() and string_field_used().
*/
conf->reset_val = (char *) conf->boot_val;
break;
}
}
}
}
/* If we got here all the options checked out okay, so apply them. */
for (item = head; item; item = item->next)
set_config_option(item->name, item->value, context,
PGC_S_FILE, false, true);
}
/*
* Reset variables to the value of environment variables
* (PGC_S_ENV_VAR overrules PGC_S_FILE). PGPORT is ignored,
* because it cannot be changed without restart.
*/
var = getenv("PGDATESTYLE");
if (var != NULL)
set_config_option("datestyle", var, context,
PGC_S_ENV_VAR, false, true);
var = getenv("PGCLIENTENCODING");
if (var != NULL)
set_config_option("client_encoding", var, context,
PGC_S_ENV_VAR, false, true);
success = true;
cleanup_list:
free(in_conffile);
free_name_value_list(head);
if (!success)
set_config_option("custom_variable_classes",
custom_variable_classes_backup,
context, PGC_S_FILE, false, true);
if (custom_variable_classes_backup)
{
pfree(custom_variable_classes_backup);
custom_variable_classes_backup = NULL;
}
}
......@@ -312,14 +508,14 @@ ParseConfigFile(const char *config_file, const char *calling_file,
{
pfree(opt_name);
pfree(opt_value);
/* we assume error message was logged already */
/* We assume the error message was logged already. */
OK = false;
goto cleanup_exit;
}
pfree(opt_name);
pfree(opt_value);
}
else
if (pg_strcasecmp(opt_name, "include") != 0)
{
/* append to list */
struct name_value_pair *item;
......
This diff is collapsed.
......@@ -7,7 +7,7 @@
*
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.30 2007/01/05 22:19:59 momjian Exp $
* $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.31 2007/03/12 22:09:28 petere Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -154,11 +154,12 @@ struct config_bool
/* these fields must be set correctly in initial value: */
/* (all but reset_val are constants) */
bool *variable;
bool reset_val;
bool boot_val;
GucBoolAssignHook assign_hook;
GucShowHook show_hook;
/* variable fields, initialized at runtime: */
bool tentative_val;
bool reset_val;
};
struct config_int
......@@ -167,13 +168,14 @@ struct config_int
/* these fields must be set correctly in initial value: */
/* (all but reset_val are constants) */
int *variable;
int reset_val;
int boot_val;
int min;
int max;
GucIntAssignHook assign_hook;
GucShowHook show_hook;
/* variable fields, initialized at runtime: */
int tentative_val;
int reset_val;
};
struct config_real
......@@ -182,13 +184,14 @@ struct config_real
/* these fields must be set correctly in initial value: */
/* (all but reset_val are constants) */
double *variable;
double reset_val;
double boot_val;
double min;
double max;
GucRealAssignHook assign_hook;
GucShowHook show_hook;
/* variable fields, initialized at runtime: */
double tentative_val;
double reset_val;
};
struct config_string
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment