/src/kamailio/src/core/cfg/cfg_struct.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2007 iptelorg GmbH |
3 | | * |
4 | | * This file is part of Kamailio, a free SIP server. |
5 | | * |
6 | | * Kamailio is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU General Public License as published by |
8 | | * the Free Software Foundation; either version 2 of the License, or |
9 | | * (at your option) any later version |
10 | | * |
11 | | * Kamailio is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | * |
20 | | */ |
21 | | |
22 | | #ifndef _CFG_STRUCT_H |
23 | | #define _CFG_STRUCT_H |
24 | | |
25 | | #include "../str.h" |
26 | | #include "../atomic_ops.h" |
27 | | #include "../mem/shm_mem.h" |
28 | | #include "../locking.h" |
29 | | #include "../compiler_opt.h" |
30 | | #include "../bit_test.h" |
31 | | #include "cfg.h" |
32 | | |
33 | | /*! \brief Maximum number of variables within a configuration group. */ |
34 | 0 | #define CFG_MAX_VAR_NUM 256 |
35 | | |
36 | | /*! \brief indicates that the variable has been already shmized */ |
37 | 0 | #define cfg_var_shmized 1U |
38 | | |
39 | | /*! \brief Structure for storing additional values of a variable. |
40 | | * When the config is shmzied, these variables are combined in |
41 | | * an array. |
42 | | */ |
43 | | #pragma pack(push, 1) |
44 | | typedef struct _cfg_add_var |
45 | | { |
46 | | struct _cfg_add_var *next; |
47 | | unsigned int type; /*!< type == 0 is also valid, it indicates that the group |
48 | | must be created with the default values */ |
49 | | unsigned int group_id; /*!< Id of the group instance */ |
50 | | union |
51 | | { |
52 | | char *ch; |
53 | | str s; |
54 | | int i; |
55 | | } val; |
56 | | int name_len; /*!< Name of the variable. The variable may not be known, |
57 | | for example the additional group value is set in the script |
58 | | before the cfg group is declared. Hence, the pointer cannot |
59 | | be stored here. */ |
60 | | char name[1]; |
61 | | } cfg_add_var_t; |
62 | | #pragma pack(pop) |
63 | | |
64 | | /*! \brief structure used for variable - pointer mapping */ |
65 | | typedef struct _cfg_mapping |
66 | | { |
67 | | cfg_def_t *def; /*!< one item of the cfg structure definition */ |
68 | | int name_len; /*!< length of def->name */ |
69 | | |
70 | | /* additional information about the cfg variable */ |
71 | | int pos; /*!< position of the variable within the group starting from 0 */ |
72 | | int offset; /*!< offest within the memory block */ |
73 | | unsigned int flag; /*!< flag indicating the state of the variable */ |
74 | | } cfg_mapping_t; |
75 | | |
76 | | /*! \brief type of the group */ |
77 | | enum |
78 | | { |
79 | | CFG_GROUP_UNKNOWN = 0, |
80 | | CFG_GROUP_DYNAMIC, |
81 | | CFG_GROUP_STATIC |
82 | | }; |
83 | | |
84 | | /*! \brief linked list of registered groups */ |
85 | | #pragma pack(push, 1) |
86 | | typedef struct _cfg_group |
87 | | { |
88 | | cfg_mapping_t *mapping; /*!< describes the mapping betweeen |
89 | | the cfg variable definition and the memory block */ |
90 | | char *vars; /*!< pointer to the memory block where the values |
91 | | are stored -- used only before the config is |
92 | | shmized. */ |
93 | | cfg_add_var_t *add_var; /*!< Additional instances of the variables. |
94 | | This linked list is used only before the config is |
95 | | shmized. */ |
96 | | int num; /*!< number of variables within the group */ |
97 | | int size; /*!< size of the memory block that has to be |
98 | | allocated to store the values */ |
99 | | int meta_offset; /*!< offset of the group within the |
100 | | shmized memory block for the meta_data */ |
101 | | int var_offset; /*!< offset of the group within the |
102 | | shmized memory block for the variables */ |
103 | | void **handle; /*!< per-process handle that can be used |
104 | | by the modules to access the variables. |
105 | | It is registered when the group is created, |
106 | | and updated every time the block is replaced */ |
107 | | void *orig_handle; /*!< Original value that the handle points to |
108 | | when the config group is registered. This is needed |
109 | | to temporary set the handle in the main process and |
110 | | restore it later to its original value. */ |
111 | | |
112 | | struct _cfg_group *next; |
113 | | unsigned int dynamic; /*!< indicates whether the variables within the group |
114 | | are dynamically allocated or not */ |
115 | | int name_len; |
116 | | char name[1]; |
117 | | } cfg_group_t; |
118 | | #pragma pack(pop) |
119 | | |
120 | | /*! \brief One instance of the cfg group variables which stores |
121 | | * the additional values. These values can overwrite the default values. */ |
122 | | #pragma pack(push, 1) |
123 | | typedef struct _cfg_group_inst |
124 | | { |
125 | | unsigned int id; /*!< identifier of the group instance */ |
126 | | unsigned int set[CFG_MAX_VAR_NUM / (sizeof(int) * 8)]; |
127 | | /*!< Bitmap indicating whether or not a value is explicitely set |
128 | | within this instance. If the value is not set, |
129 | | then the default value is used, and copied into this instance. */ |
130 | | unsigned char vars[1]; /*!< block for the values */ |
131 | | } cfg_group_inst_t; |
132 | | #pragma pack(pop) |
133 | | |
134 | | /*! \brief Meta-data which is stored before each variable group |
135 | | * within the blob. This structure is used to handle the multivalue |
136 | | * instances of the variables, i.e. manages the array for the |
137 | | * additional values. */ |
138 | | typedef struct _cfg_group_meta |
139 | | { |
140 | | int num; /*!< Number of items in the array */ |
141 | | cfg_group_inst_t |
142 | | *array; /*!< Array of cfg groups with num number of items */ |
143 | | } cfg_group_meta_t; |
144 | | |
145 | | /*! \brief single memory block that contains all the cfg values */ |
146 | | #pragma pack(push, 1) |
147 | | typedef struct _cfg_block |
148 | | { |
149 | | atomic_t refcnt; /*!< reference counter, |
150 | | the block is automatically deleted |
151 | | when it reaches 0 */ |
152 | | int _pad; /*!< force 8 byte alignment */ |
153 | | unsigned char vars[1]; /*!< blob that contains the values */ |
154 | | } cfg_block_t; |
155 | | #pragma pack(pop) |
156 | | |
157 | | /*! \brief Linked list of per-child process callbacks. |
158 | | * Each child process has a local pointer, and executes the callbacks |
159 | | * when the pointer is not pointing to the end of the list. |
160 | | * Items from the begginning of the list are deleted when the starter |
161 | | * pointer is moved, and no more child process uses them. |
162 | | */ |
163 | | typedef struct _cfg_child_cb |
164 | | { |
165 | | atomic_t refcnt; /*!< number of child processes |
166 | | referring to the element */ |
167 | | atomic_t cb_count; /*!< This counter is used to track |
168 | | * how many times the callback needs |
169 | | * to be executed. |
170 | | * >0 the cb needs to be executed |
171 | | * <=0 the cb no longer needs to be executed |
172 | | */ |
173 | | str gname, name; /*!< name of the variable that has changed */ |
174 | | cfg_on_set_child cb; /*!< callback function that has to be called */ |
175 | | void **replaced; /*!< set of strings and other memory segments |
176 | | that must be freed together with this structure. |
177 | | The content depends on the new config block. |
178 | | This makes sure that the replaced strings are freed |
179 | | after all the child processes release the old configuration. */ |
180 | | |
181 | | struct _cfg_child_cb *next; |
182 | | } cfg_child_cb_t; |
183 | | |
184 | | extern cfg_group_t *cfg_group; |
185 | | extern cfg_block_t **cfg_global; |
186 | | extern cfg_block_t *cfg_local; |
187 | | extern int cfg_block_size; |
188 | | extern gen_lock_t *cfg_global_lock; |
189 | | extern gen_lock_t *cfg_writer_lock; |
190 | | extern int cfg_shmized; |
191 | | extern cfg_child_cb_t **cfg_child_cb_first; |
192 | | extern cfg_child_cb_t **cfg_child_cb_last; |
193 | | extern cfg_child_cb_t *cfg_child_cb; |
194 | | extern int cfg_ginst_count; |
195 | | |
196 | | /* magic value for cfg_child_cb for processes that do not want to |
197 | | execute per-child callbacks */ |
198 | 0 | #define CFG_NO_CHILD_CBS ((void *)(long)(-1)) |
199 | | |
200 | | /* macros for easier variable access */ |
201 | 0 | #define CFG_VAR_TYPE(var) CFG_VAR_MASK((var)->def->type) |
202 | 0 | #define CFG_INPUT_TYPE(var) CFG_INPUT_MASK((var)->def->type) |
203 | | |
204 | | /* get the meta-data of a group from the block */ |
205 | | #define CFG_GROUP_META(block, group) \ |
206 | 0 | ((cfg_group_meta_t *)((block)->vars + (group)->meta_offset)) |
207 | | |
208 | | /* get the data block of a group from the block */ |
209 | | #define CFG_GROUP_DATA(block, group) \ |
210 | 0 | ((unsigned char *)((block)->vars + (group)->var_offset)) |
211 | | |
212 | | /* Test whether a variable is explicitely set in the group instance, |
213 | | * or it uses the default value */ |
214 | | #define CFG_VAR_TEST(group_inst, var) \ |
215 | 0 | bit_test((var)->pos % (sizeof(int) * 8), \ |
216 | 0 | (group_inst)->set + (var)->pos / (sizeof(int) * 8)) |
217 | | |
218 | | /* Test whether a variable is explicitely set in the group instance, |
219 | | * or it uses the default value, and set the flag. */ |
220 | | #define CFG_VAR_TEST_AND_SET(group_inst, var) \ |
221 | 0 | bit_test_and_set((var)->pos % (sizeof(int) * 8), \ |
222 | 0 | (group_inst)->set + (var)->pos / (sizeof(int) * 8)) |
223 | | |
224 | | /* Test whether a variable is explicitely set in the group instance, |
225 | | * or it uses the default value, and reset the flag. */ |
226 | | #define CFG_VAR_TEST_AND_RESET(group_inst, var) \ |
227 | 0 | bit_test_and_reset((var)->pos % (sizeof(int) * 8), \ |
228 | 0 | (group_inst)->set + (var)->pos / (sizeof(int) * 8)) |
229 | | |
230 | | /* Return the group instance pointer from a handle, |
231 | | * or NULL if the handle points to the default configuration block */ |
232 | | #define CFG_HANDLE_TO_GINST(h) \ |
233 | 0 | ((((unsigned char *)(h) < cfg_local->vars) \ |
234 | 0 | || ((unsigned char *)(h) > cfg_local->vars + cfg_block_size)) \ |
235 | 0 | ? (cfg_group_inst_t *)((char *)(h) \ |
236 | 0 | - (unsigned long)&( \ |
237 | 0 | (cfg_group_inst_t *)0) \ |
238 | 0 | ->vars) \ |
239 | 0 | : NULL) |
240 | | |
241 | | /* initiate the cfg framework */ |
242 | | int sr_cfg_init(void); |
243 | | |
244 | | /* destroy the memory allocated for the cfg framework */ |
245 | | void cfg_destroy(void); |
246 | | |
247 | | /* Register num number of child processes that will |
248 | | * keep updating their local configuration. |
249 | | * This function needs to be called from mod_init |
250 | | * before any child process is forked. |
251 | | */ |
252 | | void cfg_register_child(int num); |
253 | | |
254 | | /* per-child process init function. |
255 | | * It needs to be called from the forked process. |
256 | | * cfg_register_child() must be called before this function! |
257 | | */ |
258 | | int cfg_child_init(void); |
259 | | |
260 | | /* Child process init function that can be called |
261 | | * without cfg_register_child(). |
262 | | * Note that the child process may miss some configuration changes. |
263 | | */ |
264 | | int cfg_late_child_init(void); |
265 | | |
266 | | /* per-child init function for non-cb executing processes. |
267 | | * Mark this process as not wanting to execute any per-child config |
268 | | * callback (it will have only limited config functionality, but is useful |
269 | | * when a process needs only to watch some non-callback cfg. values, |
270 | | * e.g. the main attendant process, debug and memlog). |
271 | | * It needs to be called from the forked process. |
272 | | * cfg_register_child must _not_ be called. |
273 | | */ |
274 | | int cfg_child_no_cb_init(void); |
275 | | |
276 | | /* per-child process destroy function |
277 | | * Should be called only when the child process exits, |
278 | | * but SER continues running. |
279 | | * |
280 | | * WARNING: this function call must be the very last action |
281 | | * before the child process exits, because the local config |
282 | | * is not available afterwards. |
283 | | */ |
284 | | void cfg_child_destroy(void); |
285 | | |
286 | | /* creates a new cfg group, and adds it to the linked list */ |
287 | | cfg_group_t *cfg_new_group(char *name, int name_len, int num, |
288 | | cfg_mapping_t *mapping, char *vars, int size, void **handle); |
289 | | |
290 | | /* Set the values of an existing cfg group. */ |
291 | | void cfg_set_group(cfg_group_t *group, int num, cfg_mapping_t *mapping, |
292 | | char *vars, int size, void **handle); |
293 | | |
294 | | /* copy the variables to shm mem */ |
295 | | int cfg_shmize(void); |
296 | | |
297 | | /* free the memory of a child cb structure */ |
298 | | static inline void cfg_child_cb_free_item(cfg_child_cb_t *cb) |
299 | 0 | { |
300 | 0 | int i; |
301 | | |
302 | | /* free the changed variables */ |
303 | 0 | if(cb->replaced) { |
304 | 0 | for(i = 0; cb->replaced[i]; i++) |
305 | 0 | shm_free(cb->replaced[i]); |
306 | 0 | shm_free(cb->replaced); |
307 | 0 | } |
308 | 0 | shm_free(cb); |
309 | 0 | } Unexecuted instantiation: main.c:cfg_child_cb_free_item Unexecuted instantiation: route.c:cfg_child_cb_free_item Unexecuted instantiation: tcp_main.c:cfg_child_cb_free_item Unexecuted instantiation: tcp_read.c:cfg_child_cb_free_item Unexecuted instantiation: timer.c:cfg_child_cb_free_item Unexecuted instantiation: timer_proc.c:cfg_child_cb_free_item Unexecuted instantiation: udp_server.c:cfg_child_cb_free_item Unexecuted instantiation: action.c:cfg_child_cb_free_item Unexecuted instantiation: async_task.c:cfg_child_cb_free_item Unexecuted instantiation: cfg.c:cfg_child_cb_free_item Unexecuted instantiation: cfg_ctx.c:cfg_child_cb_free_item Unexecuted instantiation: cfg_script.c:cfg_child_cb_free_item Unexecuted instantiation: cfg_select.c:cfg_child_cb_free_item Unexecuted instantiation: cfg_struct.c:cfg_child_cb_free_item |
310 | | |
311 | 0 | #define cfg_block_free(block) shm_free(block) |
312 | | |
313 | | /* Move the group handle to the specified group instance pointed by dst_ginst. |
314 | | * src_ginst shall point to the active group instance. |
315 | | * Both parameters can be NULL meaning that the src/dst config is the default, |
316 | | * not an additional group instance. |
317 | | * The function executes all the per-child process callbacks which are different |
318 | | * in the two instances. |
319 | | */ |
320 | | void cfg_move_handle(cfg_group_t *group, cfg_group_inst_t *src_ginst, |
321 | | cfg_group_inst_t *dst_ginst); |
322 | | |
323 | | |
324 | | /* lock and unlock the global cfg block -- used only at the |
325 | | * very last step when the block is replaced */ |
326 | 0 | #define CFG_LOCK() lock_get(cfg_global_lock); |
327 | 0 | #define CFG_UNLOCK() lock_release(cfg_global_lock); |
328 | | |
329 | | /* lock and unlock used by the cfg drivers to make sure that |
330 | | * only one driver process is considering replacing the global |
331 | | * cfg block */ |
332 | 0 | #define CFG_WRITER_LOCK() lock_get(cfg_writer_lock); |
333 | 0 | #define CFG_WRITER_UNLOCK() lock_release(cfg_writer_lock); |
334 | | |
335 | | /* increase and decrease the reference counter of a block */ |
336 | 0 | #define CFG_REF(block) atomic_inc(&(block)->refcnt) |
337 | | |
338 | | #define CFG_UNREF(block) \ |
339 | 0 | do { \ |
340 | 0 | if(atomic_dec_and_test(&(block)->refcnt)) \ |
341 | 0 | cfg_block_free(block); \ |
342 | 0 | } while(0) |
343 | | |
344 | | /* updates all the module handles and calls the |
345 | | * per-child process callbacks -- not intended to be used |
346 | | * directly, use cfg_update() instead! |
347 | | * params: |
348 | | * no_cbs - if 1, do not call per child callbacks |
349 | | */ |
350 | | static inline void cfg_update_local(int no_cbs) |
351 | 0 | { |
352 | 0 | cfg_group_t *group; |
353 | 0 | cfg_child_cb_t *last_cb; |
354 | 0 | cfg_child_cb_t *prev_cb; |
355 | |
|
356 | 0 | if(cfg_local) |
357 | 0 | CFG_UNREF(cfg_local); |
358 | 0 | CFG_LOCK(); |
359 | 0 | CFG_REF(*cfg_global); |
360 | 0 | cfg_local = *cfg_global; |
361 | | /* the value of the last callback must be read within the lock */ |
362 | 0 | last_cb = *cfg_child_cb_last; |
363 | | |
364 | | /* I unlock now, because the child process can update its own private |
365 | | config without the lock held. In the worst case, the process will get the |
366 | | lock once more to set cfg_child_cb_first, but only one of the child |
367 | | processes will do so, and only if a value, that has per-child process |
368 | | callback defined, was changed. */ |
369 | 0 | CFG_UNLOCK(); |
370 | | |
371 | | /* update the handles */ |
372 | 0 | for(group = cfg_group; group; group = group->next) |
373 | 0 | *(group->handle) = CFG_GROUP_DATA(cfg_local, group); |
374 | |
|
375 | 0 | if(unlikely(cfg_child_cb == CFG_NO_CHILD_CBS || no_cbs)) |
376 | 0 | return; |
377 | | /* call the per-process callbacks */ |
378 | 0 | while(cfg_child_cb != last_cb) { |
379 | 0 | prev_cb = cfg_child_cb; |
380 | 0 | cfg_child_cb = cfg_child_cb->next; |
381 | 0 | atomic_inc(&cfg_child_cb->refcnt); |
382 | 0 | if(atomic_dec_and_test(&prev_cb->refcnt)) { |
383 | | /* No more pocess refers to this callback. |
384 | | Did this process block the deletion, |
385 | | or is there any other process that has not |
386 | | reached prev_cb yet? */ |
387 | 0 | CFG_LOCK(); |
388 | 0 | if(*cfg_child_cb_first == prev_cb) { |
389 | | /* yes, this process was blocking the deletion */ |
390 | 0 | *cfg_child_cb_first = cfg_child_cb; |
391 | 0 | CFG_UNLOCK(); |
392 | 0 | cfg_child_cb_free_item(prev_cb); |
393 | 0 | } else { |
394 | 0 | CFG_UNLOCK(); |
395 | 0 | } |
396 | 0 | } |
397 | 0 | if(cfg_child_cb->cb |
398 | 0 | && (atomic_add(&cfg_child_cb->cb_count, -1) |
399 | 0 | >= 0) /* the new value is returned |
400 | | by atomic_add() */ |
401 | 0 | ) |
402 | | /* execute the callback */ |
403 | 0 | cfg_child_cb->cb(&cfg_child_cb->gname, &cfg_child_cb->name); |
404 | | /* else the callback no longer needs to be executed */ |
405 | 0 | } |
406 | 0 | } Unexecuted instantiation: main.c:cfg_update_local Unexecuted instantiation: route.c:cfg_update_local Unexecuted instantiation: tcp_main.c:cfg_update_local Unexecuted instantiation: tcp_read.c:cfg_update_local Unexecuted instantiation: timer.c:cfg_update_local Unexecuted instantiation: timer_proc.c:cfg_update_local Unexecuted instantiation: udp_server.c:cfg_update_local Unexecuted instantiation: action.c:cfg_update_local Unexecuted instantiation: async_task.c:cfg_update_local Unexecuted instantiation: cfg.c:cfg_update_local Unexecuted instantiation: cfg_ctx.c:cfg_update_local Unexecuted instantiation: cfg_script.c:cfg_update_local Unexecuted instantiation: cfg_select.c:cfg_update_local Unexecuted instantiation: cfg_struct.c:cfg_update_local |
407 | | |
408 | | /* Reset all the group handles to the default, local configuration */ |
409 | | static inline void cfg_reset_handles(void) |
410 | 0 | { |
411 | 0 | cfg_group_t *group; |
412 | |
|
413 | 0 | if(!cfg_local) |
414 | 0 | return; |
415 | | |
416 | 0 | for(group = cfg_group; |
417 | 0 | group && cfg_ginst_count; /* cfg_ginst_count is decreased every time |
418 | | a group handle is reset. When it reaches 0, |
419 | | needless to continue the loop */ |
420 | 0 | group = group->next) { |
421 | 0 | if(((unsigned char *)*(group->handle) < cfg_local->vars) |
422 | 0 | || ((unsigned char *)*(group->handle) |
423 | 0 | > cfg_local->vars + cfg_block_size)) |
424 | 0 | cfg_move_handle(group, CFG_HANDLE_TO_GINST(*(group->handle)), NULL); |
425 | 0 | } |
426 | 0 | } Unexecuted instantiation: main.c:cfg_reset_handles Unexecuted instantiation: route.c:cfg_reset_handles Unexecuted instantiation: tcp_main.c:cfg_reset_handles Unexecuted instantiation: tcp_read.c:cfg_reset_handles Unexecuted instantiation: timer.c:cfg_reset_handles Unexecuted instantiation: timer_proc.c:cfg_reset_handles Unexecuted instantiation: udp_server.c:cfg_reset_handles Unexecuted instantiation: action.c:cfg_reset_handles Unexecuted instantiation: async_task.c:cfg_reset_handles Unexecuted instantiation: cfg.c:cfg_reset_handles Unexecuted instantiation: cfg_ctx.c:cfg_reset_handles Unexecuted instantiation: cfg_script.c:cfg_reset_handles Unexecuted instantiation: cfg_select.c:cfg_reset_handles Unexecuted instantiation: cfg_struct.c:cfg_reset_handles |
427 | | |
428 | | /* sets the local cfg block to the active block |
429 | | * |
430 | | * If your module forks a new process that implements |
431 | | * an infinite loop, put cfg_update() to the beginning of |
432 | | * the cycle to make sure, that subsequent function calls see the |
433 | | * up-to-date config set. |
434 | | */ |
435 | | #define cfg_update() \ |
436 | 0 | do { \ |
437 | 0 | if(unlikely(cfg_ginst_count)) \ |
438 | 0 | cfg_reset_handles(); \ |
439 | 0 | if(unlikely(cfg_local != *cfg_global)) \ |
440 | 0 | cfg_update_local(0); \ |
441 | 0 | } while(0) |
442 | | |
443 | | /* like cfg_update(), but does not execute callbacks |
444 | | * (it should be used sparingly only in special cases, since it |
445 | | * breaks an important cfg framework feature) |
446 | | */ |
447 | | #define cfg_update_no_cbs() \ |
448 | 0 | do { \ |
449 | 0 | if(unlikely(cfg_local != *cfg_global)) \ |
450 | 0 | cfg_update_local(1); \ |
451 | 0 | } while(0) |
452 | | |
453 | | /* Reset all the group handles in the child process, |
454 | | * i.e. move them back to the default local configuration. |
455 | | */ |
456 | | #define cfg_reset_all() \ |
457 | 0 | do { \ |
458 | 0 | if(unlikely(cfg_ginst_count)) \ |
459 | 0 | cfg_reset_handles(); \ |
460 | 0 | } while(0) |
461 | | |
462 | | |
463 | | /* searches a group by name */ |
464 | | cfg_group_t *cfg_lookup_group(char *name, int len); |
465 | | |
466 | | /* searches a variable definition by group and variable name */ |
467 | | int cfg_lookup_var( |
468 | | str *gname, str *vname, cfg_group_t **group, cfg_mapping_t **var); |
469 | | |
470 | | /* searches a variable definition within a group by its name */ |
471 | | cfg_mapping_t *cfg_lookup_var2(cfg_group_t *group, char *name, int len); |
472 | | |
473 | | /* clones the global config block |
474 | | * WARNING: unsafe, cfg_writer_lock or cfg_global_lock must be held! |
475 | | */ |
476 | | cfg_block_t *cfg_clone_global(void); |
477 | | |
478 | | /* Clone an array of configuration group instances. */ |
479 | | cfg_group_inst_t *cfg_clone_array(cfg_group_meta_t *meta, cfg_group_t *group); |
480 | | |
481 | | /* Extend the array of configuration group instances with one more instance. |
482 | | * Only the ID of the new group is set, nothing else. */ |
483 | | cfg_group_inst_t *cfg_extend_array(cfg_group_meta_t *meta, cfg_group_t *group, |
484 | | unsigned int group_id, cfg_group_inst_t **new_group); |
485 | | |
486 | | /* Remove an instance from a group array. |
487 | | * inst must point to an instance within meta->array. |
488 | | * *_new_array is set to the newly allocated array. */ |
489 | | int cfg_collapse_array(cfg_group_meta_t *meta, cfg_group_t *group, |
490 | | cfg_group_inst_t *inst, cfg_group_inst_t **_new_array); |
491 | | |
492 | | /* clones a string to shared memory */ |
493 | | int cfg_clone_str(str *src, str *dst); |
494 | | |
495 | | /* Find the group instance within the meta-data based on the group_id */ |
496 | | cfg_group_inst_t *cfg_find_group( |
497 | | cfg_group_meta_t *meta, int group_size, unsigned int group_id); |
498 | | |
499 | | /* append new callbacks to the end of the child callback list |
500 | | * |
501 | | * WARNING: the function is unsafe, either hold CFG_LOCK(), |
502 | | * or call the function before forking |
503 | | */ |
504 | | void cfg_install_child_cb(cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last); |
505 | | |
506 | | /* installs a new global config |
507 | | * |
508 | | * replaced is an array of strings that must be freed together |
509 | | * with the previous global config. |
510 | | * cb_first and cb_last define a linked list of per-child process |
511 | | * callbacks. This list is added to the global linked list. |
512 | | */ |
513 | | void cfg_install_global(cfg_block_t *block, void **replaced, |
514 | | cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last); |
515 | | |
516 | | /* creates a structure for a per-child process callback */ |
517 | | cfg_child_cb_t *cfg_child_cb_new( |
518 | | str *gname, str *name, cfg_on_set_child cb, unsigned int type); |
519 | | |
520 | | /* free the memory allocated for a child cb list */ |
521 | | void cfg_child_cb_free_list(cfg_child_cb_t *child_cb_first); |
522 | | |
523 | | /* Allocate memory for a new additional variable |
524 | | * and link it to a configuration group. |
525 | | * type==0 results in creating a new group instance with the default values. |
526 | | * The group is created with CFG_GROUP_UNKNOWN type if it does not exist. |
527 | | * Note: this function is usable only before the configuration is shmized. |
528 | | */ |
529 | | int new_add_var(str *group_name, unsigned int group_id, str *var_name, |
530 | | void *val, unsigned int type); |
531 | | |
532 | | /* Move the group handle to the specified group instance. */ |
533 | | int cfg_select(cfg_group_t *group, unsigned int id); |
534 | | |
535 | | /* Reset the group handle to the default, local configuration */ |
536 | | int cfg_reset(cfg_group_t *group); |
537 | | |
538 | | /* Move the group handle to the first group instance. |
539 | | * This function together with cfg_select_next() can be used |
540 | | * to iterate though the list of instances. |
541 | | * |
542 | | * Return value: |
543 | | * -1: no group instance found |
544 | | * 0: first group instance is successfully selected. |
545 | | */ |
546 | | int cfg_select_first(cfg_group_t *group); |
547 | | |
548 | | /* Move the group handle to the next group instance. |
549 | | * This function together with cfg_select_first() can be used |
550 | | * to iterate though the list of instances. |
551 | | * |
552 | | * Return value: |
553 | | * -1: no more group instance found. Note, that the active group |
554 | | * instance is not changed in this case. |
555 | | * 0: the next group instance is successfully selected. |
556 | | */ |
557 | | int cfg_select_next(cfg_group_t *group); |
558 | | |
559 | | /* Temporary set the local configuration in the main process before forking. |
560 | | * This makes the group instances usable in the main process after |
561 | | * the configuration is shmized, but before the children are forked. |
562 | | */ |
563 | | void cfg_main_set_local(void); |
564 | | |
565 | | /* Reset the local configuration of the main process back to its original state |
566 | | * to make sure that the forked processes are not affected. |
567 | | */ |
568 | | void cfg_main_reset_local(void); |
569 | | |
570 | | #endif /* _CFG_STRUCT_H */ |