- Updating the local configuration in the child processes that are
[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  */
31
32 #ifndef _CFG_STRUCT_H
33 #define _CFG_STRUCT_H
34
35 #include "../str.h"
36 #include "../atomic_ops.h"
37 #include "../mem/shm_mem.h"
38 #include "../locking.h"
39 #include "../compiler_opt.h"
40 #include "cfg.h"
41
42 /* indicates that the variable has been already shmized */
43 #define cfg_var_shmized 1U
44
45 /* structure used for variable - pointer mapping */
46 typedef struct _cfg_mapping {
47         cfg_def_t       *def;           /* one item of the cfg structure definition */
48         int             name_len;       /* length of def->name */
49
50         /* additional information about the cfg variable */
51         int             offset; /* offest within the memory block */
52         unsigned int    flag;   /* flag indicating the state of the variable */
53 } cfg_mapping_t;
54
55 /* linked list of registered groups */
56 typedef struct _cfg_group {
57         int             num;            /* number of variables within the group */
58         cfg_mapping_t   *mapping;       /* describes the mapping betweeen
59                                         the cfg variable definition and the memory block */
60         char            *vars;          /* pointer to the memory block where the values
61                                         are stored -- used only before the config is
62                                         shmized. */
63         int             size;           /* size of the memory block that has to be
64                                         allocated to store the values */
65         int             offset;         /* offset of the group within the
66                                         shmized memory block */
67         void            **handle;       /* per-process handle that can be used
68                                         by the modules to access the variables.
69                                         It is registered when the group is created,
70                                         and updated every time the block is replaced */
71
72         struct _cfg_group       *next;
73         int             name_len;       
74         char            name[1];
75 } cfg_group_t;
76
77 /* single memoy block that contains all the cfg values */
78 typedef struct _cfg_block {
79         atomic_t        refcnt;         /* reference counter,
80                                         the block is automatically deleted
81                                         when it reaches 0 */
82         char            **replaced;     /* set of the strings that must be freed
83                                         together with the block. The content depends
84                                         on the block that replaces this one */
85         unsigned char   vars[1];        /* blob that contains the values */
86 } cfg_block_t;
87
88 /* Linked list of per-child process callbacks.
89  * Each child process has a local pointer, and executes the callbacks
90  * when the pointer is not pointing to the end of the list.
91  * Items from the begginning of the list are deleted when the starter
92  * pointer is moved, and no more child process uses them.
93  */
94 typedef struct _cfg_child_cb {
95         atomic_t                refcnt; /* number of child processes
96                                         referring to the element */
97         str                     name;   /* name of the variable that has changed */
98         cfg_on_set_child        cb;     /* callback function that has to be called */
99
100         struct _cfg_child_cb    *next;
101 } cfg_child_cb_t;
102
103 extern cfg_group_t      *cfg_group;
104 extern cfg_block_t      **cfg_global;
105 extern cfg_block_t      *cfg_local;
106 extern gen_lock_t       *cfg_global_lock;
107 extern gen_lock_t       *cfg_writer_lock;
108 extern int              cfg_shmized;
109 extern cfg_child_cb_t   **cfg_child_cb_first;
110 extern cfg_child_cb_t   **cfg_child_cb_last;
111 extern cfg_child_cb_t   *cfg_child_cb;
112
113 /* macros for easier variable access */
114 #define CFG_VAR_TYPE(var)       CFG_VAR_MASK((var)->def->type)
115 #define CFG_INPUT_TYPE(var)     CFG_INPUT_MASK((var)->def->type)
116
117 /* initiate the cfg framework */
118 int cfg_init(void);
119
120 /* destroy the memory allocated for the cfg framework */
121 void cfg_destroy(void);
122
123 /* per-child process init function */
124 int cfg_child_init(void);
125
126 /* per-child process destroy function
127  * Should be called only when the child process exits,
128  * but SER continues running.
129  *
130  * WARNING: this function call must be the very last action
131  * before the child process exits, because the local config
132  * is not available afterwards.
133  */
134 void cfg_child_destroy(void);
135
136 /* creates a new cfg group, and adds it to the linked list */
137 int cfg_new_group(char *name, int num, cfg_mapping_t *mapping,
138                 char *vars, int size, void **handle);
139
140 /* copy the variables to shm mem */
141 int cfg_shmize(void);
142
143 /* free the memory of a config block */
144 static inline void cfg_block_free(cfg_block_t *block)
145 {
146         int     i;
147
148         /* free the changed variables */
149         if (block->replaced) {
150                 for (i=0; block->replaced[i]; i++)
151                         shm_free(block->replaced[i]);
152                 shm_free(block->replaced);
153         }
154         shm_free(block);
155 }
156
157 /* lock and unlock the global cfg block -- used only at the
158  * very last step when the block is replaced */
159 #define CFG_LOCK()      lock_get(cfg_global_lock);
160 #define CFG_UNLOCK()    lock_release(cfg_global_lock);
161
162 /* lock and unlock used by the cfg drivers to make sure that
163  * only one driver process is considering replacing the global
164  * cfg block */
165 #define CFG_WRITER_LOCK()       lock_get(cfg_writer_lock);
166 #define CFG_WRITER_UNLOCK()     lock_release(cfg_writer_lock);
167
168 /* increase and decrease the reference counter of a block */
169 #define CFG_REF(block) \
170         atomic_inc(&(block)->refcnt)
171
172 #define CFG_UNREF(block) \
173         do { \
174                 if (atomic_dec_and_test(&(block)->refcnt)) \
175                         cfg_block_free(block); \
176         } while(0)
177
178 /* updates all the module handles and calls the
179  * per-child process callbacks -- not intended to be used
180  * directly, use cfg_update() instead!
181  */
182 static inline void cfg_update_local(void)
183 {
184         cfg_group_t     *group;
185         cfg_child_cb_t  *last_cb;
186         cfg_child_cb_t  *prev_cb;
187
188         if (cfg_local) CFG_UNREF(cfg_local);
189         CFG_LOCK();
190         CFG_REF(*cfg_global);
191         cfg_local = *cfg_global;
192         /* the value of the last callback must be read within the lock */
193         last_cb = *cfg_child_cb_last;
194
195         /* I unlock now, because the child process can update its own private
196         config without the lock held. In the worst case, the process will get the
197         lock once more to set cfg_child_cb_first, but only one of the child
198         processes will do so, and only if a value, that has per-child process
199         callback defined, was changed. */
200         CFG_UNLOCK();
201
202         /* update the handles */
203         for (   group = cfg_group;
204                 group;
205                 group = group->next
206         )
207                 *(group->handle) = cfg_local->vars + group->offset;
208
209         /* call the per-process callbacks */
210         while (cfg_child_cb != last_cb) {
211                 prev_cb = cfg_child_cb;
212                 cfg_child_cb = cfg_child_cb->next;
213                 atomic_inc(&cfg_child_cb->refcnt);
214                 if (atomic_dec_and_test(&prev_cb->refcnt)) {
215                         /* No more pocess refers to this callback.
216                         Did this process block the deletion,
217                         or is there any other process that has not
218                         reached prev_cb yet? */
219                         CFG_LOCK();
220                         if (*cfg_child_cb_first == prev_cb) {
221                                 /* yes, this process was blocking the deletion */
222                                 *cfg_child_cb_first = cfg_child_cb;
223                                 CFG_UNLOCK();
224                                 shm_free(prev_cb);
225                         } else {
226                                 CFG_UNLOCK();
227                         }
228                 }
229                 /* execute the callback */
230                 cfg_child_cb->cb(&cfg_child_cb->name);
231         }
232 }
233
234 /* sets the local cfg block to the active block
235  * 
236  * If your module forks a new process that implements
237  * an infinite loop, put cfg_update() to the beginning of
238  * the cycle to make sure, that subsequent function calls see the
239  * up-to-date config set.
240  */
241 #define cfg_update() \
242         do { \
243                 if (unlikely(cfg_local != *cfg_global)) \
244                         cfg_update_local(); \
245         } while(0)
246         
247 /* searches a variable definition by group and variable name */
248 int cfg_lookup_var(str *gname, str *vname,
249                         cfg_group_t **group, cfg_mapping_t **var);
250
251 /* clones the global config block */
252 cfg_block_t *cfg_clone_global(void);
253
254 /* clones a string to shared memory */
255 char *cfg_clone_str(str s);
256
257 /* installs a new global config
258  *
259  * replaced is an array of strings that must be freed together
260  * with the previous global config.
261  * cb_first and cb_last define a linked list of per-child process
262  * callbacks. This list is added to the global linked list.
263  */
264 void cfg_install_global(cfg_block_t *block, char **replaced,
265                         cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last);
266
267 /* creates a structure for a per-child process callback */
268 cfg_child_cb_t *cfg_child_cb_new(str *name, cfg_on_set_child cb);
269
270 /* free the memory allocated for a child cb list */
271 void cfg_child_cb_free(cfg_child_cb_t *child_cb_first);
272
273 #endif /* _CFG_STRUCT_H */