[sr-dev] git:master: cfg framework: read variables by name with a handle

Miklos Tirpak miklos at iptel.org
Wed Jul 1 11:06:48 CEST 2009


Module: sip-router
Branch: master
Commit: bcf3fff9389fc06a0fcc92f7e9875b185929987f
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=bcf3fff9389fc06a0fcc92f7e9875b185929987f

Author: Miklos Tirpak <miklos at iptel.org>
Committer: Miklos Tirpak <miklos at iptel.org>
Date:   Tue Jun 30 17:33:52 2009 +0200

cfg framework: read variables by name with a handle

- read_cfg_var() is introduced which allows reading
even the custom declared variables from the modules.
It requires a handle returned by read_cfg_var_fixup()
- read_cfg_var_int() and read_cfg_var_str() are wrapper functions

---

 cfg/cfg_ctx.c    |    4 +-
 cfg/cfg_ctx.h    |    4 ++
 cfg/cfg_select.c |  142 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 cfg/cfg_select.h |   24 +++++++++
 4 files changed, 171 insertions(+), 3 deletions(-)

diff --git a/cfg/cfg_ctx.c b/cfg/cfg_ctx.c
index 04ee5f1..ef3661c 100644
--- a/cfg/cfg_ctx.c
+++ b/cfg/cfg_ctx.c
@@ -129,7 +129,7 @@ void cfg_notify_drivers(char *group_name, int group_name_len, cfg_def_t *def)
 static char	*temp_string = NULL;
 
 /* convert the value to the requested type */
-static int convert_val(unsigned int val_type, void *val,
+int convert_val(unsigned int val_type, void *val,
 			unsigned int var_type, void **new_val)
 {
 	static str	s;
@@ -482,7 +482,7 @@ static int cfg_var_size(cfg_mapping_t *var)
 		return sizeof(void *);
 
 	default:
-		LOG(L_CRIT, "BUG: cfg_var_sizeK(): unknown type: %u\n",
+		LOG(L_CRIT, "BUG: cfg_var_size(): unknown type: %u\n",
 			CFG_VAR_TYPE(var));
 		return 0;
 	}
diff --git a/cfg/cfg_ctx.h b/cfg/cfg_ctx.h
index 07cf734..e738c96 100644
--- a/cfg/cfg_ctx.h
+++ b/cfg/cfg_ctx.h
@@ -108,6 +108,10 @@ int cfg_help(cfg_ctx_t *ctx, str *group_name, str *var_name,
 /* notify the drivers about the new config definition */
 void cfg_notify_drivers(char *group_name, int group_name_len, cfg_def_t *def);
 
+/* convert the value to the requested type */
+int convert_val(unsigned int val_type, void *val,
+			unsigned int var_type, void **new_val);
+
 /* initialize the handle for cfg_get_group_next() */
 #define cfg_get_group_init(handle) \
 	(*(handle)) = (void *)cfg_group
diff --git a/cfg/cfg_select.c b/cfg/cfg_select.c
index 72168d7..45aeb94 100644
--- a/cfg/cfg_select.c
+++ b/cfg/cfg_select.c
@@ -33,6 +33,7 @@
 #include "../select.h"
 #include "../ut.h"
 #include "cfg_struct.h"
+#include "cfg_ctx.h"
 #include "cfg_select.h"
 
 /* It may happen that the select calls cannot be fixed up before shmizing
@@ -200,7 +201,7 @@ int select_cfg_var(str *res, select_t *s, struct sip_msg *msg)
 	if (!group || !var) return -1;
 
 	/* use the module's handle to access the variable, so the variables
-	are read from private memory */
+	are read from the local config */
 	p = *(group->handle) + var->offset;
 
 	switch (CFG_VAR_TYPE(var)) {
@@ -220,6 +221,145 @@ int select_cfg_var(str *res, select_t *s, struct sip_msg *msg)
 		memcpy(res, p, sizeof(str));
 		break;
 
+	default:
+		LOG(L_DBG, "DEBUG: select_cfg_var(): unsupported variable type: %d\n",
+			CFG_VAR_TYPE(var));
+		return -1;
 	}
 	return 0;
 }
+
+/* fix-up function for read_cfg_var()
+ *
+ * return value:
+ * >0 - success
+ *  0 - the variable has not been declared yet, but it will be automatically
+ *	fixed-up later.
+ * <0 - error
+ */
+int read_cfg_var_fixup(char *gname, char *vname, struct cfg_read_handle *read_handle)
+{
+	cfg_group_t	*group;
+	cfg_mapping_t	*var;
+	str		group_name, var_name;
+
+	if (!gname || !vname || !read_handle)
+		return -1;
+
+	group_name.s = gname;
+	group_name.len = strlen(gname);
+	var_name.s = vname;
+	var_name.len = strlen(vname);
+
+	/* look-up the group and the variable */
+	if (cfg_lookup_var(&group_name, &var_name, &group, &var)) {
+		if (cfg_shmized) {
+			LOG(L_ERR, "ERROR: read_cfg_var_fixup(): unknown variable: %.*s.%.*s\n",
+				group_name.len, group_name.s,
+				var_name.len, var_name.s);
+			return -1;
+		}
+		/* The variable was not found, add it to the non-fixed select list.
+		 * So we act as if the fixup was successful, and we retry it later */
+		if (cfg_new_select(&group_name, &var_name,
+					&read_handle->group, &read_handle->var))
+			return -1;
+
+		LOG(L_DBG, "DEBUG: read_cfg_var_fixup(): cfg read fixup is postponed: %.*s.%.*s\n",
+			group_name.len, group_name.s,
+			var_name.len, var_name.s);
+
+		read_handle->group = NULL;
+		read_handle->var = NULL;
+		return 0;
+	}
+
+	if (var->def->on_change_cb) {
+		/* fixup function is defined -- safer to return an error
+		than an incorrect value */
+		LOG(L_ERR, "ERROR: read_cfg_var_fixup(): variable cannot be retrieved\n");
+		return -1;
+	}
+
+	read_handle->group = (void *)group;
+	read_handle->var = (void *)var;
+	return 1;
+}
+
+/* read the value of a variable via a group and variable name previously fixed up
+ * Returns the type of the variable
+ */
+unsigned int read_cfg_var(struct cfg_read_handle *read_handle, void **val)
+{
+	cfg_group_t	*group;
+	cfg_mapping_t	*var;
+	void		*p;
+	static str	s;
+
+	if (!val || !read_handle || !read_handle->group || !read_handle->var)
+		return 0;
+
+	group = (cfg_group_t *)(read_handle->group);
+	var = (cfg_mapping_t *)(read_handle->var);
+
+	/* use the module's handle to access the variable, so the variables
+	are read from the local config */
+	p = *(group->handle) + var->offset;
+
+	switch (CFG_VAR_TYPE(var)) {
+	case CFG_VAR_INT:
+		*val = (void *)(long)*(int *)p;
+		break;
+
+	case CFG_VAR_STRING:
+		*val = (void *)*(char **)p;
+		break;
+
+	case CFG_VAR_STR:
+		memcpy(&s, p, sizeof(str));
+		*val = (void *)&s;
+		break;
+
+	case CFG_VAR_POINTER:
+		*val = *(void **)p;
+		break;
+
+	}
+	return CFG_VAR_TYPE(var);
+}
+
+/* wrapper function for read_cfg_var() -- convert the value to integer
+ * returns -1 on error, 0 on success
+ */
+int read_cfg_var_int(struct cfg_read_handle *read_handle, int *val)
+{
+	unsigned int	type;
+	void		*v1, *v2;
+
+	if ((type = read_cfg_var(read_handle, &v1)) == 0)
+		return -1;
+
+	if (convert_val(type, v1, CFG_INPUT_INT, &v2))
+		return -1;
+
+	*val = (int)(long)(v2);
+	return 0;
+}
+
+/* wrapper function for read_cfg_var() -- convert the value to str
+ * returns -1 on error, 0 on success
+ */
+int read_cfg_var_str(struct cfg_read_handle *read_handle, str *val)
+{
+	unsigned int	type;
+	void		*v1, *v2;
+
+	if ((type = read_cfg_var(read_handle, &v1)) == 0)
+		return -1;
+
+	if (convert_val(type, v1, CFG_INPUT_STR, &v2))
+		return -1;
+
+	*val = *(str *)(v2);
+	return 0;
+}
diff --git a/cfg/cfg_select.h b/cfg/cfg_select.h
index 9f9b186..6a03dd2 100644
--- a/cfg/cfg_select.h
+++ b/cfg/cfg_select.h
@@ -34,6 +34,11 @@
 
 #include "../select.h"
 
+struct cfg_read_handle {
+	void	*group;
+	void	*var;
+};
+
 /* free the list of not yet fixed selects */
 void cfg_free_selects();
 
@@ -42,4 +47,23 @@ int cfg_fixup_selects();
 
 int select_cfg_var(str *res, select_t *s, struct sip_msg *msg);
 
+/* fix-up function for read_cfg_var()
+ *
+ * return value:
+ * >0 - success
+ *  0 - the variable has not been declared yet, but it will be automatically
+ *	fixed-up later.
+ * <0 - error
+ */
+int read_cfg_var_fixup(char *gname, char *vname, struct cfg_read_handle *read_handle);
+
+/* read the value of a variable via a group and variable name previously fixed up
+ * Returns the type of the variable
+ */
+unsigned int read_cfg_var(struct cfg_read_handle *read_handle, void **val);
+
+/* wrapper functions for read_cfg_var() -- convert the value to the requested format */
+int read_cfg_var_int(struct cfg_read_handle *read_handle, int *val);
+int read_cfg_var_str(struct cfg_read_handle *read_handle, str *val);
+
 #endif /* _CFG_SELECT_H */




More information about the sr-dev mailing list