- Call the per-child process callback functions even if the
[sip-router] / cfg / cfg_struct.h
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2007 iptelorg GmbH
5  *
6  * This file is part of ser, a free SIP server.
7  *
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
12  *
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:
16  *    info@iptel.org
17  *
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.
22  *
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
26  *
27  * History
28  * -------
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)
32  */
33
34 #ifndef _CFG_STRUCT_H
35 #define _CFG_STRUCT_H
36
37 #include "../str.h"
38 #include "../atomic_ops.h"
39 #include "../mem/shm_mem.h"
40 #include "../locking.h"
41 #include "../compiler_opt.h"
42 #include "cfg.h"
43
44 /* indicates that the variable has been already shmized */
45 #define cfg_var_shmized 1U
46
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 */
51
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 */
55 } cfg_mapping_t;
56
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
64                                         shmized. */
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 */
73
74         unsigned char   dynamic;        /* indicates whether the variables within the group
75                                         are dynamically allocated or not */
76         struct _cfg_group       *next;
77         int             name_len;       
78         char            name[1];
79 } cfg_group_t;
80
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
85                                         when it reaches 0 */
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 */
90 } cfg_block_t;
91
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.
97  */
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 */
103
104         struct _cfg_child_cb    *next;
105 } cfg_child_cb_t;
106
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;
116
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)
120
121 /* initiate the cfg framework */
122 int cfg_init(void);
123
124 /* destroy the memory allocated for the cfg framework */
125 void cfg_destroy(void);
126
127 /* per-child process init function */
128 int cfg_child_init(void);
129
130 /* per-child process destroy function
131  * Should be called only when the child process exits,
132  * but SER continues running.
133  *
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.
137  */
138 void cfg_child_destroy(void);
139
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);
144
145 /* copy the variables to shm mem */
146 int cfg_shmize(void);
147
148 /* free the memory of a config block */
149 static inline void cfg_block_free(cfg_block_t *block)
150 {
151         int     i;
152
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);
158         }
159         shm_free(block);
160 }
161
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);
166
167 /* lock and unlock used by the cfg drivers to make sure that
168  * only one driver process is considering replacing the global
169  * cfg block */
170 #define CFG_WRITER_LOCK()       lock_get(cfg_writer_lock);
171 #define CFG_WRITER_UNLOCK()     lock_release(cfg_writer_lock);
172
173 /* increase and decrease the reference counter of a block */
174 #define CFG_REF(block) \
175         atomic_inc(&(block)->refcnt)
176
177 #define CFG_UNREF(block) \
178         do { \
179                 if (atomic_dec_and_test(&(block)->refcnt)) \
180                         cfg_block_free(block); \
181         } while(0)
182
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!
186  */
187 static inline void cfg_update_local(void)
188 {
189         cfg_group_t     *group;
190         cfg_child_cb_t  *last_cb;
191         cfg_child_cb_t  *prev_cb;
192
193         if (cfg_local) CFG_UNREF(cfg_local);
194         CFG_LOCK();
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;
199
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. */
205         CFG_UNLOCK();
206
207         /* update the handles */
208         for (   group = cfg_group;
209                 group;
210                 group = group->next
211         )
212                 *(group->handle) = cfg_local->vars + group->offset;
213
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? */
224                         CFG_LOCK();
225                         if (*cfg_child_cb_first == prev_cb) {
226                                 /* yes, this process was blocking the deletion */
227                                 *cfg_child_cb_first = cfg_child_cb;
228                                 CFG_UNLOCK();
229                                 shm_free(prev_cb);
230                         } else {
231                                 CFG_UNLOCK();
232                         }
233                 }
234                 /* execute the callback */
235                 cfg_child_cb->cb(&cfg_child_cb->name);
236         }
237 }
238
239 /* sets the local cfg block to the active block
240  * 
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.
245  */
246 #define cfg_update() \
247         do { \
248                 if (unlikely(cfg_local != *cfg_global)) \
249                         cfg_update_local(); \
250         } while(0)
251
252 /* searches a group by name */
253 cfg_group_t *cfg_lookup_group(char *name, int len);
254         
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);
258
259 /* clones the global config block */
260 cfg_block_t *cfg_clone_global(void);
261
262 /* clones a string to shared memory */
263 int cfg_clone_str(str *src, str *dst);
264
265 /* append new callbacks to the end of the child callback list
266  *
267  * WARNING: the function is unsafe, either hold CFG_LOCK(),
268  * or call the function before forking
269  */
270 void cfg_install_child_cb(cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last);
271
272 /* installs a new global config
273  *
274  * replaced is an array of strings that must be freed together
275  * with the previous global config.
276  * cb_first and cb_last define a linked list of per-child process
277  * callbacks. This list is added to the global linked list.
278  */
279 void cfg_install_global(cfg_block_t *block, char **replaced,
280                         cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last);
281
282 /* creates a structure for a per-child process callback */
283 cfg_child_cb_t *cfg_child_cb_new(str *name, cfg_on_set_child cb);
284
285 /* free the memory allocated for a child cb list */
286 void cfg_child_cb_free(cfg_child_cb_t *child_cb_first);
287
288 #endif /* _CFG_STRUCT_H */