4 * Copyright (C) 2007 iptelorg GmbH
6 * This file is part of ser, a free SIP server.
8 * ser is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
13 * For a license to use the ser software under conditions
14 * other than those described here, or to purchase support for this
15 * software, please contact iptel.org by e-mail at the following addresses:
18 * ser is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 * 2007-12-03 Initial version (Miklos)
30 * 2008-01-24 dynamic groups are introduced in order to make
31 * variable declaration possible in the script (Miklos)
38 #include "../atomic_ops.h"
39 #include "../mem/shm_mem.h"
40 #include "../locking.h"
41 #include "../compiler_opt.h"
44 /* indicates that the variable has been already shmized */
45 #define cfg_var_shmized 1U
47 /* structure used for variable - pointer mapping */
48 typedef struct _cfg_mapping {
49 cfg_def_t *def; /* one item of the cfg structure definition */
50 int name_len; /* length of def->name */
52 /* additional information about the cfg variable */
53 int offset; /* offest within the memory block */
54 unsigned int flag; /* flag indicating the state of the variable */
57 /* linked list of registered groups */
58 typedef struct _cfg_group {
59 int num; /* number of variables within the group */
60 cfg_mapping_t *mapping; /* describes the mapping betweeen
61 the cfg variable definition and the memory block */
62 char *vars; /* pointer to the memory block where the values
63 are stored -- used only before the config is
65 int size; /* size of the memory block that has to be
66 allocated to store the values */
67 int offset; /* offset of the group within the
68 shmized memory block */
69 void **handle; /* per-process handle that can be used
70 by the modules to access the variables.
71 It is registered when the group is created,
72 and updated every time the block is replaced */
74 unsigned char dynamic; /* indicates whether the variables within the group
75 are dynamically allocated or not */
76 struct _cfg_group *next;
81 /* single memoy block that contains all the cfg values */
82 typedef struct _cfg_block {
83 atomic_t refcnt; /* reference counter,
84 the block is automatically deleted
86 char **replaced; /* set of the strings that must be freed
87 together with the block. The content depends
88 on the block that replaces this one */
89 unsigned char vars[1]; /* blob that contains the values */
92 /* Linked list of per-child process callbacks.
93 * Each child process has a local pointer, and executes the callbacks
94 * when the pointer is not pointing to the end of the list.
95 * Items from the begginning of the list are deleted when the starter
96 * pointer is moved, and no more child process uses them.
98 typedef struct _cfg_child_cb {
99 atomic_t refcnt; /* number of child processes
100 referring to the element */
101 str name; /* name of the variable that has changed */
102 cfg_on_set_child cb; /* callback function that has to be called */
104 struct _cfg_child_cb *next;
107 extern cfg_group_t *cfg_group;
108 extern cfg_block_t **cfg_global;
109 extern cfg_block_t *cfg_local;
110 extern gen_lock_t *cfg_global_lock;
111 extern gen_lock_t *cfg_writer_lock;
112 extern int cfg_shmized;
113 extern cfg_child_cb_t **cfg_child_cb_first;
114 extern cfg_child_cb_t **cfg_child_cb_last;
115 extern cfg_child_cb_t *cfg_child_cb;
117 /* macros for easier variable access */
118 #define CFG_VAR_TYPE(var) CFG_VAR_MASK((var)->def->type)
119 #define CFG_INPUT_TYPE(var) CFG_INPUT_MASK((var)->def->type)
121 /* initiate the cfg framework */
124 /* destroy the memory allocated for the cfg framework */
125 void cfg_destroy(void);
127 /* per-child process init function */
128 int cfg_child_init(void);
130 /* per-child process destroy function
131 * Should be called only when the child process exits,
132 * but SER continues running.
134 * WARNING: this function call must be the very last action
135 * before the child process exits, because the local config
136 * is not available afterwards.
138 void cfg_child_destroy(void);
140 /* creates a new cfg group, and adds it to the linked list */
141 cfg_group_t *cfg_new_group(char *name, int name_len,
142 int num, cfg_mapping_t *mapping,
143 char *vars, int size, void **handle);
145 /* copy the variables to shm mem */
146 int cfg_shmize(void);
148 /* free the memory of a config block */
149 static inline void cfg_block_free(cfg_block_t *block)
153 /* free the changed variables */
154 if (block->replaced) {
155 for (i=0; block->replaced[i]; i++)
156 shm_free(block->replaced[i]);
157 shm_free(block->replaced);
162 /* lock and unlock the global cfg block -- used only at the
163 * very last step when the block is replaced */
164 #define CFG_LOCK() lock_get(cfg_global_lock);
165 #define CFG_UNLOCK() lock_release(cfg_global_lock);
167 /* lock and unlock used by the cfg drivers to make sure that
168 * only one driver process is considering replacing the global
170 #define CFG_WRITER_LOCK() lock_get(cfg_writer_lock);
171 #define CFG_WRITER_UNLOCK() lock_release(cfg_writer_lock);
173 /* increase and decrease the reference counter of a block */
174 #define CFG_REF(block) \
175 atomic_inc(&(block)->refcnt)
177 #define CFG_UNREF(block) \
179 if (atomic_dec_and_test(&(block)->refcnt)) \
180 cfg_block_free(block); \
183 /* updates all the module handles and calls the
184 * per-child process callbacks -- not intended to be used
185 * directly, use cfg_update() instead!
187 static inline void cfg_update_local(void)
190 cfg_child_cb_t *last_cb;
191 cfg_child_cb_t *prev_cb;
193 if (cfg_local) CFG_UNREF(cfg_local);
195 CFG_REF(*cfg_global);
196 cfg_local = *cfg_global;
197 /* the value of the last callback must be read within the lock */
198 last_cb = *cfg_child_cb_last;
200 /* I unlock now, because the child process can update its own private
201 config without the lock held. In the worst case, the process will get the
202 lock once more to set cfg_child_cb_first, but only one of the child
203 processes will do so, and only if a value, that has per-child process
204 callback defined, was changed. */
207 /* update the handles */
208 for ( group = cfg_group;
212 *(group->handle) = cfg_local->vars + group->offset;
214 /* call the per-process callbacks */
215 while (cfg_child_cb != last_cb) {
216 prev_cb = cfg_child_cb;
217 cfg_child_cb = cfg_child_cb->next;
218 atomic_inc(&cfg_child_cb->refcnt);
219 if (atomic_dec_and_test(&prev_cb->refcnt)) {
220 /* No more pocess refers to this callback.
221 Did this process block the deletion,
222 or is there any other process that has not
223 reached prev_cb yet? */
225 if (*cfg_child_cb_first == prev_cb) {
226 /* yes, this process was blocking the deletion */
227 *cfg_child_cb_first = cfg_child_cb;
234 /* execute the callback */
235 cfg_child_cb->cb(&cfg_child_cb->name);
239 /* sets the local cfg block to the active block
241 * If your module forks a new process that implements
242 * an infinite loop, put cfg_update() to the beginning of
243 * the cycle to make sure, that subsequent function calls see the
244 * up-to-date config set.
246 #define cfg_update() \
248 if (unlikely(cfg_local != *cfg_global)) \
249 cfg_update_local(); \
252 /* searches a group by name */
253 cfg_group_t *cfg_lookup_group(char *name, int len);
255 /* searches a variable definition by group and variable name */
256 int cfg_lookup_var(str *gname, str *vname,
257 cfg_group_t **group, cfg_mapping_t **var);
259 /* clones the global config block */
260 cfg_block_t *cfg_clone_global(void);
262 /* clones a string to shared memory */
263 int cfg_clone_str(str *src, str *dst);
265 /* installs a new global config
267 * replaced is an array of strings that must be freed together
268 * with the previous global config.
269 * cb_first and cb_last define a linked list of per-child process
270 * callbacks. This list is added to the global linked list.
272 void cfg_install_global(cfg_block_t *block, char **replaced,
273 cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last);
275 /* creates a structure for a per-child process callback */
276 cfg_child_cb_t *cfg_child_cb_new(str *name, cfg_on_set_child cb);
278 /* free the memory allocated for a child cb list */
279 void cfg_child_cb_free(cfg_child_cb_t *child_cb_first);
281 #endif /* _CFG_STRUCT_H */