[sr-dev] git:tirpi/cfg_framework_multivalue: cfg framework: group meta-data introduced

Miklos Tirpak miklos at iptel.org
Tue Sep 14 16:46:29 CEST 2010


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

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




More information about the sr-dev mailing list