Module: sip-router Branch: tirpi/cfg_framework_multivalue Commit: eddc94d703afb2685ffd6162ddd29a4fef464c2d URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=eddc94d7...
Author: Miklos Tirpak miklos@iptel.org Committer: Miklos Tirpak miklos@iptel.org Date: Mon Sep 27 16:03:13 2010 +0200
cfg framework: group instance support before forking
The new group instances, and their variables are stored in a list which is linked to the group before the config is shmized. After all the variables are known, this list can be changed to memory blocks.
---
cfg/cfg_ctx.c | 14 +++--- cfg/cfg_struct.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ cfg/cfg_struct.h | 10 ++++ 3 files changed, 150 insertions(+), 6 deletions(-)
diff --git a/cfg/cfg_ctx.c b/cfg/cfg_ctx.c index 5fa961d..e94d678 100644 --- a/cfg/cfg_ctx.c +++ b/cfg/cfg_ctx.c @@ -332,8 +332,8 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *va but an additional instance of a variable needs to be added to the group. Add this instance to the linked list of variables, they will be fixed later. */ - /* TODO */ - return -1; + return new_add_var(group_name, *group_id, var_name, + val, val_type); }
/* look-up the group and the variable */ @@ -686,7 +686,7 @@ int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str && var->def->on_set_child_cb && var->def->type & CFG_CB_ONLY_ONCE ) { - LOG(L_ERR, "ERROR: cfg_set_now(): This variable does not support muliple values.\n"); + LOG(L_ERR, "ERROR: cfg_set_delayed(): This variable does not support muliple values.\n"); goto error0; }
@@ -1427,9 +1427,11 @@ int cfg_add_group_inst(cfg_ctx_t *ctx, str *group_name, unsigned int group_id) }
if (!cfg_shmized) { - /* TODO: Add a new fake variable belonging to - the additional group instance to the linked list. */ - return -1; + /* Add a new variable without any value to + the linked list of additional values. This variable + will force a new group instance to be created. */ + return new_add_var(group_name, group_id, NULL /* var_name */, + NULL /* val */, 0 /* type */); }
if (!(group = cfg_lookup_group(group_name->s, group_name->len))) { diff --git a/cfg/cfg_struct.c b/cfg/cfg_struct.c index d34ed06..aa4c005 100644 --- a/cfg/cfg_struct.c +++ b/cfg/cfg_struct.c @@ -56,6 +56,10 @@ cfg_child_cb_t **cfg_child_cb_first = NULL; /* first item of the per-child proce cfg_child_cb_t **cfg_child_cb_last = NULL; /* last item of the above list */ cfg_child_cb_t *cfg_child_cb = NULL; /* pointer to the previously executed cb */
+ +/* forward declarations */ +static void del_add_var_list(cfg_group_t *group); + /* creates a new cfg group, and adds it to the linked list */ cfg_group_t *cfg_new_group(char *name, int name_len, int num, cfg_mapping_t *mapping, @@ -298,6 +302,8 @@ static void cfg_destory_groups(unsigned char *block) pointers are just set to static variables */ if (mapping) pkg_free(mapping); } + /* Delete the additional variable list */ + del_add_var_list(group);
group2 = group->next; pkg_free(group); @@ -824,3 +830,129 @@ void cfg_child_cb_free(cfg_child_cb_t *child_cb_first) shm_free(cb); } } + +/* Allocate memory for a new additional variable + * and link it to a configuration group. + * type==0 results in creating a new group instance with the default values. + * The group is created with CFG_GROUP_UNKNOWN type if it does not exist. + * Note: this function is usable only before the configuration is shmized. + */ +int new_add_var(str *group_name, unsigned int group_id, str *var_name, + void *val, unsigned int type) +{ + cfg_group_t *group; + cfg_add_var_t *add_var = NULL, **add_var_p; + int len; + + LOG(L_DBG, "DEBUG: new_add_var(): declaring a new variable instance %.*s[%u].%.*s\n", + group_name->len, group_name->s, + group_id, + var_name->len, var_name->s); + + if (cfg_shmized) { + LOG(L_ERR, "ERROR: new_add_var(): too late, the configuration has already been shmized\n"); + goto error; + } + + group = cfg_lookup_group(group_name->s, group_name->len); + if (!group) { + /* create a new group with NULL values, it will be filled in later */ + group = cfg_new_group(group_name->s, group_name->len, + 0 /* num */, NULL /* mapping */, + NULL /* vars */, 0 /* size */, NULL /* handle */); + + if (!group) + goto error; + /* It is not yet known whether the group will be static or dynamic */ + group->dynamic = CFG_GROUP_UNKNOWN; + } + + add_var = (cfg_add_var_t *)pkg_malloc(sizeof(cfg_add_var_t) + + (type ? (var_name->len - 1) : 0)); + if (!add_var) { + LOG(L_ERR, "ERROR: new_add_var(): Not enough memory\n"); + goto error; + } + memset(add_var, 0, sizeof(cfg_add_var_t) + + (type ? (var_name->len - 1) : 0)); + + add_var->group_id = group_id; + if (type) { + add_var->name_len = var_name->len; + memcpy(add_var->name, var_name->s, var_name->len); + + switch (type) { + case CFG_VAR_INT: + add_var->val.i = (int)(long)val; + break; + + case CFG_VAR_STR: + len = ((str *)val)->len; + add_var->val.s.s = (char *)pkg_malloc(sizeof(char) * len); + if (!add_var->val.s.s) { + LOG(L_ERR, "ERROR: new_add_var(): Not enough memory\n"); + goto error; + } + add_var->val.s.len = len; + memcpy(add_var->val.s.s, ((str *)val)->s, len); + break; + + case CFG_VAR_STRING: + len = strlen((char *)val); + add_var->val.ch = (char *)pkg_malloc(sizeof(char) * (len + 1)); + if (!add_var->val.ch) { + LOG(L_ERR, "ERROR: new_add_var(): Not enough memory\n"); + goto error; + } + memcpy(add_var->val.ch, (char *)val, len); + add_var->val.ch[len] = '\0'; + break; + + default: + LOG(L_ERR, "ERROR: new_add_var(): unsupported value type: %u\n", + type); + goto error; + } + add_var->type = type; + } + + /* order the list by group_id, it will be easier to count the group instances */ + for( add_var_p = &group->add_var; + *add_var_p && ((*add_var_p)->group_id < group_id); + add_var_p = &((*add_var_p)->next)); + + add_var->next = *add_var_p; + *add_var_p = add_var; + + return 0; + +error: + if (!type) + LOG(L_ERR, "ERROR: new_add_var(): failed to add the additional group instance: %.*s[%u]\n", + group_name->len, group_name->s, group_id); + else + LOG(L_ERR, "ERROR: new_add_var(): failed to add the additional variable instance: %.*s[%u].%.*s\n", + group_name->len, group_name->s, group_id, + var_name->len, var_name->s); + + if (add_var) + pkg_free(add_var); + return -1; +} + +/* delete the additional variable list */ +static void del_add_var_list(cfg_group_t *group) { + cfg_add_var_t *add_var, *add_var2; + + add_var = group->add_var; + while (add_var) { + add_var2 = add_var->next; + if ((add_var->type == CFG_VAR_STR) && add_var->val.s.s) + pkg_free(add_var->val.s.s); + else if ((add_var->type == CFG_VAR_STRING) && add_var->val.ch) + pkg_free(add_var->val.ch); + pkg_free(add_var); + add_var = add_var2; + } + group->add_var = NULL; +} diff --git a/cfg/cfg_struct.h b/cfg/cfg_struct.h index 37d56ca..9f7b9fc 100644 --- a/cfg/cfg_struct.h +++ b/cfg/cfg_struct.h @@ -52,6 +52,7 @@ typedef struct _cfg_add_var { unsigned int type; /*!< type == 0 is also valid, it indicates that the group must be created with the default values */ union { + char *ch; str s; int i; } val; @@ -433,4 +434,13 @@ cfg_child_cb_t *cfg_child_cb_new(str *gname, str *name, /* free the memory allocated for a child cb list */ void cfg_child_cb_free(cfg_child_cb_t *child_cb_first);
+/* Allocate memory for a new additional variable + * and link it to a configuration group. + * type==0 results in creating a new group instance with the default values. + * The group is created with CFG_GROUP_UNKNOWN type if it does not exist. + * Note: this function is usable only before the configuration is shmized. + */ +int new_add_var(str *group_name, unsigned int group_id, str *var_name, + void *val, unsigned int type); + #endif /* _CFG_STRUCT_H */