227 lines
10 KiB
Plaintext
227 lines
10 KiB
Plaintext
$PostgreSQL: pgsql/src/backend/utils/misc/README,v 1.10 2008/03/20 17:55:15 momjian Exp $
|
|
|
|
Guc Implementation Notes
|
|
========================
|
|
|
|
The GUC (Grand Unified Configuration) module implements configuration
|
|
variables of multiple types (currently boolean, enum, int, float, and string).
|
|
Variable settings can come from various places, with a priority ordering
|
|
determining which setting is used.
|
|
|
|
|
|
Per-Variable Hooks
|
|
------------------
|
|
|
|
Each variable known to GUC can optionally have an assign_hook and/or
|
|
a show_hook to provide customized behavior. Assign hooks are used to
|
|
perform validity checking on variable values (above and beyond what
|
|
GUC can do). They are also used to update any derived state that needs
|
|
to change when a GUC variable is set. Show hooks are used to modify
|
|
the default SHOW display for a variable.
|
|
|
|
If an assign_hook is provided, it points to a function of the signature
|
|
bool assign_hook(newvalue, bool doit, GucSource source)
|
|
where the type of "newvalue" matches the kind of variable. This function
|
|
is called immediately before actually setting the variable's value (so it
|
|
can look at the actual variable to determine the old value). If the
|
|
function returns "true" then the assignment is completed; if it returns
|
|
"false" then newvalue is considered invalid and the assignment is not
|
|
performed. If "doit" is false then the function should simply check
|
|
validity of newvalue and not change any derived state. The "source" parameter
|
|
indicates where the new value came from. If it is >= PGC_S_INTERACTIVE,
|
|
then we are performing an interactive assignment (e.g., a SET command), and
|
|
ereport(ERROR) is safe to do. But when source < PGC_S_INTERACTIVE, we are
|
|
reading a non-interactive option source, such as postgresql.conf. In this
|
|
case the assign_hook should *not* ereport but should just return false if it
|
|
doesn't like the newvalue.
|
|
|
|
If an assign_hook returns false then guc.c will report a generic "invalid
|
|
value for option FOO" error message. If you feel the need to provide a more
|
|
specific error message, ereport() it using "GUC_complaint_elevel(source)"
|
|
as the error level. Note that this might return either ERROR or a lower level
|
|
such as LOG, so the ereport call might or might not return. If it does
|
|
return, return false out of the assign_hook.
|
|
|
|
For string variables, the signature for assign hooks is a bit different:
|
|
const char *assign_hook(const char *newvalue,
|
|
bool doit,
|
|
GucSource source)
|
|
The meanings of the parameters are the same as for the other types of GUC
|
|
variables, but the return value is handled differently:
|
|
NULL --- assignment fails (like returning false for other datatypes)
|
|
newvalue --- assignment succeeds, assign the newvalue as-is
|
|
malloc'd (not palloc'd!!!) string --- assign that value instead
|
|
The third choice is allowed in case the assign_hook wants to return a
|
|
"canonical" version of the new value. For example, the assign_hook for
|
|
datestyle always returns a string that includes both output and input
|
|
datestyle options, although the input might have specified only one.
|
|
|
|
Note that a string variable's assign_hook will NEVER be called with a NULL
|
|
value for newvalue, since there would be no way to distinguish success
|
|
and failure returns. If the boot_val or reset_val for a string variable
|
|
is NULL, it will just be assigned without calling the assign_hook.
|
|
Therefore, a NULL boot_val should never be used in combination with an
|
|
assign_hook that has side-effects, as the side-effects wouldn't happen
|
|
during a RESET that re-institutes the boot-time setting.
|
|
|
|
If a show_hook is provided, it points to a function of the signature
|
|
const char *show_hook(void)
|
|
This hook allows variable-specific computation of the value displayed
|
|
by SHOW.
|
|
|
|
|
|
Saving/Restoring Guc Variable Values
|
|
------------------------------------
|
|
|
|
Prior values of configuration variables must be remembered in order to deal
|
|
with several special cases: RESET (a/k/a SET TO DEFAULT), rollback of SET
|
|
on transaction abort, rollback of SET LOCAL at transaction end (either
|
|
commit or abort), and save/restore around a function that has a SET option.
|
|
RESET is defined as selecting the value that would be effective had there
|
|
never been any SET commands in the current session.
|
|
|
|
To handle these cases we must keep track of many distinct values for each
|
|
variable. The primary values are:
|
|
|
|
* actual variable contents always the current effective value
|
|
|
|
* reset_val the value to use for RESET
|
|
|
|
(Each GUC entry also has a boot_val which is the wired-in default value.
|
|
This is assigned to the reset_val and the actual variable during
|
|
InitializeGUCOptions(). The boot_val is also consulted to restore the
|
|
correct reset_val if SIGHUP processing discovers that a variable formerly
|
|
specified in postgresql.conf is no longer set there.)
|
|
|
|
In addition to the primary values, there is a stack of former effective
|
|
values that might need to be restored in future. Stacking and unstacking
|
|
is controlled by the GUC "nest level", which is zero when outside any
|
|
transaction, one at top transaction level, and incremented for each
|
|
open subtransaction or function call with a SET option. A stack entry
|
|
is made whenever a GUC variable is first modified at a given nesting level.
|
|
(Note: the reset_val need not be stacked because it is only changed by
|
|
non-transactional operations.)
|
|
|
|
A stack entry has a state, a prior value of the GUC variable, a remembered
|
|
source of that prior value, and depending on the state may also have a
|
|
"masked" value. The masked value is needed when SET followed by SET LOCAL
|
|
occur at the same nest level: the SET's value is masked but must be
|
|
remembered to restore after transaction commit.
|
|
|
|
During initialization we set the actual value and reset_val based on
|
|
whichever non-interactive source has the highest priority. They will
|
|
have the same value.
|
|
|
|
The possible transactional operations on a GUC value are:
|
|
|
|
Entry to a function with a SET option:
|
|
|
|
Push a stack entry with the prior variable value and state SAVE,
|
|
then set the variable.
|
|
|
|
Plain SET command:
|
|
|
|
If no stack entry of current level:
|
|
Push new stack entry w/prior value and state SET
|
|
else if stack entry's state is SAVE, SET, or LOCAL:
|
|
change stack state to SET, don't change saved value
|
|
(here we are forgetting effects of prior set action)
|
|
else (entry must have state SET+LOCAL):
|
|
discard its masked value, change state to SET
|
|
(here we are forgetting effects of prior SET and SET LOCAL)
|
|
Now set new value.
|
|
|
|
SET LOCAL command:
|
|
|
|
If no stack entry of current level:
|
|
Push new stack entry w/prior value and state LOCAL
|
|
else if stack entry's state is SAVE or LOCAL or SET+LOCAL:
|
|
no change to stack entry
|
|
(in SAVE case, SET LOCAL will be forgotten at func exit)
|
|
else (entry must have state SET):
|
|
put current active into its masked slot, set state SET+LOCAL
|
|
Now set new value.
|
|
|
|
Transaction or subtransaction abort:
|
|
|
|
Pop stack entries, restoring prior value, until top < subxact depth
|
|
|
|
Transaction or subtransaction commit (incl. successful function exit):
|
|
|
|
While stack entry level >= subxact depth
|
|
|
|
if entry's state is SAVE:
|
|
pop, restoring prior value
|
|
else if level is 1 and entry's state is SET+LOCAL:
|
|
pop, restoring *masked* value
|
|
else if level is 1 and entry's state is SET:
|
|
pop, discarding old value
|
|
else if level is 1 and entry's state is LOCAL:
|
|
pop, restoring prior value
|
|
else if there is no entry of exactly level N-1:
|
|
decrement entry's level, no other state change
|
|
else
|
|
merge entries of level N-1 and N as specified below
|
|
|
|
The merged entry will have level N-1 and prior = older prior, so easiest
|
|
to keep older entry and free newer. There are 12 possibilities since
|
|
we already handled level N state = SAVE:
|
|
|
|
N-1 N
|
|
|
|
SAVE SET discard top prior, set state SET
|
|
SAVE LOCAL discard top prior, no change to stack entry
|
|
SAVE SET+LOCAL discard top prior, copy masked, state S+L
|
|
|
|
SET SET discard top prior, no change to stack entry
|
|
SET LOCAL copy top prior to masked, state S+L
|
|
SET SET+LOCAL discard top prior, copy masked, state S+L
|
|
|
|
LOCAL SET discard top prior, set state SET
|
|
LOCAL LOCAL discard top prior, no change to stack entry
|
|
LOCAL SET+LOCAL discard top prior, copy masked, state S+L
|
|
|
|
SET+LOCAL SET discard top prior and second masked, state SET
|
|
SET+LOCAL LOCAL discard top prior, no change to stack entry
|
|
SET+LOCAL SET+LOCAL discard top prior, copy masked, state S+L
|
|
|
|
|
|
RESET is executed like a SET, but using the reset_val as the desired new
|
|
value. (We do not provide a RESET LOCAL command, but SET LOCAL TO DEFAULT
|
|
has the same behavior that RESET LOCAL would.) The source associated with
|
|
the reset_val also becomes associated with the actual value.
|
|
|
|
If SIGHUP is received, the GUC code rereads the postgresql.conf
|
|
configuration file (this does not happen in the signal handler, but at
|
|
next return to main loop; note that it can be executed while within a
|
|
transaction). New values from postgresql.conf are assigned to actual
|
|
variable, reset_val, and stacked actual values, but only if each of
|
|
these has a current source priority <= PGC_S_FILE. (It is thus possible
|
|
for reset_val to track the config-file setting even if there is
|
|
currently a different interactive value of the actual variable.)
|
|
|
|
The assign_hook and show_hook routines work only with the actual variable,
|
|
and are not directly aware of the additional values maintained by GUC.
|
|
This is not a problem for normal usage, since we can assign first to the
|
|
actual variable and then (if that succeeds) to the additional values as
|
|
needed. However, for SIGHUP rereads we may not want to assign to the
|
|
actual variable. Our procedure in that case is to call the assign_hook
|
|
with doit = false so that the value is validated, but no derived state is
|
|
changed.
|
|
|
|
|
|
String Memory Handling
|
|
----------------------
|
|
|
|
String option values are allocated with strdup, not with the
|
|
pstrdup/palloc mechanisms. We would need to keep them in a permanent
|
|
context anyway, and strdup gives us more control over handling
|
|
out-of-memory failures.
|
|
|
|
We allow a string variable's actual value, reset_val, boot_val, and stacked
|
|
values to point at the same storage. This makes it slightly harder to free
|
|
space (we must test whether a value to be freed isn't equal to any of the
|
|
other pointers in the GUC entry or associated stack items). The main
|
|
advantage is that we never need to strdup during transaction commit/abort,
|
|
so cannot cause an out-of-memory failure there.
|