Module: sip-router
Branch: tirpi/cfg_framework_multivalue
Commit: 8e1d174cc6ddcbdb573e2f6435ed2086d5b1c5ac
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=8e1d174…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Thu Sep 9 16:21:41 2010 +0200
cfg framework: group instances can be deleted + bugfix
- cfg_del_group_inst() is added which can be used to delete
the group instances apart from the default one.
- cfg_find_group_inst() used a wrong offset for shifting.
- The copies of the default variable needs to be updated even if the variable
is atomic.
---
cfg/cfg_ctx.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++----
cfg/cfg_ctx.h | 3 +
cfg/cfg_struct.c | 43 +++++++++++++++++++++-
cfg/cfg_struct.h | 7 +++
4 files changed, 151 insertions(+), 10 deletions(-)
diff --git a/cfg/cfg_ctx.c b/cfg/cfg_ctx.c
index b0fa851..3ecc69e 100644
--- a/cfg/cfg_ctx.c
+++ b/cfg/cfg_ctx.c
@@ -274,10 +274,11 @@ static int cfg_update_defaults(cfg_group_meta_t *meta,
int i, clone_done=0;
cfg_group_inst_t *array, *ginst;
- array = meta->array;
+ if (!(array = meta->array))
+ return 0;
for (i = 0; i < meta->num; i++) {
ginst = (cfg_group_inst_t *)((char *)array
- + (sizeof(cfg_group_meta_t) + group->size - 1) * i);
+ + (sizeof(cfg_group_inst_t) + group->size - 1) * i);
if (!CFG_VAR_TEST(ginst, var)) {
/* The variable uses the default value, it needs to be rewritten. */
@@ -514,15 +515,15 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *va
it cannot be freed */
if (cfg_shmized) {
- if (!group_inst && block && CFG_GROUP_META(block, group)->array) {
- if (cfg_update_defaults(CFG_GROUP_META(block, group),
+ if (!group_inst) {
+ /* the default value is changed, the copies of this value
+ need to be also updated */
+ if (cfg_update_defaults(CFG_GROUP_META(block ? block : *cfg_global, group),
group, var, p,
- ((var->def->type & CFG_ATOMIC) == 0)) /* clone if needed */
- ) {
- LOG(L_ERR, "ERROR: cfg_set_now(): not enough shm memory\n");
+ block ? 1 : 0) /* clone if needed */
+ )
goto error;
- }
- if (CFG_GROUP_META(block, group)->array != CFG_GROUP_META(*cfg_global, group)->array)
+ if (block && (CFG_GROUP_META(block, group)->array != CFG_GROUP_META(*cfg_global, group)->array))
new_array = CFG_GROUP_META(block, group)->array;
}
@@ -1338,3 +1339,92 @@ error:
return -1;
}
+
+/* Delete an instance of a group */
+int cfg_del_group_inst(cfg_ctx_t *ctx, str *group_name, unsigned int group_id)
+{
+ cfg_group_t *group;
+ cfg_block_t *block = NULL;
+ void **replaced = NULL;
+ cfg_group_inst_t *new_array = NULL, *group_inst;
+
+ /* verify the context even if we do not need it now
+ to make sure that a cfg driver has called the function
+ (very very weak security) */
+ if (!ctx) {
+ LOG(L_ERR, "ERROR: cfg_del_group_inst(): context is undefined\n");
+ return -1;
+ }
+
+ if (!cfg_shmized) {
+ /* It makes no sense to delete a group instance that has not
+ been created yet */
+ return -1;
+ }
+
+ if (!(group = cfg_lookup_group(group_name->s, group_name->len))) {
+ LOG(L_ERR, "ERROR: cfg_del_group_inst(): group not found\n");
+ return -1;
+ }
+
+ /* make sure that nobody else replaces the global config
+ while the new one is prepared */
+ CFG_WRITER_LOCK();
+ if (!(group_inst = cfg_find_group(CFG_GROUP_META(*cfg_global, group),
+ group->size,
+ group_id))
+ ) {
+ LOG(L_DBG, "DEBUG: cfg_del_group_inst(): the group instance does not exist\n");
+ goto error;
+ }
+
+ /* clone the global memory block because the additional array can be
+ replaced only together with the block. */
+ if (!(block = cfg_clone_global()))
+ goto error;
+
+ /* Remove the group instance from the array. */
+ if (cfg_collapse_array(CFG_GROUP_META(*cfg_global, group), group,
+ group_inst,
+ &new_array)
+ )
+ goto error;
+
+ CFG_GROUP_META(block, group)->array = new_array;
+ CFG_GROUP_META(block, group)->num--;
+
+ if (CFG_GROUP_META(*cfg_global, group)->array) {
+ /* prepare the array of the replaced strings,
+ and replaced group instances,
+ they will be freed when the old block is freed */
+ replaced = (void **)shm_malloc(sizeof(void *) * 2);
+ if (!replaced) {
+ LOG(L_ERR, "ERROR: cfg_del_group_inst(): not enough shm memory\n");
+ goto error;
+ }
+ replaced[0] = CFG_GROUP_META(*cfg_global, group)->array;
+ replaced[1] = NULL;
+ }
+ /* replace the global config with the new one */
+ cfg_install_global(block, replaced, NULL, NULL);
+ CFG_WRITER_UNLOCK();
+
+ LOG(L_INFO, "INFO: cfg_del_group_inst(): "
+ "group instance is deleted: %.*s[%u]\n",
+ group_name->len, group_name->s,
+ group_id);
+
+ return 0;
+error:
+ CFG_WRITER_UNLOCK();
+ if (block) cfg_block_free(block);
+ if (new_array) shm_free(new_array);
+ if (replaced) shm_free(replaced);
+
+ LOG(L_ERR, "ERROR: cfg_add_group_inst(): "
+ "Failed to delete the group instance: %.*s[%u]\n",
+ group_name->len, group_name->s,
+ group_id);
+
+ return -1;
+}
diff --git a/cfg/cfg_ctx.h b/cfg/cfg_ctx.h
index 255911e..964e7f5 100644
--- a/cfg/cfg_ctx.h
+++ b/cfg/cfg_ctx.h
@@ -180,4 +180,7 @@ void cfg_diff_release(cfg_ctx_t *ctx);
/* Add a new instance to an existing group */
int cfg_add_group_inst(cfg_ctx_t *ctx, str *group_name, unsigned int group_id);
+/* Delete an instance of a group */
+int cfg_del_group_inst(cfg_ctx_t *ctx, str *group_name, unsigned int group_id);
+
#endif /* _CFG_CTX_H */
diff --git a/cfg/cfg_struct.c b/cfg/cfg_struct.c
index 77d7cf5..9d5f008 100644
--- a/cfg/cfg_struct.c
+++ b/cfg/cfg_struct.c
@@ -645,6 +645,47 @@ cfg_group_inst_t *cfg_extend_array(cfg_group_meta_t *meta, cfg_group_t *group,
return new_array;
}
+/* Remove an instance from a group array.
+ * inst must point to an instance within meta->array.
+ * *_new_array is set to the newly allocated array. */
+int cfg_collapse_array(cfg_group_meta_t *meta, cfg_group_t *group,
+ cfg_group_inst_t *inst,
+ cfg_group_inst_t **_new_array)
+{
+ cfg_group_inst_t *new_array, *old_array;
+ int inst_size, offset;
+
+ if (!meta->num)
+ return -1;
+
+ if (meta->num == 1) {
+ *_new_array = NULL;
+ return 0;
+ }
+
+ inst_size = sizeof(cfg_group_inst_t) + group->size - 1;
+ new_array = (cfg_group_inst_t *)shm_malloc(inst_size * (meta->num - 1));
+ if (!new_array) {
+ LOG(L_ERR, "ERROR: cfg_collapse_array(): not enough shm memory\n");
+ return -1;
+ }
+
+ old_array = meta->array;
+ offset = (char *)inst - (char *)old_array;
+ if (offset)
+ memcpy( new_array,
+ old_array,
+ offset);
+
+ if (meta->num * inst_size > offset + inst_size)
+ memcpy( (char *)new_array + offset,
+ (char *)old_array + offset + inst_size,
+ (meta->num - 1) * inst_size - offset);
+
+ *_new_array = new_array;
+ return 0;
+}
+
/* Find the group instance within the meta-data based on the group_id */
cfg_group_inst_t *cfg_find_group(cfg_group_meta_t *meta, int group_size, unsigned int group_id)
{
@@ -658,7 +699,7 @@ cfg_group_inst_t *cfg_find_group(cfg_group_meta_t *meta, int group_size, unsigne
TODO: improve */
for (i = 0; i < meta->num; i++) {
ginst = (cfg_group_inst_t *)((char *)meta->array
- + (sizeof(cfg_group_meta_t) + group_size - 1) * i);
+ + (sizeof(cfg_group_inst_t) + group_size - 1) * i);
if (ginst->id == group_id)
return ginst;
else if (ginst->id > group_id)
diff --git a/cfg/cfg_struct.h b/cfg/cfg_struct.h
index 65519e2..5f1fa0a 100644
--- a/cfg/cfg_struct.h
+++ b/cfg/cfg_struct.h
@@ -381,6 +381,13 @@ cfg_group_inst_t *cfg_extend_array(cfg_group_meta_t *meta, cfg_group_t *group,
unsigned int group_id,
cfg_group_inst_t **new_group);
+/* Remove an instance from a group array.
+ * inst must point to an instance within meta->array.
+ * *_new_array is set to the newly allocated array. */
+int cfg_collapse_array(cfg_group_meta_t *meta, cfg_group_t *group,
+ cfg_group_inst_t *inst,
+ cfg_group_inst_t **_new_array);
+
/* clones a string to shared memory */
int cfg_clone_str(str *src, str *dst);
Module: sip-router
Branch: tirpi/cfg_framework_multivalue
Commit: 99b680c32a92d5d528b7b4375ed8c2974221bc45
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=99b680c…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Tue Sep 14 15:49:25 2010 +0200
cfg framework: error messages added
When a group instance is deleted while there are pending changes
to this instance which are not yet committed, the commit failed
without any error. An error message is added, and cfg_diff_next returns
also error in this case to let the drivers farther propagate the error.
---
cfg/cfg_ctx.c | 13 ++++++++++---
cfg/cfg_ctx.h | 13 +++++++++++--
2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/cfg/cfg_ctx.c b/cfg/cfg_ctx.c
index 9413d75..534cf49 100644
--- a/cfg/cfg_ctx.c
+++ b/cfg/cfg_ctx.c
@@ -1027,8 +1027,11 @@ int cfg_commit(cfg_ctx_t *ctx)
group = changed->group;
if (!(CFG_GROUP_META(block, group)->array =
cfg_clone_array(CFG_GROUP_META(*cfg_global, group), group))
- )
+ ) {
+ LOG(L_ERR, "ERROR: cfg_set_now(): group array cannot be cloned for %.*s[%u]\n",
+ group->name_len, group->name, changed->group_id);
goto error;
+ }
replaced[replaced_num] = CFG_GROUP_META(*cfg_global, group)->array;
replaced_num++;
@@ -1318,6 +1321,10 @@ int cfg_diff_init(cfg_ctx_t *ctx,
/* return the pending changes that have not been
* committed yet
+ * return value:
+ * 1: valid value is found
+ * 0: no more changed value found
+ * -1: error occured
*/
int cfg_diff_next(void **h,
str *gname, unsigned int **gid, str *vname,
@@ -1348,7 +1355,7 @@ int cfg_diff_next(void **h,
} else {
if (!cfg_local) {
LOG(L_ERR, "ERROR: cfg_diff_next(): Local configuration is missing\n");
- return 0;
+ return -1;
}
group_inst = cfg_find_group(CFG_GROUP_META(cfg_local, changed->group),
changed->group->size,
@@ -1356,7 +1363,7 @@ int cfg_diff_next(void **h,
if (!group_inst) {
LOG(L_ERR, "ERROR: cfg_diff_next(): local group instance %.*s[%u] is not found\n",
changed->group->name_len, changed->group->name, changed->group_id);
- return 0;
+ return -1;
}
pval = (union cfg_var_value*)
(group_inst->vars + changed->var->offset);
diff --git a/cfg/cfg_ctx.h b/cfg/cfg_ctx.h
index 1bfd348..8a0836e 100644
--- a/cfg/cfg_ctx.h
+++ b/cfg/cfg_ctx.h
@@ -157,19 +157,28 @@ int cfg_diff_init(cfg_ctx_t *ctx,
/*! \brief return the pending changes that have not been
* committed yet
+ * return value:
+ * 1: valid value is found
+ * 0: no more changed value found
+ * -1: error occured
+ *
*
* can be used as follows:
*
* void *handle;
* if (cfg_diff_init(ctx, &handle)) return -1
- * while (cfg_diff_next(&handle
+ * while ((err = cfg_diff_next(&handle
* &group_name, &group_id, &var_name,
* &old_val, &new_val
- * &val_type)
+ * &val_type)) > 0
* ) {
* ...
* }
* cfg_diff_release(ctx);
+ * if (err) {
+ * error occured, the changes cannot be retrieved
+ * ...
+ * }
*/
int cfg_diff_next(void **h,
str *gname, unsigned int **gid, str *vname,
Module: sip-router
Branch: tirpi/cfg_framework_multivalue
Commit: 28d46c65eaecd623a5e472522fc53564730fe2c8
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=28d46c6…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Wed Sep 8 15:26:59 2010 +0200
cfg framework: cfg_add_group_inst() added
The function can add a new group instance to an existing group.
The values of the new instance are identical to the default values
of the group. After the new group instance is added, the values can be
changed by cfg_set_now().
---
cfg/cfg_ctx.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
cfg/cfg_struct.c | 49 +++++++++++++++++++++++++--
cfg/cfg_struct.h | 6 +++
3 files changed, 146 insertions(+), 4 deletions(-)
diff --git a/cfg/cfg_ctx.c b/cfg/cfg_ctx.c
index cc64a0d..1ca2ec9 100644
--- a/cfg/cfg_ctx.c
+++ b/cfg/cfg_ctx.c
@@ -593,6 +593,7 @@ error:
if (block) cfg_block_free(block);
if (new_array) shm_free(new_array);
if (child_cb) cfg_child_cb_free(child_cb);
+ if (replaced) shm_free(replaced);
error0:
LOG(L_ERR, "ERROR: cfg_set_now(): failed to set the variable: %.*s.%.*s\n",
@@ -1219,3 +1220,97 @@ void cfg_diff_release(cfg_ctx_t *ctx)
CFG_CTX_UNLOCK(ctx);
}
+
+/* Add a new instance to an existing group */
+int cfg_add_group_inst(cfg_ctx_t *ctx, str *group_name, unsigned int group_id)
+{
+ cfg_group_t *group;
+ cfg_block_t *block = NULL;
+ void **replaced = NULL;
+ cfg_group_inst_t *new_array = NULL, *new_inst;
+
+ /* verify the context even if we do not need it now
+ to make sure that a cfg driver has called the function
+ (very very weak security) */
+ if (!ctx) {
+ LOG(L_ERR, "ERROR: cfg_add_group_inst(): context is undefined\n");
+ return -1;
+ }
+
+ if (!cfg_shmized) {
+ /* TODO: Add a new fake variable belonging to
+ the additional group instance to the linked list. */
+ return -1;
+ }
+
+ if (!(group = cfg_lookup_group(group_name->s, group_name->len))) {
+ LOG(L_ERR, "ERROR: cfg_add_group_inst(): group not found\n");
+ return -1;
+ }
+
+ /* make sure that nobody else replaces the global config
+ while the new one is prepared */
+ CFG_WRITER_LOCK();
+ if (cfg_find_group(CFG_GROUP_META(*cfg_global, group),
+ group->size,
+ group_id)
+ ) {
+ LOG(L_DBG, "DEBUG: cfg_add_group_inst(): the group instance already exists\n");
+ CFG_WRITER_UNLOCK();
+ return 0; /* not an error */
+ }
+
+ /* clone the global memory block because the additional array can be
+ replaced only together with the block. */
+ if (!(block = cfg_clone_global()))
+ goto error;
+
+ /* Extend the array with a new group instance */
+ if (!(new_array = cfg_extend_array(CFG_GROUP_META(*cfg_global, group), group,
+ group_id,
+ &new_inst))
+ )
+ goto error;
+
+ /* fill in the new group instance with the default data */
+ memcpy( new_inst->vars,
+ CFG_GROUP_DATA(*cfg_global, group),
+ sizeof(cfg_group_inst_t) + group->size - 1);
+
+ CFG_GROUP_META(block, group)->array = new_array;
+
+ if (CFG_GROUP_META(*cfg_global, group)->array) {
+ /* prepare the array of the replaced strings,
+ and replaced group instances,
+ they will be freed when the old block is freed */
+ replaced = (void **)shm_malloc(sizeof(void *) * 2);
+ if (!replaced) {
+ LOG(L_ERR, "ERROR: cfg_add_group_inst(): not enough shm memory\n");
+ goto error;
+ }
+ replaced[0] = CFG_GROUP_META(*cfg_global, group)->array;
+ replaced[1] = NULL;
+ }
+ /* replace the global config with the new one */
+ cfg_install_global(block, replaced, NULL, NULL);
+ CFG_WRITER_UNLOCK();
+
+ LOG(L_INFO, "INFO: cfg_add_group_inst(): "
+ "group instance is added: %.*s[%u]\n",
+ group_name->len, group_name->s,
+ group_id);
+
+ return 0;
+error:
+ CFG_WRITER_UNLOCK();
+ if (block) cfg_block_free(block);
+ if (new_array) shm_free(new_array);
+ if (replaced) shm_free(replaced);
+
+ LOG(L_ERR, "ERROR: cfg_add_group_inst(): "
+ "Failed to add the group instance: %.*s[%u]\n",
+ group_name->len, group_name->s,
+ group_id);
+
+ return -1;
+}
diff --git a/cfg/cfg_struct.c b/cfg/cfg_struct.c
index 3e92080..77d7cf5 100644
--- a/cfg/cfg_struct.c
+++ b/cfg/cfg_struct.c
@@ -584,9 +584,7 @@ cfg_block_t *cfg_clone_global(void)
return block;
}
-/* Clone an array of configuration group instances.
- * WARNING: unsafe, cfg_writer_lock or cfg_global_lock must be held!
- */
+/* Clone an array of configuration group instances. */
cfg_group_inst_t *cfg_clone_array(cfg_group_meta_t *meta, cfg_group_t *group)
{
cfg_group_inst_t *new_array;
@@ -606,6 +604,47 @@ cfg_group_inst_t *cfg_clone_array(cfg_group_meta_t *meta, cfg_group_t *group)
return new_array;
}
+/* Extend the array of configuration group instances with one more instance.
+ * Only the ID of the new group is set, nothing else. */
+cfg_group_inst_t *cfg_extend_array(cfg_group_meta_t *meta, cfg_group_t *group,
+ unsigned int group_id,
+ cfg_group_inst_t **new_group)
+{
+ int i;
+ cfg_group_inst_t *new_array, *old_array;
+ int inst_size;
+
+ inst_size = sizeof(cfg_group_inst_t) + group->size - 1;
+ new_array = (cfg_group_inst_t *)shm_malloc(inst_size * (meta->num + 1));
+ if (!new_array) {
+ LOG(L_ERR, "ERROR: cfg_extend_array(): not enough shm memory\n");
+ return NULL;
+ }
+ /* Find the position of the new group in the array. The array is ordered
+ by the group IDs. */
+ old_array = meta->array;
+ for ( i = 0;
+ (i < meta->num)
+ && (((cfg_group_inst_t *)((char *)old_array + inst_size * i))->id < group_id);
+ i++
+ );
+ if (i > 0)
+ memcpy( new_array,
+ old_array,
+ inst_size * i);
+
+ memset((char*)new_array + inst_size * i, 0, inst_size);
+ *new_group = (cfg_group_inst_t *)((char*)new_array + inst_size * i);
+ (*new_group)->id = group_id;
+
+ if (i < meta->num)
+ memcpy( (char*)new_array + inst_size * (i + 1),
+ (char*)old_array + inst_size * i,
+ inst_size * (meta->num - i));
+
+ return new_array;
+}
+
/* Find the group instance within the meta-data based on the group_id */
cfg_group_inst_t *cfg_find_group(cfg_group_meta_t *meta, int group_size, unsigned int group_id)
{
@@ -615,13 +654,15 @@ cfg_group_inst_t *cfg_find_group(cfg_group_meta_t *meta, int group_size, unsigne
if (!meta)
return NULL;
- /* For now, search lineray till the end of the array.
+ /* For now, search lineray.
TODO: improve */
for (i = 0; i < meta->num; i++) {
ginst = (cfg_group_inst_t *)((char *)meta->array
+ (sizeof(cfg_group_meta_t) + group_size - 1) * i);
if (ginst->id == group_id)
return ginst;
+ else if (ginst->id > group_id)
+ break; /* needless to continue, the array is ordered */
}
return NULL;
}
diff --git a/cfg/cfg_struct.h b/cfg/cfg_struct.h
index 58cd810..65519e2 100644
--- a/cfg/cfg_struct.h
+++ b/cfg/cfg_struct.h
@@ -375,6 +375,12 @@ cfg_block_t *cfg_clone_global(void);
/* Clone an array of configuration group instances. */
cfg_group_inst_t *cfg_clone_array(cfg_group_meta_t *meta, cfg_group_t *group);
+/* Extend the array of configuration group instances with one more instance.
+ * Only the ID of the new group is set, nothing else. */
+cfg_group_inst_t *cfg_extend_array(cfg_group_meta_t *meta, cfg_group_t *group,
+ unsigned int group_id,
+ cfg_group_inst_t **new_group);
+
/* clones a string to shared memory */
int cfg_clone_str(str *src, str *dst);
Module: sip-router
Branch: tirpi/cfg_framework_multivalue
Commit: 5d4d6ae9ed9848d92e10e746a8d870833b5c683d
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=5d4d6ae…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Thu Sep 9 12:56:58 2010 +0200
cfg framework: group instance support in cfg_get_by_name() + bugfix
- cfg_get_by_name() can return the value from both the default or from
a specific group instance.
- bugfix: cfg_add_group_inst() overwrote a larger memory area then the group size.
- More verbose log messages when the group instance is not found.
---
cfg/cfg_ctx.c | 36 ++++++++++++++++++++++++++++--------
cfg/cfg_ctx.h | 5 ++++-
2 files changed, 32 insertions(+), 9 deletions(-)
diff --git a/cfg/cfg_ctx.c b/cfg/cfg_ctx.c
index 480fab5..b0fa851 100644
--- a/cfg/cfg_ctx.c
+++ b/cfg/cfg_ctx.c
@@ -387,7 +387,8 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *va
group->size,
*group_id);
if (!group_inst) {
- LOG(L_ERR, "ERROR: cfg_set_now(): local group instance is not found\n");
+ LOG(L_ERR, "ERROR: cfg_set_now(): local group instance %.*s[%u] is not found\n",
+ group_name->len, group_name->s, *group_id);
goto error0;
}
var_block = group_inst->vars;
@@ -432,7 +433,8 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *va
group->size,
*group_id);
if (!group_inst) {
- LOG(L_ERR, "ERROR: cfg_set_now(): global group instance is not found\n");
+ LOG(L_ERR, "ERROR: cfg_set_now(): global group instance %.*s[%u] is not found\n",
+ group_name->len, group_name->s, *group_id);
goto error;
}
var_block = group_inst->vars;
@@ -1038,7 +1040,7 @@ int cfg_rollback(cfg_ctx_t *ctx)
* -1 - error
* 1 - variable exists, but it is not readable
*/
-int cfg_get_by_name(cfg_ctx_t *ctx, str *group_name, str *var_name,
+int cfg_get_by_name(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
void **val, unsigned int *val_type)
{
cfg_group_t *group;
@@ -1046,6 +1048,7 @@ int cfg_get_by_name(cfg_ctx_t *ctx, str *group_name, str *var_name,
void *p;
static str s; /* we need the value even
after the function returns */
+ cfg_group_inst_t *group_inst;
/* verify the context even if we do not need it now
to make sure that a cfg driver has called the function
@@ -1066,10 +1069,27 @@ int cfg_get_by_name(cfg_ctx_t *ctx, str *group_name, str *var_name,
return 1;
}
- /* use the module's handle to access the variable
- It means that the variable is read from the local config
- after forking */
- p = *(group->handle) + var->offset;
+ if (group_id) {
+ if (!cfg_local) {
+ LOG(L_ERR, "ERROR: cfg_get_by_name(): Local configuration is missing\n");
+ return -1;
+ }
+ group_inst = cfg_find_group(CFG_GROUP_META(cfg_local, group),
+ group->size,
+ *group_id);
+ if (!group_inst) {
+ LOG(L_ERR, "ERROR: cfg_get_by_name(): local group instance %.*s[%u] is not found\n",
+ group_name->len, group_name->s, *group_id);
+ return -1;
+ }
+ p = group_inst->vars + var->offset;
+
+ } else {
+ /* use the module's handle to access the variable
+ It means that the variable is read from the local config
+ after forking */
+ p = *(group->handle) + var->offset;
+ }
switch (CFG_VAR_TYPE(var)) {
case CFG_VAR_INT:
@@ -1278,7 +1298,7 @@ int cfg_add_group_inst(cfg_ctx_t *ctx, str *group_name, unsigned int group_id)
/* fill in the new group instance with the default data */
memcpy( new_inst->vars,
CFG_GROUP_DATA(*cfg_global, group),
- sizeof(cfg_group_inst_t) + group->size - 1);
+ group->size);
CFG_GROUP_META(block, group)->array = new_array;
CFG_GROUP_META(block, group)->num++;
diff --git a/cfg/cfg_ctx.h b/cfg/cfg_ctx.h
index 0e2299f..255911e 100644
--- a/cfg/cfg_ctx.h
+++ b/cfg/cfg_ctx.h
@@ -110,7 +110,7 @@ int cfg_commit(cfg_ctx_t *ctx);
int cfg_rollback(cfg_ctx_t *ctx);
/*! \brief returns the value of a variable */
-int cfg_get_by_name(cfg_ctx_t *ctx, str *group_name, str *var_name,
+int cfg_get_by_name(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
void **val, unsigned int *val_type);
/*! \brief returns the description of a variable */
@@ -177,4 +177,7 @@ int cfg_diff_next(void **h,
/*! \brief destroy the handle of cfg_diff_next() */
void cfg_diff_release(cfg_ctx_t *ctx);
+/* Add a new instance to an existing group */
+int cfg_add_group_inst(cfg_ctx_t *ctx, str *group_name, unsigned int group_id);
+
#endif /* _CFG_CTX_H */
Module: sip-router
Branch: tirpi/cfg_framework_multivalue
Commit: 6a44d0bd28c2cb896b9e53f7974d1bad88654c24
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=6a44d0b…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Tue Sep 7 17:09:07 2010 +0200
cfg framework: cfg_set_now() supports the group instances
cfg_set_now() can write the variables within both
the default and the additional group instances.
If the additional variable is not explicitely set, then
the default value overwrites it.
Note: the group instance must exist before cfg_set_now() is called,
it is not created dynamicaly.
The function does not work yet before the config is shmized.
---
cfg/cfg.c | 1 +
cfg/cfg_ctx.c | 228 +++++++++++++++++++++++++++++++++++++++++++-----------
cfg/cfg_ctx.h | 22 ++++--
cfg/cfg_script.c | 1 +
cfg/cfg_script.h | 1 +
cfg/cfg_struct.c | 48 +++++++++++-
cfg/cfg_struct.h | 50 +++++++++++-
7 files changed, 293 insertions(+), 58 deletions(-)
Diff: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commitdiff;h=6a4…