[sr-dev] git:tirpi/cfg_framework_multivalue: cfg framework: group instance support before forking

Miklos Tirpak miklos at iptel.org
Tue Sep 28 11:51:08 CEST 2010


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=eddc94d703afb2685ffd6162ddd29a4fef464c2d

Author: Miklos Tirpak <miklos at iptel.org>
Committer: Miklos Tirpak <miklos at 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 */




More information about the sr-dev mailing list