documenting the configuration framework
authorMiklos Tirpak <miklos@iptel.org>
Fri, 7 Dec 2007 16:32:57 +0000 (16:32 +0000)
committerMiklos Tirpak <miklos@iptel.org>
Fri, 7 Dec 2007 16:32:57 +0000 (16:32 +0000)
doc/cfg.txt [new file with mode: 0644]

diff --git a/doc/cfg.txt b/doc/cfg.txt
new file mode 100644 (file)
index 0000000..fa603f4
--- /dev/null
@@ -0,0 +1,240 @@
+# $Id$
+#
+# History:
+# --------
+# 2007-12-06:  Created by Miklos
+
+SER Configuration Framework
+
+1. Overview
+===============================================================================
+
+The configuration framework can be used by SER core and by the modules,
+to get and set internal variables on-the-fly, and eliminate SER restarts
+whenever it is possible.
+
+The core and the modules can declare configuration variables, and can
+retrieve the value of the variables at any time without performance
+overhead. The framework makes sure that the variables do not change
+during the SIP message processing, the child processes see a snapshot
+of the variables with constant values. The variable, that is changed by
+a cfg driver module, will be automatically replaced by the framework
+the next time a SIP message is started to be processed.
+  
+The drivers can change the values of all the variables by names with or
+without the need of commit. That means a kind of transaction support,
+the framework can keep track of the changes (per driver) until they
+are committed or rolled-back.
+
+2. Using the framework in a module
+===============================================================================
+
+Make sure that the run-time change of the variable cannot cause troubles.
+You can expect the variable change before a SIP message is processed,
+or before a timer fires, but it will never change during the function
+calls.
+
+1. Include the header file:
+
+#include "../../cfg/cfg.h"
+
+-------------------------------------------------------------------------------
+
+2. Define a structure that contains the variables, the structure name
+must begin with "cfg_group_" followed by the group name: (The group name
+is typically the module name, but a single module can register more than
+one groups as well.)
+
+struct cfg_group_foo {
+       int     i;
+       char    *ch;
+       str     s;
+       void    *p;
+};
+
+-------------------------------------------------------------------------------
+
+3. Set the default values:
+
+static struct cfg_group_foo default_cfg = {
+       -1,
+       "mystring",
+       {"interoperability", 16},
+       NULL,
+};
+
+-------------------------------------------------------------------------------
+
+4. Export the variables over the module interface if you wish:
+
+static param_export_t params[] = {
+       {"i",   PARAM_INT,      &default_cfg.i},
+       {"ch",  PARAM_STRING,   &default_cfg.ch},
+       {"s",   PARAM_STR,      &default_cfg.s},
+       {0, 0, 0}
+};
+
+-------------------------------------------------------------------------------
+
+5. Declare a void* handle that will be used to access the config group:
+
+static void    *cfg_handle = &default_cfg;
+
+-------------------------------------------------------------------------------
+
+6. Describe the structure you defined at step 2 for the framework:
+
+static cfg_def_t cfg_def[] = {
+       {"int", CFG_VAR_INT, -10, 10, 0, 0, "integer for testing"},
+       {"ch", CFG_VAR_STRING, 0, 0, 0, 0, "string for testing"},
+       {"s", CFG_VAR_STR, 0, 0, 0, 0, "str for testing"},
+       {"p", CFG_VAR_POINTER | CFG_INPUT_STRING, 0, 0, fixup_p, fixup_child_p, "pointer for testing"},
+       {0, 0, 0, 0, 0, 0, 0},
+};
+
+Each row consists of the following items:
+
+- name that will be used by the drivers to refer to the variable
+- flag indicating the variable and the input type, that is accepted
+  by the fixup function
+
+  Valid variable types are:
+       - CFG_VAR_INT           = int
+       - CFG_VAR_STRING        = char*
+       - CFG_VAR_STR           = str
+       - CFG_VAR_POINTER       = void*
+
+  Valid input types are:
+       - CFG_INPUT_INT         = int
+       - CFG_INPUT_STRING      = char*
+       - CFG_INPUT_STR         = str*
+
+- minimum value for integers (optional)
+- maximum value for integers (optional)
+- fixup function (optional) that is called when the variable is going to be
+  changed by a driver. The module still uses the old value until the change
+  is committed, and the next SIP message is started to be processed, however
+  the new, not-yet-committed values can be accessed by using the temporary
+  handle within the fixup function. String and str values are cloned to
+  shm memory by the framework. The callback type is:
+
+  typedef int (*cfg_on_change)(void *temp_handle, str *var_name, void **value);
+
+- per-child process callback function (optional) that is called by each child
+  process separately, after the new values have been committed, and the
+  child process is updating its local configuration. The old value will no
+  longer be used by the process. (Useful for fix-ups that cannot be done
+  in shm memory, for example regexp compilation.)
+
+  typedef void (*cfg_on_set_child)(str *var_name);
+
+- description of the variable
+
+-------------------------------------------------------------------------------
+
+7. Declare the configuration group in mod_init:
+
+static int mod_init(void)
+{
+       if (cfg_declare("foo", cfg_def, &default_cfg, cfg_size(foo),
+                        &cfg_handle)
+       ) {
+               /* error */
+               return -1;
+       }
+       ...
+}
+
+-------------------------------------------------------------------------------
+
+8. The variables can be accessed any time by the group name and handle:
+
+cfg_get(foo, cfg_handle, i)
+cfg_get(foo, cfg_handle, ch)
+cfg_get(foo, cfg_handle, s)
+cfg_get(foo, cfg_handle, p)
+
+
+3. Using the framework in the core
+===============================================================================
+
+There is basically no difference between the modules and the core, the core can
+register any number of groups just like a module. A group called "core" has
+been already registered, have a look at the cfg_core.* files.
+
+
+4. Drivers
+===============================================================================
+
+Drivers can change the values of the configuration variables run-time, they can
+implement RPC calls or database backend for example.
+The framework is multi-process safe, more drivers (or a single driver with
+multiple processes) can modify the configuration at the same time.
+
+1. Create a context for the driver
+
+#include "../../cfg/cfg_ctx.h"
+
+static cfg_ctx_t       *ctx = NULL;
+
+static void on_declare(str *group_name, cfg_def_t *definition)
+{
+       ...
+}
+
+static int mod_init(void)
+{
+       ctx = cfg_register_ctx(on_declare);
+       if (!ctx) {
+               /* error */
+               return -1;
+       }
+       ...
+}
+
+The callback function, on_declare(), is called every time a new configuration
+group is registered, so the driver has a chance to know which groups and
+variables are present, and can immediately modify them.
+
+-------------------------------------------------------------------------------
+
+2. Get the value of a variable by name:
+
+cfg_get_by_name()
+
+-------------------------------------------------------------------------------
+
+3. Set the value of a variable without the need of explicit commit:
+
+cfg_set_now()
+
+wrapper functions:
+
+cfg_set_now_int()
+cfg_set_now_string()
+
+-------------------------------------------------------------------------------
+
+4. Set the value of a variable, but does not commit the change:
+
+cfg_set_delayed()
+
+wrapper functions:
+
+cfg_set_delayed_int()
+cfg_set_delayed_string()
+
+More changes can be done, and committed at once.
+
+-------------------------------------------------------------------------------
+
+5. Commit or roll back the previously prepared changes:
+
+cfg_commit()
+cfg_rollback()
+
+-------------------------------------------------------------------------------
+
+6. Get the description of a variable:
+
+cfg_help()