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=b2efa6a…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)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;