e9554adc79e02aad101b2136d1001276c27a0a88
[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 /* creates a new cfg group, and adds it to the linked list */
127 int cfg_new_group(char *name, int num, cfg_mapping_t *mapping,
128                 char *vars, int size, void **handle);
129
130 /* copy the variables to shm mem */
131 int cfg_shmize(void);
132
133 /* free the memory of a config block */
134 static inline void cfg_block_free(cfg_block_t *block)
135 {
136         int     i;
137
138         /* free the changed variables */
139         if (block->replaced) {
140                 for (i=0; block->replaced[i]; i++)
141                         shm_free(block->replaced[i]);
142                 shm_free(block->replaced);
143         }
144         shm_free(block);
145 }
146
147 /* lock and unlock the global cfg block -- used only at the
148  * very last step when the block is replaced */
149 #define CFG_LOCK()      lock_get(cfg_global_lock);
150 #define CFG_UNLOCK()    lock_release(cfg_global_lock);
151
152 /* lock and unlock used by the cfg drivers to make sure that
153  * only one driver process is considering replacing the global
154  * cfg block */
155 #define CFG_WRITER_LOCK()       lock_get(cfg_writer_lock);
156 #define CFG_WRITER_UNLOCK()     lock_release(cfg_writer_lock);
157
158 /* increase and decrease the reference counter of a block */
159 #define CFG_REF(block) \
160         atomic_inc(&(block)->refcnt)
161
162 #define CFG_UNREF(block) \
163         do { \
164                 if (atomic_dec_and_test(&(block)->refcnt)) \
165                         cfg_block_free(block); \
166         } while(0)
167
168 /* updates all the module handles and calls the
169  * per-child process callbacks -- not intended to be used
170  * directly, use cfg_update() instead!
171  */
172 static inline void cfg_update_local(void)
173 {
174         cfg_group_t     *group;
175         cfg_child_cb_t  *last_cb;
176         cfg_child_cb_t  *prev_cb;
177
178         if (cfg_local) CFG_UNREF(cfg_local);
179         CFG_LOCK();
180         CFG_REF(*cfg_global);
181         cfg_local = *cfg_global;
182         /* the value of the last callback must be read within the lock */
183         last_cb = *cfg_child_cb_last;
184
185         /* I unlock now, because the child process can update its own private
186         config without the lock held. In the worst case, the process will get the
187         lock once more to set cfg_child_cb_first, but only one of the child
188         processes will do so, and only if a value, that has per-child process
189         callback defined, was changed. */
190         CFG_UNLOCK();
191
192         /* update the handles */
193         for (   group = cfg_group;
194                 group;
195                 group = group->next
196         )
197                 *(group->handle) = cfg_local->vars + group->offset;
198
199         /* call the per-process callbacks */
200         while (cfg_child_cb != last_cb) {
201                 prev_cb = cfg_child_cb;
202                 cfg_child_cb = cfg_child_cb->next;
203                 atomic_inc(&cfg_child_cb->refcnt);
204                 if (atomic_dec_and_test(&prev_cb->refcnt)) {
205                         /* No more pocess refers to this callback.
206                         Did this process block the deletion,
207                         or is there any other process that has not
208                         reached prev_cb yet? */
209                         CFG_LOCK();
210                         if (*cfg_child_cb_first == prev_cb) {
211                                 /* yes, this process was blocking the deletion */
212                                 *cfg_child_cb_first = cfg_child_cb;
213                                 CFG_UNLOCK();
214                                 shm_free(prev_cb);
215                         } else {
216                                 CFG_UNLOCK();
217                         }
218                 }
219                 /* execute the callback */
220                 cfg_child_cb->cb(&cfg_child_cb->name);
221         }
222 }
223
224 /* sets the local cfg block to the active block
225  * 
226  * If your module forks a new process that implements
227  * an infinite loop, put cfg_update() to the beginning of
228  * the cycle to make sure, that subsequent function calls see the
229  * up-to-date config set.
230  */
231 #define cfg_update() \
232         do { \
233                 if (unlikely(cfg_local != *cfg_global)) \
234                         cfg_update_local(); \
235         } while(0)
236         
237 /* searches a variable definition by group and variable name */
238 int cfg_lookup_var(str *gname, str *vname,
239                         cfg_group_t **group, cfg_mapping_t **var);
240
241 /* clones the global config block */
242 cfg_block_t *cfg_clone_global(void);
243
244 /* clones a string to shared memory */
245 char *cfg_clone_str(str s);
246
247 /* installs a new global config
248  *
249  * replaced is an array of strings that must be freed together
250  * with the previous global config.
251  * cb_first and cb_last define a linked list of per-child process
252  * callbacks. This list is added to the global linked list.
253  */
254 void cfg_install_global(cfg_block_t *block, char **replaced,
255                         cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last);
256
257 /* creates a structure for a per-child process callback */
258 cfg_child_cb_t *cfg_child_cb_new(str *name, cfg_on_set_child cb);
259
260 /* free the memory allocated for a child cb list */
261 void cfg_child_cb_free(cfg_child_cb_t *child_cb_first);
262
263 #endif /* _CFG_STRUCT_H */