Browse Source

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
Miklos Tirpak 16 years ago
parent
commit
bcf3fff938
4 changed files with 171 additions and 3 deletions
  1. 2 2
      cfg/cfg_ctx.c
  2. 4 0
      cfg/cfg_ctx.h
  3. 141 1
      cfg/cfg_select.c
  4. 24 0
      cfg/cfg_select.h

+ 2 - 2
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;
 	}

+ 4 - 0
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

+ 141 - 1
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;
+}

+ 24 - 0
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 */