cfg_struct.h

00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2007 iptelorg GmbH
00005  *
00006  * This file is part of SIP-router, a free SIP server.
00007  *
00008  * SIP-router is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * SIP-router is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  * History
00023  * -------
00024  *  2007-12-03  Initial version (Miklos)
00025  *  2008-01-24  dynamic groups are introduced in order to make
00026  *              variable declaration possible in the script (Miklos)
00027  */
00028 
00029 #ifndef _CFG_STRUCT_H
00030 #define _CFG_STRUCT_H
00031 
00032 #include "../str.h"
00033 #include "../atomic_ops.h"
00034 #include "../mem/shm_mem.h"
00035 #include "../locking.h"
00036 #include "../compiler_opt.h"
00037 #include "../bit_test.h"
00038 #include "cfg.h"
00039 
00041 #define CFG_MAX_VAR_NUM 256
00042 
00044 #define cfg_var_shmized 1U
00045 
00050 typedef struct _cfg_add_var {
00051         struct _cfg_add_var     *next;
00052         unsigned int    type;   
00054         union {
00055                 char    *ch;
00056                 str     s;
00057                 int     i;
00058         } val;
00059         unsigned int    group_id; 
00060         int             name_len;       
00064         char            name[1];
00065 } cfg_add_var_t;
00066 
00068 typedef struct _cfg_mapping {
00069         cfg_def_t       *def;           
00070         int             name_len;       
00072         /* additional information about the cfg variable */
00073         int             pos;    
00074         int             offset; 
00075         unsigned int    flag;   
00076 } cfg_mapping_t;
00077 
00079 enum { CFG_GROUP_UNKNOWN = 0, CFG_GROUP_DYNAMIC, CFG_GROUP_STATIC };
00080 
00082 typedef struct _cfg_group {
00083         int             num;            
00084         cfg_mapping_t   *mapping;       
00086         char            *vars;          
00089         cfg_add_var_t   *add_var;       
00092         int             size;           
00094         int             meta_offset;    
00096         int             var_offset;     
00098         void            **handle;       
00102         void            *orig_handle;   
00107         unsigned char   dynamic;        
00109         struct _cfg_group       *next;
00110         int             name_len;
00111         char            name[1];
00112 } cfg_group_t;
00113 
00116 typedef struct _cfg_group_inst {
00117         unsigned int    id;             
00118         unsigned int    set[CFG_MAX_VAR_NUM/(sizeof(int)*8)];
00122         unsigned char   vars[1];        
00123 } cfg_group_inst_t;
00124 
00129 typedef struct _cfg_group_meta {
00130         int                     num;    
00131         cfg_group_inst_t        *array; 
00132 } cfg_group_meta_t;
00133 
00135 typedef struct _cfg_block {
00136         atomic_t        refcnt;         
00139         unsigned char   vars[1];        
00140 } cfg_block_t;
00141 
00148 typedef struct _cfg_child_cb {
00149         atomic_t                refcnt; 
00151         atomic_t                cb_count;       
00157         str                     gname, name;    
00158         cfg_on_set_child        cb;             
00159         void                    **replaced;     
00165         struct _cfg_child_cb    *next;
00166 } cfg_child_cb_t;
00167 
00168 extern cfg_group_t      *cfg_group;
00169 extern cfg_block_t      **cfg_global;
00170 extern cfg_block_t      *cfg_local;
00171 extern int              cfg_block_size;
00172 extern gen_lock_t       *cfg_global_lock;
00173 extern gen_lock_t       *cfg_writer_lock;
00174 extern int              cfg_shmized;
00175 extern cfg_child_cb_t   **cfg_child_cb_first;
00176 extern cfg_child_cb_t   **cfg_child_cb_last;
00177 extern cfg_child_cb_t   *cfg_child_cb;
00178 extern int              cfg_ginst_count;
00179 
00180 /* magic value for cfg_child_cb for processes that do not want to
00181    execute per-child callbacks */
00182 #define CFG_NO_CHILD_CBS ((void*)(long)(-1))
00183 
00184 /* macros for easier variable access */
00185 #define CFG_VAR_TYPE(var)       CFG_VAR_MASK((var)->def->type)
00186 #define CFG_INPUT_TYPE(var)     CFG_INPUT_MASK((var)->def->type)
00187 
00188 /* get the meta-data of a group from the block */
00189 #define CFG_GROUP_META(block, group) \
00190         ((cfg_group_meta_t *)((block)->vars + (group)->meta_offset))
00191 
00192 /* get the data block of a group from the block */
00193 #define CFG_GROUP_DATA(block, group) \
00194         ((unsigned char *)((block)->vars + (group)->var_offset))
00195 
00196 /* Test whether a variable is explicitely set in the group instance,
00197  * or it uses the default value */
00198 #define CFG_VAR_TEST(group_inst, var) \
00199         bit_test((var)->pos % (sizeof(int)*8), (group_inst)->set + (var)->pos/(sizeof(int)*8))
00200 
00201 /* Test whether a variable is explicitely set in the group instance,
00202  * or it uses the default value, and set the flag. */
00203 #define CFG_VAR_TEST_AND_SET(group_inst, var) \
00204         bit_test_and_set((var)->pos % (sizeof(int)*8), (group_inst)->set + (var)->pos/(sizeof(int)*8))
00205 
00206 /* Test whether a variable is explicitely set in the group instance,
00207  * or it uses the default value, and reset the flag. */
00208 #define CFG_VAR_TEST_AND_RESET(group_inst, var) \
00209         bit_test_and_reset((var)->pos % (sizeof(int)*8), (group_inst)->set + (var)->pos/(sizeof(int)*8))
00210 
00211 /* Return the group instance pointer from a handle,
00212  * or NULL if the handle points to the default configuration block */
00213 #define CFG_HANDLE_TO_GINST(h) \
00214         ( (((unsigned char*)(h) < cfg_local->vars) \
00215                 || ((unsigned char*)(h) > cfg_local->vars + cfg_block_size) \
00216         ) ? \
00217                 (cfg_group_inst_t*)((char*)(h) - (unsigned long)&((cfg_group_inst_t *)0)->vars) \
00218                 : NULL )
00219 
00220 /* initiate the cfg framework */
00221 int sr_cfg_init(void);
00222 
00223 /* destroy the memory allocated for the cfg framework */
00224 void cfg_destroy(void);
00225 
00226 /* Register num number of child processes that will
00227  * keep updating their local configuration.
00228  * This function needs to be called from mod_init
00229  * before any child process is forked.
00230  */
00231 void cfg_register_child(int num);
00232 
00233 /* per-child process init function.
00234  * It needs to be called from the forked process.
00235  * cfg_register_child() must be called before this function!
00236  */
00237 int cfg_child_init(void);
00238 
00239 /* Child process init function that can be called
00240  * without cfg_register_child().
00241  * Note that the child process may miss some configuration changes.
00242  */
00243 int cfg_late_child_init(void);
00244 
00245 /* per-child init function for non-cb executing processes.
00246  * Mark this process as not wanting to execute any per-child config
00247  * callback (it will have only limited config functionality, but is useful
00248  * when a process needs only to watch some non-callback cfg. values,
00249  * e.g. the main attendant process, debug and memlog).
00250  * It needs to be called from the forked process.
00251  * cfg_register_child must _not_ be called.
00252  */
00253 int cfg_child_no_cb_init(void);
00254 
00255 /* per-child process destroy function
00256  * Should be called only when the child process exits,
00257  * but SER continues running.
00258  *
00259  * WARNING: this function call must be the very last action
00260  * before the child process exits, because the local config
00261  * is not available afterwards.
00262  */
00263 void cfg_child_destroy(void);
00264 
00265 /* creates a new cfg group, and adds it to the linked list */
00266 cfg_group_t *cfg_new_group(char *name, int name_len,
00267                 int num, cfg_mapping_t *mapping,
00268                 char *vars, int size, void **handle);
00269 
00270 /* Set the values of an existing cfg group. */
00271 void cfg_set_group(cfg_group_t *group,
00272                 int num, cfg_mapping_t *mapping,
00273                 char *vars, int size, void **handle);
00274 
00275 /* copy the variables to shm mem */
00276 int cfg_shmize(void);
00277 
00278 /* free the memory of a child cb structure */
00279 static inline void cfg_child_cb_free_item(cfg_child_cb_t *cb)
00280 {
00281         int     i;
00282 
00283         /* free the changed variables */
00284         if (cb->replaced) {
00285                 for (i=0; cb->replaced[i]; i++)
00286                         shm_free(cb->replaced[i]);
00287                 shm_free(cb->replaced);
00288         }
00289         shm_free(cb);
00290 }
00291 
00292 #define cfg_block_free(block) \
00293         shm_free(block)
00294 
00295 /* Move the group handle to the specified group instance pointed by dst_ginst.
00296  * src_ginst shall point to the active group instance.
00297  * Both parameters can be NULL meaning that the src/dst config is the default, 
00298  * not an additional group instance.
00299  * The function executes all the per-child process callbacks which are different
00300  * in the two instaces.
00301  */
00302 void cfg_move_handle(cfg_group_t *group, cfg_group_inst_t *src_ginst, cfg_group_inst_t *dst_ginst);
00303 
00304 
00305 /* lock and unlock the global cfg block -- used only at the
00306  * very last step when the block is replaced */
00307 #define CFG_LOCK()      lock_get(cfg_global_lock);
00308 #define CFG_UNLOCK()    lock_release(cfg_global_lock);
00309 
00310 /* lock and unlock used by the cfg drivers to make sure that
00311  * only one driver process is considering replacing the global
00312  * cfg block */
00313 #define CFG_WRITER_LOCK()       lock_get(cfg_writer_lock);
00314 #define CFG_WRITER_UNLOCK()     lock_release(cfg_writer_lock);
00315 
00316 /* increase and decrease the reference counter of a block */
00317 #define CFG_REF(block) \
00318         atomic_inc(&(block)->refcnt)
00319 
00320 #define CFG_UNREF(block) \
00321         do { \
00322                 if (atomic_dec_and_test(&(block)->refcnt)) \
00323                         cfg_block_free(block); \
00324         } while(0)
00325 
00326 /* updates all the module handles and calls the
00327  * per-child process callbacks -- not intended to be used
00328  * directly, use cfg_update() instead!
00329  * params:
00330  *   no_cbs - if 1, do not call per child callbacks
00331  */
00332 static inline void cfg_update_local(int no_cbs)
00333 {
00334         cfg_group_t     *group;
00335         cfg_child_cb_t  *last_cb;
00336         cfg_child_cb_t  *prev_cb;
00337 
00338         if (cfg_local) CFG_UNREF(cfg_local);
00339         CFG_LOCK();
00340         CFG_REF(*cfg_global);
00341         cfg_local = *cfg_global;
00342         /* the value of the last callback must be read within the lock */
00343         last_cb = *cfg_child_cb_last;
00344 
00345         /* I unlock now, because the child process can update its own private
00346         config without the lock held. In the worst case, the process will get the
00347         lock once more to set cfg_child_cb_first, but only one of the child
00348         processes will do so, and only if a value, that has per-child process
00349         callback defined, was changed. */
00350         CFG_UNLOCK();
00351 
00352         /* update the handles */
00353         for (   group = cfg_group;
00354                 group;
00355                 group = group->next
00356         )
00357                 *(group->handle) = CFG_GROUP_DATA(cfg_local, group);
00358 
00359         if (unlikely(cfg_child_cb==CFG_NO_CHILD_CBS || no_cbs))
00360                 return;
00361         /* call the per-process callbacks */
00362         while (cfg_child_cb != last_cb) {
00363                 prev_cb = cfg_child_cb;
00364                 cfg_child_cb = cfg_child_cb->next;
00365                 atomic_inc(&cfg_child_cb->refcnt);
00366                 if (atomic_dec_and_test(&prev_cb->refcnt)) {
00367                         /* No more pocess refers to this callback.
00368                         Did this process block the deletion,
00369                         or is there any other process that has not
00370                         reached prev_cb yet? */
00371                         CFG_LOCK();
00372                         if (*cfg_child_cb_first == prev_cb) {
00373                                 /* yes, this process was blocking the deletion */
00374                                 *cfg_child_cb_first = cfg_child_cb;
00375                                 CFG_UNLOCK();
00376                                 cfg_child_cb_free_item(prev_cb);
00377                         } else {
00378                                 CFG_UNLOCK();
00379                         }
00380                 }
00381                 if (cfg_child_cb->cb
00382                         && (atomic_add(&cfg_child_cb->cb_count, -1) >= 0) /* the new value is returned
00383                                                                         by atomic_add() */
00384                 )
00385                         /* execute the callback */
00386                         cfg_child_cb->cb(&cfg_child_cb->gname, &cfg_child_cb->name);
00387                 /* else the callback no longer needs to be executed */
00388         }
00389 }
00390 
00391 /* Reset all the group handles to the default, local configuration */
00392 static inline void cfg_reset_handles(void)
00393 {
00394         cfg_group_t     *group;
00395 
00396         if (!cfg_local)
00397                 return;
00398 
00399         for (   group = cfg_group;
00400                 group && cfg_ginst_count; /* cfg_ginst_count is decreased every time
00401                                         a group handle is reset. When it reaches 0,
00402                                         needless to continue the loop */
00403                 group = group->next
00404         ) {
00405                 if (((unsigned char*)*(group->handle) < cfg_local->vars)
00406                         || ((unsigned char*)*(group->handle) > cfg_local->vars + cfg_block_size)
00407                 )
00408                         cfg_move_handle(group,
00409                                         CFG_HANDLE_TO_GINST(*(group->handle)),
00410                                         NULL);
00411         }
00412 }
00413 
00414 /* sets the local cfg block to the active block
00415  * 
00416  * If your module forks a new process that implements
00417  * an infinite loop, put cfg_update() to the beginning of
00418  * the cycle to make sure, that subsequent function calls see the
00419  * up-to-date config set.
00420  */
00421 #define cfg_update() \
00422         do { \
00423                 if (unlikely(cfg_ginst_count)) \
00424                         cfg_reset_handles(); \
00425                 if (unlikely(cfg_local != *cfg_global)) \
00426                         cfg_update_local(0); \
00427         } while(0)
00428 
00429 /* like cfg_update(), but does not execute callbacks
00430  * (it should be used sparingly only in special cases, since it
00431  *  breaks an important cfg framework feature)
00432  */
00433 #define cfg_update_no_cbs() \
00434         do { \
00435                 if (unlikely(cfg_local != *cfg_global)) \
00436                         cfg_update_local(1); \
00437         } while(0)
00438 
00439 /* Reset all the group handles in the child process,
00440  * i.e. move them back to the default local configuration.
00441  */
00442 #define cfg_reset_all() \
00443         do { \
00444                 if (unlikely(cfg_ginst_count)) \
00445                         cfg_reset_handles(); \
00446         } while(0)
00447 
00448 
00449 /* searches a group by name */
00450 cfg_group_t *cfg_lookup_group(char *name, int len);
00451         
00452 /* searches a variable definition by group and variable name */
00453 int cfg_lookup_var(str *gname, str *vname,
00454                         cfg_group_t **group, cfg_mapping_t **var);
00455 
00456 /* searches a variable definition within a group by its name */
00457 cfg_mapping_t *cfg_lookup_var2(cfg_group_t *group, char *name, int len);
00458 
00459 /* clones the global config block
00460  * WARNING: unsafe, cfg_writer_lock or cfg_global_lock must be held!
00461  */
00462 cfg_block_t *cfg_clone_global(void);
00463 
00464 /* Clone an array of configuration group instances. */
00465 cfg_group_inst_t *cfg_clone_array(cfg_group_meta_t *meta, cfg_group_t *group);
00466 
00467 /* Extend the array of configuration group instances with one more instance.
00468  * Only the ID of the new group is set, nothing else. */
00469 cfg_group_inst_t *cfg_extend_array(cfg_group_meta_t *meta, cfg_group_t *group,
00470                                 unsigned int group_id,
00471                                 cfg_group_inst_t **new_group);
00472 
00473 /* Remove an instance from a group array.
00474  * inst must point to an instance within meta->array.
00475  * *_new_array is set to the newly allocated array. */
00476 int cfg_collapse_array(cfg_group_meta_t *meta, cfg_group_t *group,
00477                                 cfg_group_inst_t *inst,
00478                                 cfg_group_inst_t **_new_array);
00479 
00480 /* clones a string to shared memory */
00481 int cfg_clone_str(str *src, str *dst);
00482 
00483 /* Find the group instance within the meta-data based on the group_id */
00484 cfg_group_inst_t *cfg_find_group(cfg_group_meta_t *meta, int group_size, unsigned int group_id);
00485 
00486 /* append new callbacks to the end of the child callback list
00487  *
00488  * WARNING: the function is unsafe, either hold CFG_LOCK(),
00489  * or call the function before forking
00490  */
00491 void cfg_install_child_cb(cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last);
00492 
00493 /* installs a new global config
00494  *
00495  * replaced is an array of strings that must be freed together
00496  * with the previous global config.
00497  * cb_first and cb_last define a linked list of per-child process
00498  * callbacks. This list is added to the global linked list.
00499  */
00500 void cfg_install_global(cfg_block_t *block, void **replaced,
00501                         cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last);
00502 
00503 /* creates a structure for a per-child process callback */
00504 cfg_child_cb_t *cfg_child_cb_new(str *gname, str *name,
00505                         cfg_on_set_child cb,
00506                         unsigned int type);
00507 
00508 /* free the memory allocated for a child cb list */
00509 void cfg_child_cb_free_list(cfg_child_cb_t *child_cb_first);
00510 
00511 /* Allocate memory for a new additional variable
00512  * and link it to a configuration group.
00513  * type==0 results in creating a new group instance with the default values.
00514  * The group is created with CFG_GROUP_UNKNOWN type if it does not exist.
00515  * Note: this function is usable only before the configuration is shmized.
00516  */
00517 int new_add_var(str *group_name, unsigned int group_id, str *var_name,
00518                                 void *val, unsigned int type);
00519 
00520 /* Move the group handle to the specified group instance. */
00521 int cfg_select(cfg_group_t *group, unsigned int id);
00522 
00523 /* Reset the group handle to the default, local configuration */
00524 int cfg_reset(cfg_group_t *group);
00525 
00526 /* Move the group handle to the first group instance.
00527  * This function together with cfg_select_next() can be used
00528  * to iterate though the list of instances.
00529  *
00530  * Return value:
00531  *      -1: no group instance found
00532  *       0: first group instance is successfully selected.
00533  */
00534 int cfg_select_first(cfg_group_t *group);
00535 
00536 /* Move the group handle to the next group instance.
00537  * This function together with cfg_select_first() can be used
00538  * to iterate though the list of instances.
00539  *
00540  * Return value:
00541  *      -1: no more group instance found. Note, that the active group
00542  *              instance is not changed in this case.
00543  *       0: the next group instance is successfully selected.
00544  */
00545 int cfg_select_next(cfg_group_t *group);
00546 
00547 /* Temporary set the local configuration in the main process before forking.
00548  * This makes the group instances usable in the main process after
00549  * the configuration is shmized, but before the children are forked.
00550  */
00551 void cfg_main_set_local(void);
00552 
00553 /* Reset the local configuration of the main process back to its original state
00554  * to make sure that the forked processes are not affected.
00555  */
00556 void cfg_main_reset_local(void);
00557 
00558 #endif /* _CFG_STRUCT_H */