| $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. |