Browse code

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 authored on 30/06/2009 15:33:52
Showing 4 changed files
... ...
@@ -129,7 +129,7 @@ void cfg_notify_drivers(char *group_name, int group_name_len, cfg_def_t *def)
129 129
 static char	*temp_string = NULL;
130 130
 
131 131
 /* convert the value to the requested type */
132
-static int convert_val(unsigned int val_type, void *val,
132
+int convert_val(unsigned int val_type, void *val,
133 133
 			unsigned int var_type, void **new_val)
134 134
 {
135 135
 	static str	s;
... ...
@@ -482,7 +482,7 @@ static int cfg_var_size(cfg_mapping_t *var)
482 482
 		return sizeof(void *);
483 483
 
484 484
 	default:
485
-		LOG(L_CRIT, "BUG: cfg_var_sizeK(): unknown type: %u\n",
485
+		LOG(L_CRIT, "BUG: cfg_var_size(): unknown type: %u\n",
486 486
 			CFG_VAR_TYPE(var));
487 487
 		return 0;
488 488
 	}
... ...
@@ -108,6 +108,10 @@ int cfg_help(cfg_ctx_t *ctx, str *group_name, str *var_name,
108 108
 /* notify the drivers about the new config definition */
109 109
 void cfg_notify_drivers(char *group_name, int group_name_len, cfg_def_t *def);
110 110
 
111
+/* convert the value to the requested type */
112
+int convert_val(unsigned int val_type, void *val,
113
+			unsigned int var_type, void **new_val);
114
+
111 115
 /* initialize the handle for cfg_get_group_next() */
112 116
 #define cfg_get_group_init(handle) \
113 117
 	(*(handle)) = (void *)cfg_group
... ...
@@ -33,6 +33,7 @@
33 33
 #include "../select.h"
34 34
 #include "../ut.h"
35 35
 #include "cfg_struct.h"
36
+#include "cfg_ctx.h"
36 37
 #include "cfg_select.h"
37 38
 
38 39
 /* 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)
200 200
 	if (!group || !var) return -1;
201 201
 
202 202
 	/* use the module's handle to access the variable, so the variables
203
-	are read from private memory */
203
+	are read from the local config */
204 204
 	p = *(group->handle) + var->offset;
205 205
 
206 206
 	switch (CFG_VAR_TYPE(var)) {
... ...
@@ -220,6 +221,145 @@ int select_cfg_var(str *res, select_t *s, struct sip_msg *msg)
220 220
 		memcpy(res, p, sizeof(str));
221 221
 		break;
222 222
 
223
+	default:
224
+		LOG(L_DBG, "DEBUG: select_cfg_var(): unsupported variable type: %d\n",
225
+			CFG_VAR_TYPE(var));
226
+		return -1;
223 227
 	}
224 228
 	return 0;
225 229
 }
230
+
231
+/* fix-up function for read_cfg_var()
232
+ *
233
+ * return value:
234
+ * >0 - success
235
+ *  0 - the variable has not been declared yet, but it will be automatically
236
+ *	fixed-up later.
237
+ * <0 - error
238
+ */
239
+int read_cfg_var_fixup(char *gname, char *vname, struct cfg_read_handle *read_handle)
240
+{
241
+	cfg_group_t	*group;
242
+	cfg_mapping_t	*var;
243
+	str		group_name, var_name;
244
+
245
+	if (!gname || !vname || !read_handle)
246
+		return -1;
247
+
248
+	group_name.s = gname;
249
+	group_name.len = strlen(gname);
250
+	var_name.s = vname;
251
+	var_name.len = strlen(vname);
252
+
253
+	/* look-up the group and the variable */
254
+	if (cfg_lookup_var(&group_name, &var_name, &group, &var)) {
255
+		if (cfg_shmized) {
256
+			LOG(L_ERR, "ERROR: read_cfg_var_fixup(): unknown variable: %.*s.%.*s\n",
257
+				group_name.len, group_name.s,
258
+				var_name.len, var_name.s);
259
+			return -1;
260
+		}
261
+		/* The variable was not found, add it to the non-fixed select list.
262
+		 * So we act as if the fixup was successful, and we retry it later */
263
+		if (cfg_new_select(&group_name, &var_name,
264
+					&read_handle->group, &read_handle->var))
265
+			return -1;
266
+
267
+		LOG(L_DBG, "DEBUG: read_cfg_var_fixup(): cfg read fixup is postponed: %.*s.%.*s\n",
268
+			group_name.len, group_name.s,
269
+			var_name.len, var_name.s);
270
+
271
+		read_handle->group = NULL;
272
+		read_handle->var = NULL;
273
+		return 0;
274
+	}
275
+
276
+	if (var->def->on_change_cb) {
277
+		/* fixup function is defined -- safer to return an error
278
+		than an incorrect value */
279
+		LOG(L_ERR, "ERROR: read_cfg_var_fixup(): variable cannot be retrieved\n");
280
+		return -1;
281
+	}
282
+
283
+	read_handle->group = (void *)group;
284
+	read_handle->var = (void *)var;
285
+	return 1;
286
+}
287
+
288
+/* read the value of a variable via a group and variable name previously fixed up
289
+ * Returns the type of the variable
290
+ */
291
+unsigned int read_cfg_var(struct cfg_read_handle *read_handle, void **val)
292
+{
293
+	cfg_group_t	*group;
294
+	cfg_mapping_t	*var;
295
+	void		*p;
296
+	static str	s;
297
+
298
+	if (!val || !read_handle || !read_handle->group || !read_handle->var)
299
+		return 0;
300
+
301
+	group = (cfg_group_t *)(read_handle->group);
302
+	var = (cfg_mapping_t *)(read_handle->var);
303
+
304
+	/* use the module's handle to access the variable, so the variables
305
+	are read from the local config */
306
+	p = *(group->handle) + var->offset;
307
+
308
+	switch (CFG_VAR_TYPE(var)) {
309
+	case CFG_VAR_INT:
310
+		*val = (void *)(long)*(int *)p;
311
+		break;
312
+
313
+	case CFG_VAR_STRING:
314
+		*val = (void *)*(char **)p;
315
+		break;
316
+
317
+	case CFG_VAR_STR:
318
+		memcpy(&s, p, sizeof(str));
319
+		*val = (void *)&s;
320
+		break;
321
+
322
+	case CFG_VAR_POINTER:
323
+		*val = *(void **)p;
324
+		break;
325
+
326
+	}
327
+	return CFG_VAR_TYPE(var);
328
+}
329
+
330
+/* wrapper function for read_cfg_var() -- convert the value to integer
331
+ * returns -1 on error, 0 on success
332
+ */
333
+int read_cfg_var_int(struct cfg_read_handle *read_handle, int *val)
334
+{
335
+	unsigned int	type;
336
+	void		*v1, *v2;
337
+
338
+	if ((type = read_cfg_var(read_handle, &v1)) == 0)
339
+		return -1;
340
+
341
+	if (convert_val(type, v1, CFG_INPUT_INT, &v2))
342
+		return -1;
343
+
344
+	*val = (int)(long)(v2);
345
+	return 0;
346
+}
347
+
348
+/* wrapper function for read_cfg_var() -- convert the value to str
349
+ * returns -1 on error, 0 on success
350
+ */
351
+int read_cfg_var_str(struct cfg_read_handle *read_handle, str *val)
352
+{
353
+	unsigned int	type;
354
+	void		*v1, *v2;
355
+
356
+	if ((type = read_cfg_var(read_handle, &v1)) == 0)
357
+		return -1;
358
+
359
+	if (convert_val(type, v1, CFG_INPUT_STR, &v2))
360
+		return -1;
361
+
362
+	*val = *(str *)(v2);
363
+	return 0;
364
+}
... ...
@@ -34,6 +34,11 @@
34 34
 
35 35
 #include "../select.h"
36 36
 
37
+struct cfg_read_handle {
38
+	void	*group;
39
+	void	*var;
40
+};
41
+
37 42
 /* free the list of not yet fixed selects */
38 43
 void cfg_free_selects();
39 44
 
... ...
@@ -42,4 +47,23 @@ int cfg_fixup_selects();
42 42
 
43 43
 int select_cfg_var(str *res, select_t *s, struct sip_msg *msg);
44 44
 
45
+/* fix-up function for read_cfg_var()
46
+ *
47
+ * return value:
48
+ * >0 - success
49
+ *  0 - the variable has not been declared yet, but it will be automatically
50
+ *	fixed-up later.
51
+ * <0 - error
52
+ */
53
+int read_cfg_var_fixup(char *gname, char *vname, struct cfg_read_handle *read_handle);
54
+
55
+/* read the value of a variable via a group and variable name previously fixed up
56
+ * Returns the type of the variable
57
+ */
58
+unsigned int read_cfg_var(struct cfg_read_handle *read_handle, void **val);
59
+
60
+/* wrapper functions for read_cfg_var() -- convert the value to the requested format */
61
+int read_cfg_var_int(struct cfg_read_handle *read_handle, int *val);
62
+int read_cfg_var_str(struct cfg_read_handle *read_handle, str *val);
63
+
45 64
 #endif /* _CFG_SELECT_H */