Re: GUC assign hooks (was Re: wal_buffers = -1 and SIGHUP) - Mailing list pgsql-hackers
From | Tom Lane |
---|---|
Subject | Re: GUC assign hooks (was Re: wal_buffers = -1 and SIGHUP) |
Date | |
Msg-id | 5291.1301950665@sss.pgh.pa.us Whole thread Raw |
In response to | Re: GUC assign hooks (was Re: wal_buffers = -1 and SIGHUP) (Robert Haas <robertmhaas@gmail.com>) |
Responses |
Re: GUC assign hooks (was Re: wal_buffers = -1 and SIGHUP)
Re: GUC assign hooks (was Re: wal_buffers = -1 and SIGHUP) |
List | pgsql-hackers |
Robert Haas <robertmhaas@gmail.com> writes: > OK. Please comment the crap out of whatever you do, or maybe even add > a README. This stuff is just a bit arcane, and guideposts help a lot. We already have a README for that ;-). PFA, a patch to src/backend/utils/misc/README describing the proposed revised API. If nobody has any objections, I'll get on with making this happen. regards, tom lane diff --git a/src/backend/utils/misc/README b/src/backend/utils/misc/README index 881862a30b182a94cd71c6ed1a98dd6e6d5e51e0..221f595f8b72eb1cf48d318beb4aa8d3cb2b3411 100644 *** a/src/backend/utils/misc/README --- b/src/backend/utils/misc/README *************** determining which setting is used. *** 12,68 **** 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) --- 12,108 ---- Per-Variable Hooks ------------------ ! Each variable known to GUC can optionally have a check_hook, an ! assign_hook, and/or a show_hook to provide customized behavior. ! Check hooks are used to perform validity checking on variable values ! (above and beyond what GUC can do), to compute derived settings when ! nontrivial work is needed to do that, and optionally to "canonicalize" ! user-supplied values. Assign hooks are 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 a check_hook is provided, it points to a function of the signature ! bool check_hook(datatype *newvalue, void **extra, GucSource source) ! The "newvalue" argument is of type bool *, int *, double *, or char ** ! for bool, int/enum, float, or string variables respectively. The check ! function should validate the proposed new value, and return true if it is ! OK or false if not. The function can optionally do a few other things: ! ! * When rejecting a bad proposed value, it may be useful to append some ! additional information to the generic "invalid value for option FOO" ! complaint that guc.c will emit. To do that, call ! void GUC_check_errdetail(const char *format, ...) ! where the format string and additional arguments follow the rules for ! errdetail() arguments. The resulting string will be emitted as the ! DETAIL line of guc.c's error report, so it should follow the message style ! guidelines for DETAIL messages. In general, check_hooks should avoid ! throwing errors directly if possible, though this may be difficult to ! avoid for some corner cases such as out-of-memory. ! ! * Since the newvalue is pass-by-reference, the function can modify it. ! This might be used for example to canonicalize the spelling of a string ! value, round off a buffer size to the nearest supported value, or replace ! a special value such as "-1" with a computed default value. If the ! function wishes to replace a string value, it must malloc (not palloc) ! the replacement value, and be sure to free() the previous value. ! ! * Derived information, such as the role OID represented by a user name, ! can be stored for use by the assign hook. To do this, malloc (not palloc) ! storage space for the information, and return its address at *extra. ! guc.c will automatically free() this space when the associated GUC setting ! is no longer of interest. *extra is initialized to NULL before call, so ! it can be ignored if not needed. ! ! The "source" argument indicates the source of the proposed new value, ! If it is >= PGC_S_INTERACTIVE, then we are performing an interactive ! assignment (e.g., a SET command). But when source < PGC_S_INTERACTIVE, ! we are reading a non-interactive option source, such as postgresql.conf. ! This is sometimes needed to determine whether a setting should be ! allowed. The check_hook might also look at the current actual value of ! the variable to determine what is allowed. ! ! Note that check hooks are sometimes called just to validate a value, ! without any intention of actually changing the setting. Therefore the ! check hook must *not* take any action based on the assumption that an ! assignment will occur. ! If an assign_hook is provided, it points to a function of the signature ! bool assign_hook(datatype newvalue, void *extra) ! where the type of "newvalue" matches the kind of variable, and "extra" ! is the derived-information pointer returned by the check_hook (always ! NULL if there is no check_hook). 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, for example to avoid doing work when ! the value isn't really changing). If the function returns "true" then ! the assignment is completed; if it returns "false" then the assignment ! fails and the variable value is not changed. ! IMPORTANT: assign_hooks should never fail except under the most dire ! circumstances (such as out-of-memory), since a failure may for example ! result in a GUC setting not being rolled back during transaction abort. ! In general, try to do anything that could conceivably fail in a check_hook ! instead, and pass along the results in an "extra" struct, so that the ! assign hook has little to do beyond copying the data to someplace. This ! applies particularly to catalog lookups: any required lookups should be ! done in the check_hook, since the assign_hook may be executed during ! transaction rollback when lookups will be unsafe. ! Note that check_hooks are sometimes called outside any transaction, too. ! This happens when processing the wired-in "bootstrap" value, values coming ! from the postmaster command line or environment, or values coming from ! postgresql.conf. Therefore, any catalog lookups done in a check_hook ! should be guarded with an IsTransactionState() test, and there must be a ! fallback path to allow derived values to be computed during the first ! subsequent use of the GUC setting within a transaction. Typically, ! catalog values computed by the check_hook and installed by the assign_hook ! are used only for the remainder of the transaction in which the new ! setting is made. Each subsequent transaction looks up the values afresh ! on first use. This arrangement is useful to prevent use of stale catalog ! values, independently of the problem of needing to check GUC values ! outside a transaction. If a show_hook is provided, it points to a function of the signature const char *show_hook(void) *************** currently a different interactive value *** 202,226 **** 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. --- 242,264 ---- 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. ! GUC Memory Handling ! ------------------- ! String option values are allocated with malloc/strdup, not with the ! palloc/pstrdup mechanisms. We would need to keep them in a permanent ! context anyway, and malloc 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 malloc during transaction commit/abort, so cannot cause an out-of-memory failure there. + + "Extra" structs returned by check_hook routines are managed in the same + way as string values. Note that we support "extra" structs for all types + of GUC variables, although they are mainly useful with strings.
pgsql-hackers by date: