|
NAMEapp_config —
application configuration system
LIBRARYPDEL Library (libpdel, -lpdel)SYNOPSIS#include <sys/types.h>
#include
<pdel/config/app_config.h>
struct app_config_ctx *
int
void *
int
int
void *
int
void *
const struct structs_type *
void *
void
extern const struct app_subsystem
app_config_alog_subsystem;
DESCRIPTIONThese functions implement an application configuration framework.Application modelTheapp_config model assumes that the application's
configuration is stored in a single configuration object,
which can be any data structure that is describable by a
structs(3)
type. The configuration can be stored in an XML file which is automatically
updated.
The application itself consists of one or more subsystems. A subsystem is an abstract activity that can be started or stopped and whose behavior depends on (some part of) the configuration object. When the configuration object is changed, those subsystems that require it are automatically stopped and then restarted with the new configuration. The application may provide methods for:
Each subsystem may provide methods for:
In the steady state, there is a single currently active configuration object. Only those subsystems that are supposed to be running are. All running subsystems are running with their configurations based on (i.e., consistent with) the active configuration object. When there needs to be a configuration change, a new configuration
object is constructed and the The SubsystemsA subsystem is defined as anything that can be started and/or stopped. A subsystem typically depends on some portion of the configuration object such that it must be stopped and restarted when that portion changes.A subsystem is defined by a struct app_subsystem { const char *name; /* name, null to end list */ void *arg; /* opaque subsystem argument */ app_ss_startup_t *start; /* start subsystem */ app_ss_shutdown_t *stop; /* stop subsystem */ app_ss_willrun_t *willrun; /* will subsystem run? */ app_ss_changed_t *changed; /* subsystem config changed? */ const char **deplist; /* config items dependent on */ }; The name is currently used only for
debugging, but must be typedef int app_ss_startup_t(struct app_config_ctx *ctx, const struct app_subsystem *ss, const void *config); typedef void app_ss_shutdown_t(struct app_config_ctx *ctx, const struct app_subsystem *ss, const void *config); typedef int app_ss_willrun_t(struct app_config_ctx *ctx, const struct app_subsystem *ss, const void *config); typedef int app_ss_changed_t(struct app_config_ctx *ctx, const struct app_subsystem *ss, const void *config1, const void *config2);
In the above methods, the configuration object argument(s) become invalid after the method returns. Alternately, or in conjunction with the
All four of the above subsystem methods are optional and may be
specified as ApplicationAn application itself is described by astruct
app_config :
struct app_config { u_int version; /* current version # */ const struct structs_type **types; /* all version types */ const struct app_subsystem **slist; /* list of subsystems */ app_config_init_t *init; /* initialize defaults */ app_config_getnew_t *getnew; /* generate new config */ app_config_checker_t *checker; /* validate a config */ app_config_normalize_t *normalize; /* normalize a config */ app_config_upgrade_t *upgrade; /* upgrade a config */ }; The list of subsystems supported by the application is pointed to
by slist. This list must be terminated with an entry
whose name is Subsystems are always started in the order they are listed in slist, and they are always shutdown in the reverse order. The version is the configuration object
version number (the first version is zero), and types
points to an array of version + 1 pointers to
structs(3)
types for the configuration object, where The remaining fields are pointers to functions having these types: typedef int app_config_init_t(struct app_config_ctx *ctx, void *config); typedef int app_config_getnew_t(struct app_config_ctx *ctx, void *config); typedef int app_config_checker_t(struct app_config_ctx *ctx, const void *config, char *errbuf, size_t ebufsize); typedef void app_config_normalize_t(struct app_config_ctx *ctx, void *config); typedef int app_config_upgrade_t(struct app_config_ctx *ctx, const void *old_conf, u_int old_version, void *new_conf); If the default configuration object is not equal to what is
provided by
structs_init(3),
then
The distinction between
All configurations that are applied by
Note: the configurations returned by
A quick and dirty way to do this when most of the fields are the same is to use structs_traverse(3) to list the fields in the old configuration object, structs_get_string(3) to get their ASCII values, and structs_set_string(3) to set the same values in the new configuration object. APIapp_config_init () should be called at application
startup time to initialize app_config for the
application described by info. A
pevent(3)
context ctx must be supplied.
app_config_init () returns an application context, with
which all configuration and subsystems are associated. Multiple independent
application contexts may exist at the same time. The
cookie is saved along with the context but is otherwise
ignored.
Upon return from
If the file contains an old version of the configuration object, it is automatically upgraded to the current version. If allow_writeback is non-zero, then path is remembered and the file is updated (i.e., rewritten) every time the application configuration object changes. Updates are done atomically by creating a temporary file with the suffix ".new" and renaming it (see rename(2)). In theory, one call to
If config is The new configuration (or shutdown) takes effect after a delay of
delay milliseconds after
Pre-defined subsystemsTheapp_config library comes with some predefined
subsystem templates.
app_config_alog_subsystem handles
configuring error logging for an application. To use
app_config_alog_subsystem, copy the structure and set
the arg field to point to a struct app_config_alog_info { const char *name; /* field name */ int channel; /* alog channel */ }; The name should be the
structs(3)
field name of the field in the configuration object that configures logging
for the
alog(3)
logging channel channel. This field should be a
app_config_curconf_subsystem is useful when
the application needs efficient access to the currently active
configuration. This subsystem assumes that there is a global pointer
variable (call it curconf) which by definition always
points to a read-only copy of the currently active configuration. For
example, if the application's configuration object is a
const struct my_config *const curconf; Then the function of
app_config_curconf_subsystem is to automatically keep
this variable up to date. (The To use app_config_curconf_subsystem, copy the structure and set the arg field to point to the application's curconf pointer variable. Typically the app_config_curconf_subsystem will be first in the list of subsystems, so that curconf is always updated before any other subsystem starts. Then at any time *curconf can be examined for the currently active configuration. app_config_directory_subsystem handles configuring the current working directory for the process. To use app_config_directory_subsystem, copy the structure and set the arg field to point to a string containing the structs(3) name of the field in the configuration object that contains the directory name. If this name is not the empty string, then the current working directory will be set according to the value of this field. app_config_pidfile_subsystem handles "PID files", i.e., exclusive application lock files into which the process ID is written. These guard against two instances of the same application running at the same time. To use app_config_pidfile_subsystem, copy the structure and set the arg field to point to a string containing the structs(3) name of the field in the configuration object that contains the PID file pathname. RETURN VALUESAll of theapp_config functions return
NULL or -1 to indicate an error and set
errno appropriately.
SEE ALSOalog(3), libpdel(3), pevent(3), structs(3), typed_mem(3)HISTORYThe PDEL library was developed at Packet Design, LLC.http://www.packetdesign.com/
AUTHORSArchie Cobbs ⟨archie@freebsd.org⟩BUGSThere should be explicit support for subsystems that require other subsystems to be running before they may run. As it stands now, such dependencies must be implicitly encoded into thewillrun () and
changed () methods. Even so, the dependent subsystem
cannot detect if the other subsystem fails to start.
Subsystems should be defined more like objects using dynamically allocated structures that can be added and removed from the subsystem list at any time, without having to shutdown and restart the whole application. It should be possible to start and shutdown subsystems individually.
Visit the GSP FreeBSD Man Page Interface. |