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