Module: sip-router Branch: tirpi/cfg_framework_multivalue Commit: b2efa6a116ebc89c8c6198a49fff176df745a2f5 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=b2efa6a1...
Author: Miklos Tirpak miklos@iptel.org Committer: Miklos Tirpak miklos@iptel.org Date: Fri Sep 3 14:48:27 2010 +0200
cfg framework: group meta-data introduced
A new structure for meta-data is added to the variable block before each group. This stucture will be a placeholder for the multiple values of the same variable. The meta-data indicates how many instances the group has excluding the default instance, and will store the pointer to the array of these instances.
---
cfg/cfg_ctx.c | 6 +++--- cfg/cfg_script.c | 8 ++++++++ cfg/cfg_struct.c | 40 +++++++++++++++++++++++++++++++++------- cfg/cfg_struct.h | 30 +++++++++++++++++++++++++++--- 4 files changed, 71 insertions(+), 13 deletions(-)
diff --git a/cfg/cfg_ctx.c b/cfg/cfg_ctx.c index 677a070..d2ea621 100644 --- a/cfg/cfg_ctx.c +++ b/cfg/cfg_ctx.c @@ -328,13 +328,13 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, str *var_name, if (var->def->type & CFG_ATOMIC) { /* atomic change is allowed, we can rewrite the value directly in the global config */ - p = (*cfg_global)->vars+group->offset+var->offset; + p = (*cfg_global)->vars+group->var_offset+var->offset;
} else { /* clone the memory block, and prepare the modification */ if (!(block = cfg_clone_global())) goto error;
- p = block->vars+group->offset+var->offset; + p = block->vars+group->var_offset+var->offset; } } else { /* we are allowed to rewrite the value on-the-fly @@ -786,7 +786,7 @@ int cfg_commit(cfg_ctx_t *ctx) changed = changed->next ) { p = block->vars - + changed->group->offset + + changed->group->var_offset + changed->var->offset;
if ((CFG_VAR_TYPE(changed->var) == CFG_VAR_STRING) diff --git a/cfg/cfg_script.c b/cfg/cfg_script.c index a4ef236..e57fa2d 100644 --- a/cfg/cfg_script.c +++ b/cfg/cfg_script.c @@ -103,7 +103,15 @@ cfg_script_var_t *new_cfg_script_var(char *gname, char *vname, unsigned int type LOG(L_ERR, "ERROR: new_cfg_script_var(): unsupported variable type\n"); return NULL; } + group->num++; + if (group->num > CFG_MAX_VAR_NUM) { + LOG(L_ERR, "ERROR: new_cfg_script_var(): too many variables (%d) within a single group," + " the limit is %d. Increase CFG_MAX_VAR_NUM, or split the group into multiple" + " definitions.\n", + group->num, CFG_MAX_VAR_NUM); + return NULL; + }
var = (cfg_script_var_t *)pkg_malloc(sizeof(cfg_script_var_t)); if (!var) goto error; diff --git a/cfg/cfg_struct.c b/cfg/cfg_struct.c index f2f5bfe..18a8aca 100644 --- a/cfg/cfg_struct.c +++ b/cfg/cfg_struct.c @@ -42,7 +42,7 @@ cfg_block_t **cfg_global = NULL; /* pointer to the active cfg block */ cfg_block_t *cfg_local = NULL; /* per-process pointer to the active cfg block. Updated only when the child process finishes working on the SIP message */ -static int cfg_block_size = 0; /* size of the cfg block (constant) */ +static int cfg_block_size = 0; /* size of the cfg block including the meta-data (constant) */ gen_lock_t *cfg_global_lock = 0; /* protects *cfg_global */ gen_lock_t *cfg_writer_lock = 0; /* This lock makes sure that two processes do not try to clone *cfg_global at the same time. @@ -68,6 +68,14 @@ cfg_group_t *cfg_new_group(char *name, int name_len, return NULL; }
+ if (num > CFG_MAX_VAR_NUM) { + LOG(L_ERR, "ERROR: cfg_new_group(): too many variables (%d) within a single group," + " the limit is %d. Increase CFG_MAX_VAR_NUM, or split the group into multiple" + " definitions.\n", + num, CFG_MAX_VAR_NUM); + return NULL; + } + group = (cfg_group_t *)pkg_malloc(sizeof(cfg_group_t)+name_len-1); if (!group) { LOG(L_ERR, "ERROR: cfg_new_group(): not enough memory\n"); @@ -162,13 +170,31 @@ int cfg_shmize(void) if (!cfg_group) return 0;
/* Let us allocate one memory block that - will contain all the variables */ + * will contain all the variables + meta-data + * in the following form: + * |-----------| + * | meta-data | <- group A: meta_offset + * | variables | <- group A: var_offset + * |-----------| + * | meta-data | <- group B: meta_offset + * | variables | <- group B: var_offset + * |-----------| + * | ... | + * |-----------| + * + * The additional array for the multiple values + * of the same variable is linked to the meta-data. + */ for ( size=0, group = cfg_group; group; group=group->next ) { size = ROUND_POINTER(size); - group->offset = size; + group->meta_offset = size; + size += sizeof(cfg_group_meta_t); + + size = ROUND_POINTER(size); + group->var_offset = size; size += group->size; }
@@ -190,19 +216,19 @@ int cfg_shmize(void) if (cfg_shmize_strings(group)) goto error;
/* copy the values to the new block */ - memcpy(block->vars+group->offset, group->vars, group->size); + memcpy(block->vars+group->var_offset, group->vars, group->size); } else { /* The group was declared with NULL values, * we have to fix it up. * The fixup function takes care about the values, * it fills up the block */ - if (cfg_script_fixup(group, block->vars+group->offset)) goto error; + if (cfg_script_fixup(group, block->vars+group->var_offset)) goto error;
/* Notify the drivers about the new config definition. * Temporary set the group handle so that the drivers have a chance to * overwrite the default values. The handle must be reset after this * because the main process does not have a local configuration. */ - *(group->handle) = block->vars+group->offset; + *(group->handle) = block->vars+group->var_offset; cfg_notify_drivers(group->name, group->name_len, group->mapping->def); *(group->handle) = NULL; @@ -243,7 +269,7 @@ static void cfg_destory_groups(unsigned char *block) (CFG_VAR_TYPE(&mapping[i]) == CFG_VAR_STR)) && mapping[i].flag & cfg_var_shmized) {
- old_string = *(char **)(block + group->offset + mapping[i].offset); + old_string = *(char **)(block + group->var_offset + mapping[i].offset); if (old_string) shm_free(old_string); }
diff --git a/cfg/cfg_struct.h b/cfg/cfg_struct.h index c72573b..456e32b 100644 --- a/cfg/cfg_struct.h +++ b/cfg/cfg_struct.h @@ -36,6 +36,9 @@ #include "../compiler_opt.h" #include "cfg.h"
+/*! \brief Maximum number of variables within a configuration group. */ +#define CFG_MAX_VAR_NUM 256 + /*! \brief indicates that the variable has been already shmized */ #define cfg_var_shmized 1U
@@ -59,8 +62,10 @@ typedef struct _cfg_group { shmized. */ int size; /*!< size of the memory block that has to be allocated to store the values */ - int offset; /*!< offset of the group within the - shmized memory block */ + int meta_offset; /*!< offset of the group within the + shmized memory block for the meta_data */ + int var_offset; /*!< offset of the group within the + shmized memory block for the variables */ void **handle; /*!< per-process handle that can be used by the modules to access the variables. It is registered when the group is created, @@ -73,6 +78,25 @@ typedef struct _cfg_group { char name[1]; } cfg_group_t;
+/*! \brief One instance of the cfg group variables which stores + * the additional values. These values can overwrite the default values. */ +typedef struct _cfg_group_inst { + unsigned int set[CFG_MAX_VAR_NUM/(sizeof(int)*8)]; + /*!< Bitmap indicating whether or not a value is explicitely set + within this instance. If the value is not set, + then the default value is used, and copied into this instance. */ + unsigned char vars[1]; /*!< block for the values */ +} cfg_group_inst_t; + +/*! \bried Meta-data which is stored before each variable group + * within the blob. This structure is used to handle the multivalue + * instances of the variables, i.e. manages the array for the + * additional values. */ +typedef struct _cfg_group_meta { + int num; /*!< Number of items in the array */ + cfg_group_inst_t *array; /*!< Array of cfg groups with num number of items */ +} cfg_group_meta_t; + /*! \brief single memoy block that contains all the cfg values */ typedef struct _cfg_block { atomic_t refcnt; /*!< reference counter, @@ -242,7 +266,7 @@ static inline void cfg_update_local(int no_cbs) group; group = group->next ) - *(group->handle) = cfg_local->vars + group->offset; + *(group->handle) = cfg_local->vars + group->var_offset;
if (unlikely(cfg_child_cb==CFG_NO_CHILD_CBS || no_cbs)) return;