Annotation of embedaddon/libpdel/config/app_config.3, revision 1.1
1.1 ! misho 1: .\" Copyright (c) 2001-2002 Packet Design, LLC.
! 2: .\" All rights reserved.
! 3: .\"
! 4: .\" Subject to the following obligations and disclaimer of warranty,
! 5: .\" use and redistribution of this software, in source or object code
! 6: .\" forms, with or without modifications are expressly permitted by
! 7: .\" Packet Design; provided, however, that:
! 8: .\"
! 9: .\" (i) Any and all reproductions of the source or object code
! 10: .\" must include the copyright notice above and the following
! 11: .\" disclaimer of warranties; and
! 12: .\" (ii) No rights are granted, in any manner or form, to use
! 13: .\" Packet Design trademarks, including the mark "PACKET DESIGN"
! 14: .\" on advertising, endorsements, or otherwise except as such
! 15: .\" appears in the above copyright notice or in the software.
! 16: .\"
! 17: .\" THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
! 18: .\" TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
! 19: .\" REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
! 20: .\" THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
! 21: .\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
! 22: .\" OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
! 23: .\" OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
! 24: .\" OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
! 25: .\" RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
! 26: .\" LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
! 27: .\" OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
! 28: .\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
! 29: .\" DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
! 30: .\" USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
! 31: .\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 32: .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
! 33: .\" THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
! 34: .\" THE POSSIBILITY OF SUCH DAMAGE.
! 35: .\"
! 36: .\" Author: Archie Cobbs <archie@freebsd.org>
! 37: .\"
! 38: .\" $Id: app_config.3,v 1.12 2004/06/02 17:24:36 archie Exp $
! 39: .\"
! 40: .Dd April 22, 2002
! 41: .Dt APP_CONFIG 3
! 42: .Os
! 43: .Sh NAME
! 44: .Nm app_config
! 45: .Nd application configuration system
! 46: .Sh LIBRARY
! 47: PDEL Library (libpdel, \-lpdel)
! 48: .Sh SYNOPSIS
! 49: .In sys/types.h
! 50: .In pdel/config/app_config.h
! 51: .Ft "struct app_config_ctx *"
! 52: .Fn app_config_init "struct pevent_ctx *ctx" "const struct app_config *info" "void *cookie"
! 53: .Ft int
! 54: .Fn app_config_uninit "struct app_config_ctx **ctxp"
! 55: .Ft "void *"
! 56: .Fn app_config_get_cookie "struct app_config_ctx *ctx"
! 57: .Ft int
! 58: .Fn app_config_load "struct app_config_ctx *ctx" "const char *path" "int allow_writeback"
! 59: .Ft int
! 60: .Fn app_config_reload "struct app_config_ctx *ctx"
! 61: .Ft "void *"
! 62: .Fn app_config_new "struct app_config_ctx *ctx"
! 63: .Ft int
! 64: .Fn app_config_set "struct app_config_ctx *ctx" "const void *config" "u_long delay" "char *ebuf" "int emax"
! 65: .Ft "void *"
! 66: .Fn app_config_get "struct app_config_ctx *ctx" "int pending"
! 67: .Ft "const struct structs_type *"
! 68: .Fn app_config_get_type "struct app_config_ctx *ctx"
! 69: .Ft "void *"
! 70: .Fn app_config_copy "struct app_config_ctx *ctx" "const void *config"
! 71: .Ft void
! 72: .Fn app_config_free "struct app_config_ctx *ctx" "void **configp"
! 73: .Vt extern const struct app_subsystem app_config_alog_subsystem ;
! 74: .Vt extern const struct app_subsystem app_config_curconf_subsystem ;
! 75: .Vt extern const struct app_subsystem app_config_directory_subsystem ;
! 76: .Vt extern const struct app_subsystem app_config_pidfile_subsystem ;
! 77: .Sh DESCRIPTION
! 78: These functions implement an application configuration framework.
! 79: .\"
! 80: .Ss Application model
! 81: .\"
! 82: The
! 83: .Nm app_config
! 84: model assumes that the application's configuration is stored in a single
! 85: .Em "configuration object" ,
! 86: which can be any data structure that is describable by a
! 87: .Xr structs 3
! 88: type.
! 89: The configuration can be stored in an XML file which is automatically updated.
! 90: .Pp
! 91: The application itself consists of one or more
! 92: .Em subsystems .
! 93: A subsystem is an abstract activity that can be started or stopped and
! 94: whose behavior depends on (some part of) the configuration object.
! 95: When the configuration object is changed, those subsystems that
! 96: require it are automatically stopped and then restarted with the new
! 97: configuration.
! 98: .Pp
! 99: The application may provide methods for:
! 100: .Pp
! 101: .Bl -bullet -compact -offset 3n
! 102: .It
! 103: Creating a new, default configuration object
! 104: .It
! 105: Initializing a new configuration object for the current system
! 106: .It
! 107: Checking a configuration object for overall validity
! 108: .It
! 109: Normalizing a configuration object
! 110: .It
! 111: Upgrading a configuration object from an old version
! 112: .El
! 113: .Pp
! 114: Each subsystem may provide methods for:
! 115: .Pp
! 116: .Bl -bullet -compact -offset 3n
! 117: .It
! 118: Starting the subsystem
! 119: .It
! 120: Stopping the subsystem
! 121: .It
! 122: Determining if the subsystem will run
! 123: .It
! 124: Determining if the subsystem needs to be restarted
! 125: .El
! 126: .Pp
! 127: In the steady state, there is a single currently active configuration object.
! 128: Only those subsystems that are supposed to be running are.
! 129: All running subsystems are running with their configurations based on
! 130: (i.e., consistent with) the active configuration object.
! 131: .Pp
! 132: When there needs to be a configuration change, a new configuration object
! 133: is constructed and the
! 134: .Nm app_config
! 135: library is told to apply the new configuration object.
! 136: After a configurable delay (for hysteresis), those subsystems affected
! 137: by the change are stopped, the new configuration object is installed
! 138: in place of the old one, and the stopped subsystems are restarted.
! 139: .Pp
! 140: The
! 141: .Nm app_config
! 142: library guarantees that only "valid" configurations may be applied,
! 143: where the meaning of "valid" is determined by the application.
! 144: .\"
! 145: .Ss Subsystems
! 146: .\"
! 147: A subsystem is defined as anything that can be started and/or stopped.
! 148: A subsystem typically depends on some portion of the configuration
! 149: object such that it must be stopped and restarted when that portion changes.
! 150: .Pp
! 151: A subsystem is defined by a
! 152: .Li "struct app_subsystem" :
! 153: .Pp
! 154: .Bd -literal -compact -offset 3n
! 155: struct app_subsystem {
! 156: const char *name; /* name, null to end list */
! 157: void *arg; /* opaque subsystem argument */
! 158: app_ss_startup_t *start; /* start subsystem */
! 159: app_ss_shutdown_t *stop; /* stop subsystem */
! 160: app_ss_willrun_t *willrun; /* will subsystem run? */
! 161: app_ss_changed_t *changed; /* subsystem config changed? */
! 162: const char **deplist; /* config items dependent on */
! 163: };
! 164: .Ed
! 165: .Pp
! 166: The
! 167: .Fa name
! 168: is currently used only for debugging, but must be
! 169: .Dv NULL
! 170: to terminate the list of subsystems (see below).
! 171: The
! 172: .Fa arg
! 173: is ignored and is for the application's private use.
! 174: The
! 175: .Fa start ,
! 176: .Fa stop ,
! 177: .Fa willrun ,
! 178: and
! 179: .Fa changed
! 180: fields must be pointers to functions having these types:
! 181: .Pp
! 182: .Bd -literal -compact -offset 3n
! 183: typedef int app_ss_startup_t(struct app_config_ctx *ctx,
! 184: const struct app_subsystem *ss, const void *config);
! 185: typedef void app_ss_shutdown_t(struct app_config_ctx *ctx,
! 186: const struct app_subsystem *ss, const void *config);
! 187: typedef int app_ss_willrun_t(struct app_config_ctx *ctx,
! 188: const struct app_subsystem *ss, const void *config);
! 189: typedef int app_ss_changed_t(struct app_config_ctx *ctx,
! 190: const struct app_subsystem *ss,
! 191: const void *config1, const void *config2);
! 192: .Ed
! 193: .Pp
! 194: .Fn start
! 195: starts the subsystem;
! 196: .Fa config
! 197: points to a copy of the current (i.e., new) configuration object.
! 198: .Fn start
! 199: should return zero if successful, or else -1 with
! 200: .Va errno
! 201: set on failure.
! 202: In the latter case, the
! 203: .Fn stop
! 204: method will not be called.
! 205: .Pp
! 206: .Fn stop
! 207: stops the subsystem;
! 208: .Fa config
! 209: points to a copy of the current configuration object.
! 210: .Pp
! 211: .Fn willrun
! 212: should return non-zero if the subsystem needs to run at all.
! 213: .Fa config
! 214: points to a copy of the current (i.e., new) configuration object.
! 215: .Pp
! 216: .Fn changed
! 217: determines if the subsystem needs to be restarted during a configuration
! 218: change from
! 219: .Fa config1
! 220: to
! 221: .Fa config2 .
! 222: It should return 1 if so, zero otherwise.
! 223: .Pp
! 224: In the above methods, the configuration object argument(s)
! 225: become invalid after the method returns.
! 226: .Pp
! 227: Alternately, or in conjunction with the
! 228: .Fn changed
! 229: method, the
! 230: .Fa deplist
! 231: may point to a
! 232: .Dv NULL
! 233: terminated list of
! 234: .Xr structs 3
! 235: names of fields in the configuration object on which this subsystem depends.
! 236: The subsystem will automatically be restarted if any of the named fields
! 237: differ between
! 238: .Fa config1
! 239: and
! 240: .Fa config2 ,
! 241: as determined by
! 242: .Xr structs_equal 3 .
! 243: .Pp
! 244: All four of the above subsystem methods are optional and may be specified as
! 245: .Dv NULL .
! 246: In the case of
! 247: .Fn startup
! 248: and
! 249: .Fn shutdown ,
! 250: .Dv NULL
! 251: means "do nothing".
! 252: .Fn willrun
! 253: being
! 254: .Dv NULL
! 255: is equivalent to it always returning 1.
! 256: .Fn changed
! 257: being
! 258: .Dv NULL
! 259: is equivalent to it always returning 0.
! 260: .Fa deplist
! 261: being
! 262: .Dv NULL
! 263: is equivalent to an empty list.
! 264: .\"
! 265: .Ss Application
! 266: .\"
! 267: An application itself is described by a
! 268: .Li "struct app_config" :
! 269: .Pp
! 270: .Bd -literal -compact -offset 3n
! 271: struct app_config {
! 272: u_int version; /* current version # */
! 273: const struct structs_type **types; /* all version types */
! 274: const struct app_subsystem **slist; /* list of subsystems */
! 275: app_config_init_t *init; /* initialize defaults */
! 276: app_config_getnew_t *getnew; /* generate new config */
! 277: app_config_checker_t *checker; /* validate a config */
! 278: app_config_normalize_t *normalize; /* normalize a config */
! 279: app_config_upgrade_t *upgrade; /* upgrade a config */
! 280: };
! 281: .Ed
! 282: .Pp
! 283: The list of subsystems supported by the application is pointed to by
! 284: .Fa slist .
! 285: This list must be terminated with an entry whose
! 286: .Fa name
! 287: is
! 288: .Dv NULL .
! 289: .Pp
! 290: Subsystems are always started in the order they are listed in
! 291: .Fa slist ,
! 292: and they are always shutdown in the reverse order.
! 293: .Pp
! 294: The
! 295: .Fa version
! 296: is the configuration object version number (the first version is zero), and
! 297: .Fa types
! 298: points to an array of
! 299: .Fa "version"
! 300: + 1 pointers to
! 301: .Xr structs 3
! 302: types for the configuration object, where
! 303: .Li "types[i]"
! 304: is the
! 305: .Xr structs 3
! 306: type for version
! 307: .Fa i
! 308: of the configuration object.
! 309: .Pp
! 310: The remaining fields are pointers to functions having these types:
! 311: .Pp
! 312: .Bd -literal -compact -offset 3n
! 313: typedef int app_config_init_t(struct app_config_ctx *ctx,
! 314: void *config);
! 315: typedef int app_config_getnew_t(struct app_config_ctx *ctx,
! 316: void *config);
! 317: typedef int app_config_checker_t(struct app_config_ctx *ctx,
! 318: const void *config, char *errbuf, size_t ebufsize);
! 319: typedef void app_config_normalize_t(struct app_config_ctx *ctx,
! 320: void *config);
! 321: typedef int app_config_upgrade_t(struct app_config_ctx *ctx,
! 322: const void *old_conf, u_int old_version,
! 323: void *new_conf);
! 324: .Ed
! 325: .Pp
! 326: If the default configuration object is not equal to what is provided by
! 327: .Xr structs_init 3 ,
! 328: then
! 329: .Fn init
! 330: may be implemented.
! 331: It should further modify the
! 332: .Fa config
! 333: as appropriate to get the generic default configuration.
! 334: .Fn init
! 335: returns zero on success, or -1 on error with
! 336: .Va errno
! 337: set appropriately.
! 338: .Pp
! 339: .Fn getnew
! 340: is invoked when no existing configuration is found by
! 341: .Fn app_config_load
! 342: (see below).
! 343: The
! 344: .Fa config
! 345: is as returned by
! 346: .Fn init .
! 347: .Fn getnew
! 348: should apply any further initialization required for this particular system.
! 349: .Fn getnew
! 350: returns zero on success, or -1 on error with
! 351: .Va errno
! 352: set appropriately.
! 353: .Pp
! 354: The distinction between
! 355: .Fn init
! 356: and
! 357: .Fn getnew
! 358: is somewhat subtle:
! 359: .Fn init
! 360: simply initializes a new configuration object.
! 361: It may be invoked many times during the normal operation of the application
! 362: as configuration objects are needed.
! 363: .Fn getnew
! 364: is only invoked once, at the beginning of application startup, when there
! 365: is no previously saved configuration found.
! 366: Therefore, the behavior of
! 367: .Fn init
! 368: should not be affected by the "environment", while the behavior of
! 369: .Fn getnew
! 370: often is.
! 371: .Pp
! 372: .Fn checker
! 373: determines whether the
! 374: .Fa config
! 375: is valid, returning 1 if so or 0 if not.
! 376: In the latter case, it may print an error message (including '\\0')
! 377: into the buffer
! 378: .Fa errbuf ,
! 379: which has size
! 380: .Fa ebufsize
! 381: (see
! 382: .Xr snprintf 3) .
! 383: .Pp
! 384: .Fn normalize
! 385: gives the application a chance to normalize an otherwise valid
! 386: configuration object.
! 387: This is useful when the configuration object contains redundant information,
! 388: or information that can be represented in more than one way.
! 389: .Pp
! 390: All configurations that are applied by
! 391: .Nm app_config
! 392: are guaranteed to have been checked and normalized.
! 393: All configurations passed to
! 394: .Fn checker
! 395: are guaranteed to have been passed through
! 396: .Fn normalize
! 397: first.
! 398: .Pp
! 399: Note: the configurations returned by
! 400: .Fn init
! 401: and
! 402: .Fn getnew
! 403: must be valid according to
! 404: .Fa checker .
! 405: .Pp
! 406: .Fn upgrade
! 407: is invoked when an older version of the configuration object is read
! 408: in from an XML file.
! 409: The configuration version number is stored as the "version" attribute
! 410: of the XML document element.
! 411: .Fa old_conf
! 412: is the old object, which has version
! 413: .Fa old_version ,
! 414: and
! 415: .Fa new_conf
! 416: is a newly initialized configuration object of the current version.
! 417: .Fn upgrade
! 418: should copy the configuration information from
! 419: .Fa old_conf
! 420: to
! 421: .Fa new_conf .
! 422: .Pp
! 423: A quick and dirty way to do this when most of the fields are the same
! 424: is to use
! 425: .Xr structs_traverse 3
! 426: to list the fields in the old configuration object,
! 427: .Xr structs_get_string 3
! 428: to get their ASCII values, and
! 429: .Xr structs_set_string 3
! 430: to set the same values in the new configuration object.
! 431: .\"
! 432: .Ss API
! 433: .\"
! 434: .Fn app_config_init
! 435: should be called at application startup time to initialize
! 436: .Nm app_config
! 437: for the application described by
! 438: .Fa info .
! 439: A
! 440: .Xr pevent 3
! 441: context
! 442: .Fa ctx
! 443: must be supplied.
! 444: .Fn app_config_init
! 445: returns an application context, with which all configuration and
! 446: subsystems are associated.
! 447: Multiple independent application contexts may exist at the same time.
! 448: The
! 449: .Fa cookie
! 450: is saved along with the context but is otherwise ignored.
! 451: .Pp
! 452: .Fn app_config_uninit
! 453: should be called at application shutdown time to release resources
! 454: allocated by
! 455: .Nm app_config .
! 456: It may only be called when all subsystems are shutdown (i.e., the
! 457: current configuration object pointer is
! 458: .Dv NULL) .
! 459: This enables
! 460: .Fn app_config_init
! 461: to be called again, if so desired.
! 462: .Pp
! 463: Upon return from
! 464: .Fn app_config_uninit ,
! 465: .Fa "*ctxp"
! 466: will be set to
! 467: .Dv NULL .
! 468: If
! 469: .Fa "*ctxp"
! 470: is already equal to
! 471: .Dv NULL
! 472: when
! 473: .Fn app_config_uninit
! 474: is invoked, nothing happens.
! 475: .Pp
! 476: .Fn app_config_get_cookie
! 477: retrieves the application cookie provided to
! 478: .Fn app_config_init .
! 479: .Pp
! 480: .Fn app_config_load
! 481: reads in an application configuration object from the XML file at
! 482: .Fa path
! 483: and applies it, making it the current configuration.
! 484: If
! 485: .Fa path
! 486: is empty or non-existent, a new configuration object is created
! 487: using the application's
! 488: .Fn getnew
! 489: method.
! 490: .Pp
! 491: If the file contains an old version of the configuration object,
! 492: it is automatically upgraded to the current version.
! 493: If
! 494: .Fa allow_writeback
! 495: is non-zero, then
! 496: .Fa path
! 497: is remembered and the file is updated (i.e., rewritten) every time
! 498: the application configuration object changes.
! 499: Updates are done atomically by creating a temporary file with the
! 500: suffix ".new" and renaming it (see
! 501: .Xr rename 2) .
! 502: .Pp
! 503: In theory, one call to
! 504: .Fn app_config_load
! 505: in an application's
! 506: .Fn main
! 507: routine is all that is required to get things going.
! 508: .Pp
! 509: .Fn app_config_reload
! 510: reloads the configuration file previously specified to
! 511: .Fn app_config_load
! 512: and applies it.
! 513: This would be the typical response to receiving a
! 514: .Dv SIGHUP
! 515: signal.
! 516: .Pp
! 517: .Fn app_config_new
! 518: creates a new configuration object with the application's default values
! 519: as specified by the application's
! 520: .Fn init
! 521: method.
! 522: The returned pointer should be cast to the appropriate type.
! 523: The caller is responsible for eventually freeing the returned
! 524: configuration object by calling
! 525: .Fn app_config_free .
! 526: .Pp
! 527: .Fn app_config_set
! 528: changes the application's current configuration to be a copy of the
! 529: configuration pointed to by
! 530: .Fa config .
! 531: If this configuration is invalid, -1 is returned with
! 532: .Va errno
! 533: set to
! 534: .Er EINVAL ,
! 535: and if
! 536: .Fa ebuf
! 537: is not
! 538: .Dv NULL ,
! 539: the buffer pointed to by
! 540: .Fa ebuf
! 541: and having size
! 542: .Fa emax
! 543: is filled in with a '\\0'-terminated error message.
! 544: .Fn app_config_set
! 545: may also return -1 with
! 546: .Va errno
! 547: set to other values in the case of system errors.
! 548: .Pp
! 549: If
! 550: .Fa config
! 551: is
! 552: .Dv NULL ,
! 553: all running subsystems will be shut down.
! 554: Any configurations passed to
! 555: .Fn app_config_set
! 556: subsequent to passing a
! 557: .Dv NULL
! 558: configuration, but before the shutdown operation has completed, are ignored.
! 559: This guarantees that a
! 560: .Dv NULL
! 561: configuration does actually shutdown the application.
! 562: .Pp
! 563: The new configuration (or shutdown) takes effect after a delay of
! 564: .Fa delay
! 565: milliseconds after
! 566: .Fn app_config_set
! 567: has successfully returned zero.
! 568: The appropriate subsystem
! 569: .Fn stop ,
! 570: and then
! 571: .Fn start
! 572: methods are invoked serially from a new thread.
! 573: .Pp
! 574: .Fn app_config_get
! 575: returns a copy of the current or pending configuration object.
! 576: The returned pointer should be cast to the appropriate type.
! 577: If
! 578: .Fa pending
! 579: is zero, then the configuration object currently in use is copied.
! 580: Otherwise, the configuration object most recently applied via
! 581: .Fn app_config_set
! 582: is copied.
! 583: These will be different when there is a pending, but not yet applied,
! 584: configuration.
! 585: The caller is responsible for eventually freeing the returned
! 586: configuration object by calling
! 587: .Fn app_config_free .
! 588: .Pp
! 589: .Fn app_config_get_type
! 590: returns the
! 591: .Xr structs 3
! 592: for the application configuration object.
! 593: .Pp
! 594: .Fn app_config_copy
! 595: copies a configuration object.
! 596: The returned pointer should be cast to the appropriate type.
! 597: The caller is responsible for eventually freeing the returned
! 598: configuration object by calling
! 599: .Fn app_config_free .
! 600: .Pp
! 601: .Fn app_config_free
! 602: destroys the configuration object pointed to by
! 603: .Fa "*configp" .
! 604: Upon return,
! 605: .Fa "*configp"
! 606: will be set to
! 607: .Dv NULL .
! 608: If
! 609: .Fa "*configp"
! 610: is already
! 611: .Dv NULL
! 612: when
! 613: .Fn app_config_free
! 614: is invoked, nothing happens.
! 615: .\"
! 616: .Ss Pre-defined subsystems
! 617: .\"
! 618: The
! 619: .Nm app_config
! 620: library comes with some predefined subsystem templates.
! 621: .Pp
! 622: .Va app_config_alog_subsystem
! 623: handles configuring error logging for an application.
! 624: To use
! 625: .Va app_config_alog_subsystem ,
! 626: copy the structure and set the
! 627: .Fa arg
! 628: field to point to a
! 629: .Li "struct app_config_alog_info" :
! 630: .Pp
! 631: .Bd -literal -compact -offset 3n
! 632: struct app_config_alog_info {
! 633: const char *name; /* field name */
! 634: int channel; /* alog channel */
! 635: };
! 636: .Ed
! 637: .Pp
! 638: The
! 639: .Fa name
! 640: should be the
! 641: .Xr structs 3
! 642: field name of the field in the configuration object that configures
! 643: logging for the
! 644: .Xr alog 3
! 645: logging channel
! 646: .Fa channel .
! 647: This field should be a
! 648: .Li "struct alog_config" .
! 649: .Pp
! 650: .Va app_config_curconf_subsystem
! 651: is useful when the application needs efficient access to the currently
! 652: active configuration.
! 653: This subsystem assumes that there is a global pointer variable (call it
! 654: .Va curconf )
! 655: which by definition always points to a read-only copy of the currently
! 656: active configuration.
! 657: For example, if the application's configuration object is a
! 658: .Li "struct my_config" ,
! 659: then
! 660: .Va curconf
! 661: would be defined as:
! 662: .Pp
! 663: .Bd -literal -compact -offset 3n
! 664: const struct my_config *const curconf;
! 665: .Ed
! 666: .Pp
! 667: Then the function of
! 668: .Va app_config_curconf_subsystem
! 669: is to automatically keep this variable up to date.
! 670: (The
! 671: .Li "const"
! 672: keywords reflect the application's point of view:
! 673: the first is because the structure is read-only, while the second
! 674: is because the pointer itself is read-only.)
! 675: .Pp
! 676: To use
! 677: .Va app_config_curconf_subsystem ,
! 678: copy the structure and set the
! 679: .Fa arg
! 680: field to point to the application's
! 681: .Va curconf
! 682: pointer variable.
! 683: Typically the
! 684: .Va app_config_curconf_subsystem
! 685: will be first in the list of subsystems, so that
! 686: .Va curconf
! 687: is always updated before any other subsystem starts.
! 688: Then at any time
! 689: .Va "*curconf"
! 690: can be examined for the currently active configuration.
! 691: .Pp
! 692: .Va app_config_directory_subsystem
! 693: handles configuring the current working directory for the process.
! 694: To use
! 695: .Va app_config_directory_subsystem ,
! 696: copy the structure and set the
! 697: .Fa arg
! 698: field to point to a string containing the
! 699: .Xr structs 3
! 700: name of the field in the configuration object that contains the
! 701: directory name.
! 702: If this name is not the empty string, then the current working directory
! 703: will be set according to the value of this field.
! 704: .Pp
! 705: .Va app_config_pidfile_subsystem
! 706: handles "PID files", i.e., exclusive application lock files into which
! 707: the process ID is written.
! 708: These guard against two instances of the same application running at the
! 709: same time.
! 710: To use
! 711: .Va app_config_pidfile_subsystem ,
! 712: copy the structure and set the
! 713: .Fa arg
! 714: field to point to a string containing the
! 715: .Xr structs 3
! 716: name of the field in the configuration object that contains the PID file
! 717: pathname.
! 718: .Sh RETURN VALUES
! 719: All of the
! 720: .Nm app_config
! 721: functions return
! 722: .Dv NULL
! 723: or -1 to indicate an error and set
! 724: .Va errno
! 725: appropriately.
! 726: .Sh SEE ALSO
! 727: .Xr alog 3 ,
! 728: .Xr libpdel 3 ,
! 729: .Xr pevent 3 ,
! 730: .Xr structs 3 ,
! 731: .Xr typed_mem 3
! 732: .Sh HISTORY
! 733: The PDEL library was developed at Packet Design, LLC.
! 734: .Dv "http://www.packetdesign.com/"
! 735: .Sh AUTHORS
! 736: .An Archie Cobbs Aq archie@freebsd.org
! 737: .Sh BUGS
! 738: There should be explicit support for subsystems that require other
! 739: subsystems to be running before they may run.
! 740: As it stands now, such dependencies must be implicitly encoded into the
! 741: .Fn willrun
! 742: and
! 743: .Fn changed
! 744: methods.
! 745: Even so, the dependent subsystem cannot detect if the other subsystem
! 746: fails to start.
! 747: .Pp
! 748: Subsystems should be defined more like objects using dynamically
! 749: allocated structures that can be added and removed from the subsystem
! 750: list at any time, without having to shutdown and restart the whole
! 751: application.
! 752: .Pp
! 753: It should be possible to start and shutdown subsystems individually.
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>