- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)
1 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,884 +0,0 @@ |
1 |
-/* |
|
2 |
- * Copyright (C) 2010 iptelorg GmbH |
|
3 |
- * |
|
4 |
- * Permission to use, copy, modify, and distribute this software for any |
|
5 |
- * purpose with or without fee is hereby granted, provided that the above |
|
6 |
- * copyright notice and this permission notice appear in all copies. |
|
7 |
- * |
|
8 |
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|
9 |
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|
10 |
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|
11 |
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|
12 |
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|
13 |
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|
14 |
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
15 |
- */ |
|
16 |
- |
|
17 |
-/** |
|
18 |
- * @brief Kamailio core :: counters/stats |
|
19 |
- * @file |
|
20 |
- * @ingroup: core |
|
21 |
- */ |
|
22 |
- |
|
23 |
-#include "counters.h" |
|
24 |
-#include "str_hash.h" |
|
25 |
-#include "str.h" |
|
26 |
-#include "compiler_opt.h" |
|
27 |
-#include "mem/mem.h" |
|
28 |
-#include "mem/shm_mem.h" |
|
29 |
- |
|
30 |
- |
|
31 |
-#define CNT_HASH_SIZE 64 |
|
32 |
-/* group hash size (rpc use) */ |
|
33 |
-#define GRP_HASH_SIZE 16 |
|
34 |
-/* initial sorted groups array size (rpc use) */ |
|
35 |
-#define GRP_SORTED_SIZE 16 |
|
36 |
-/* intial counter id 2 record array size */ |
|
37 |
-#define CNT_ID2RECORD_SIZE 64 |
|
38 |
- |
|
39 |
-#define CACHELINE_PAD 128 |
|
40 |
- |
|
41 |
- |
|
42 |
- |
|
43 |
-/* leave space for one flag */ |
|
44 |
-#define MAX_COUNTER_ID 32767 |
|
45 |
-/* size (number of entries) of the temporary array used for keeping stats |
|
46 |
- pre-prefork init. Note: if more counters are registered then this size, |
|
47 |
- the array will be dynamically increased (doubled each time). The value |
|
48 |
- here is meant only to optimize startup/memory fragmentation. */ |
|
49 |
-#define PREINIT_CNTS_VALS_SIZE 128 |
|
50 |
- |
|
51 |
-struct counter_record { |
|
52 |
- str group; |
|
53 |
- str name; |
|
54 |
- counter_handle_t h; |
|
55 |
- unsigned short flags; |
|
56 |
- void* cbk_param; |
|
57 |
- counter_cbk_f cbk; |
|
58 |
- struct counter_record* grp_next; /* next in group */ |
|
59 |
- str doc; |
|
60 |
-}; |
|
61 |
- |
|
62 |
- |
|
63 |
-struct grp_record { |
|
64 |
- str group; |
|
65 |
- struct counter_record* first; |
|
66 |
-}; |
|
67 |
- |
|
68 |
- |
|
69 |
- |
|
70 |
-/** hash table mapping a counter name to an id */ |
|
71 |
-static struct str_hash_table cnts_hash_table; |
|
72 |
-/** array maping id 2 record */ |
|
73 |
-struct counter_record** cnt_id2record; |
|
74 |
-static int cnt_id2record_size; |
|
75 |
-/** hash table for groups (maps a group name to a counter list) */ |
|
76 |
-static struct str_hash_table grp_hash_table; |
|
77 |
-/** array of groups, sorted */ |
|
78 |
-static struct grp_record** grp_sorted; |
|
79 |
-static int grp_sorted_max_size; |
|
80 |
-static int grp_sorted_crt_size; |
|
81 |
-static int grp_no; /* number of groups */ |
|
82 |
- |
|
83 |
-/** counters array. a[proc_no][counter_id] => |
|
84 |
- _cnst_vals[proc_no*cnts_no+counter_id] */ |
|
85 |
-counter_array_t* _cnts_vals = 0; |
|
86 |
-int _cnts_row_len; /* number of elements per row */ |
|
87 |
-static int cnts_no; /* number of registered counters */ |
|
88 |
-static int cnts_max_rows; /* set to 0 if not yet fully init */ |
|
89 |
- |
|
90 |
- |
|
91 |
-int counters_initialized(void) |
|
92 |
-{ |
|
93 |
- if (unlikely(_cnts_vals == 0)) { |
|
94 |
- /* not init yet */ |
|
95 |
- return 0; |
|
96 |
- } |
|
97 |
- return 1; |
|
98 |
-} |
|
99 |
- |
|
100 |
-/** init the coutner hash table(s). |
|
101 |
- * @return 0 on success, -1 on error. |
|
102 |
- */ |
|
103 |
-int init_counters() |
|
104 |
-{ |
|
105 |
- if (str_hash_alloc(&cnts_hash_table, CNT_HASH_SIZE) < 0) |
|
106 |
- goto error; |
|
107 |
- str_hash_init(&cnts_hash_table); |
|
108 |
- if (str_hash_alloc(&grp_hash_table, GRP_HASH_SIZE) < 0) |
|
109 |
- goto error; |
|
110 |
- str_hash_init(&grp_hash_table); |
|
111 |
- cnts_no = 1; /* start at 1 (0 used only for invalid counters) */ |
|
112 |
- cnts_max_rows = 0; /* 0 initially, !=0 after full init |
|
113 |
- (counters_prefork_init()) */ |
|
114 |
- grp_no = 0; |
|
115 |
- cnt_id2record_size = CNT_ID2RECORD_SIZE; |
|
116 |
- cnt_id2record = pkg_malloc(sizeof(*cnt_id2record) * cnt_id2record_size); |
|
117 |
- if (cnt_id2record == 0) |
|
118 |
- goto error; |
|
119 |
- memset(cnt_id2record, 0, sizeof(*cnt_id2record) * cnt_id2record_size); |
|
120 |
- grp_sorted_max_size = GRP_SORTED_SIZE; |
|
121 |
- grp_sorted_crt_size = 0; |
|
122 |
- grp_sorted = pkg_malloc(sizeof(*grp_sorted) * grp_sorted_max_size); |
|
123 |
- if (grp_sorted == 0) |
|
124 |
- goto error; |
|
125 |
- memset(grp_sorted, 0, sizeof(*grp_sorted) * grp_sorted_max_size); |
|
126 |
- return 0; |
|
127 |
-error: |
|
128 |
- destroy_counters(); |
|
129 |
- return -1; |
|
130 |
-} |
|
131 |
- |
|
132 |
- |
|
133 |
- |
|
134 |
-void destroy_counters() |
|
135 |
-{ |
|
136 |
- int r; |
|
137 |
- struct str_hash_entry* e; |
|
138 |
- struct str_hash_entry* bak; |
|
139 |
- if (_cnts_vals) { |
|
140 |
- if (cnts_max_rows) |
|
141 |
- /* fully init => it is in shm */ |
|
142 |
- shm_free(_cnts_vals); |
|
143 |
- else |
|
144 |
- /* partially init (before prefork) => pkg */ |
|
145 |
- pkg_free(_cnts_vals); |
|
146 |
- _cnts_vals = 0; |
|
147 |
- } |
|
148 |
- if (cnts_hash_table.table) { |
|
149 |
- for (r=0; r< cnts_hash_table.size; r++) { |
|
150 |
- clist_foreach_safe(&cnts_hash_table.table[r], e, bak, next) { |
|
151 |
- pkg_free(e); |
|
152 |
- } |
|
153 |
- } |
|
154 |
- pkg_free(cnts_hash_table.table); |
|
155 |
- } |
|
156 |
- if (grp_hash_table.table) { |
|
157 |
- for (r=0; r< grp_hash_table.size; r++) { |
|
158 |
- clist_foreach_safe(&grp_hash_table.table[r], e, bak, next) { |
|
159 |
- pkg_free(e); |
|
160 |
- } |
|
161 |
- } |
|
162 |
- pkg_free(grp_hash_table.table); |
|
163 |
- } |
|
164 |
- if (cnt_id2record) |
|
165 |
- pkg_free(cnt_id2record); |
|
166 |
- if (grp_sorted) |
|
167 |
- pkg_free(grp_sorted); |
|
168 |
- cnts_hash_table.table = 0; |
|
169 |
- cnts_hash_table.size = 0; |
|
170 |
- cnt_id2record = 0; |
|
171 |
- grp_sorted = 0; |
|
172 |
- grp_hash_table.table = 0; |
|
173 |
- grp_hash_table.size = 0; |
|
174 |
- grp_sorted_crt_size = 0; |
|
175 |
- grp_sorted_max_size = 0; |
|
176 |
- cnts_no = 0; |
|
177 |
- _cnts_row_len = 0; |
|
178 |
- cnts_max_rows = 0; |
|
179 |
- grp_no = 0; |
|
180 |
-} |
|
181 |
- |
|
182 |
- |
|
183 |
- |
|
184 |
-/** complete counter intialization, when the number of processes is known. |
|
185 |
- * shm must be available. |
|
186 |
- * @return 0 on success, < 0 on error |
|
187 |
- */ |
|
188 |
-int counters_prefork_init(int max_process_no) |
|
189 |
-{ |
|
190 |
- counter_array_t* old; |
|
191 |
- int size, row_size; |
|
192 |
- counter_handle_t h; |
|
193 |
- /* round cnts_no so that cnts_no * sizeof(counter) it's a CACHELINE_PAD |
|
194 |
- multiple */ |
|
195 |
- /* round-up row_size to a CACHELINE_PAD multiple if needed */ |
|
196 |
- row_size = ((sizeof(*_cnts_vals) * cnts_no - 1) / CACHELINE_PAD + 1) * |
|
197 |
- CACHELINE_PAD; |
|
198 |
- /* round-up the resulted row_siue to a sizeof(*_cnts_vals) multiple */ |
|
199 |
- row_size = ((row_size -1) / sizeof(*_cnts_vals) + 1) * |
|
200 |
- sizeof(*_cnts_vals); |
|
201 |
- /* get updated cnts_no (row length) */ |
|
202 |
- _cnts_row_len = row_size / sizeof(*_cnts_vals); |
|
203 |
- size = max_process_no * row_size; |
|
204 |
- /* replace the temporary pre-fork pkg array (with only 1 row) with |
|
205 |
- the final shm version (with max_process_no rows) */ |
|
206 |
- old = _cnts_vals; |
|
207 |
- _cnts_vals = shm_malloc(size); |
|
208 |
- if (_cnts_vals == 0) |
|
209 |
- return -1; |
|
210 |
- memset(_cnts_vals, 0, size); |
|
211 |
- cnts_max_rows = max_process_no; |
|
212 |
- /* copy prefork values into the newly shm array */ |
|
213 |
- if (old) { |
|
214 |
- for (h.id = 0; h.id < cnts_no; h.id++) |
|
215 |
- counter_pprocess_val(process_no, h) = old[h.id].v; |
|
216 |
- pkg_free(old); |
|
217 |
- } |
|
218 |
- return 0; |
|
219 |
-} |
|
220 |
- |
|
221 |
- |
|
222 |
- |
|
223 |
-/** adds new group to the group hash table (no checks, internal version). |
|
224 |
- * @return pointer to new group record on success, 0 on error. |
|
225 |
- */ |
|
226 |
-static struct grp_record* grp_hash_add(str* group) |
|
227 |
-{ |
|
228 |
- struct str_hash_entry* g; |
|
229 |
- struct grp_record* grp_rec; |
|
230 |
- struct grp_record** r; |
|
231 |
- |
|
232 |
- /* grp_rec copied at &g->u.data */ |
|
233 |
- g = pkg_malloc(sizeof(struct str_hash_entry) - sizeof(g->u.data) + |
|
234 |
- sizeof(*grp_rec) + group->len + 1); |
|
235 |
- if (g == 0) |
|
236 |
- goto error; |
|
237 |
- grp_rec = (struct grp_record*)&g->u.data[0]; |
|
238 |
- grp_rec->group.s = (char*)(grp_rec + 1); |
|
239 |
- grp_rec->group.len = group->len; |
|
240 |
- grp_rec->first = 0; |
|
241 |
- memcpy(grp_rec->group.s, group->s, group->len + 1); |
|
242 |
- g->key = grp_rec->group; |
|
243 |
- g->flags = 0; |
|
244 |
- /* insert group into the sorted group array */ |
|
245 |
- if (grp_sorted_max_size <= grp_sorted_crt_size) { |
|
246 |
- /* must increase the array */ |
|
247 |
- r = pkg_realloc(grp_sorted, 2 * grp_sorted_max_size * |
|
248 |
- sizeof(*grp_sorted)); |
|
249 |
- if (r == 0) |
|
250 |
- goto error; |
|
251 |
- grp_sorted= r; |
|
252 |
- grp_sorted_max_size *= 2; |
|
253 |
- memset(&grp_sorted[grp_sorted_crt_size], 0, |
|
254 |
- (grp_sorted_max_size - grp_sorted_crt_size) * |
|
255 |
- sizeof(*grp_sorted)); |
|
256 |
- } |
|
257 |
- for (r = grp_sorted; r < (grp_sorted + grp_sorted_crt_size); r++) |
|
258 |
- if (strcmp(grp_rec->group.s, (*r)->group.s) < 0) |
|
259 |
- break; |
|
260 |
- if (r != (grp_sorted + grp_sorted_crt_size)) |
|
261 |
- memmove(r+1, r, (int)(long)((char*)(grp_sorted + grp_sorted_crt_size) - |
|
262 |
- (char*)r)); |
|
263 |
- grp_sorted_crt_size++; |
|
264 |
- *r = grp_rec; |
|
265 |
- /* insert into the hash only on success */ |
|
266 |
- str_hash_add(&grp_hash_table, g); |
|
267 |
- return grp_rec; |
|
268 |
-error: |
|
269 |
- if (g) |
|
270 |
- pkg_free(g); |
|
271 |
- return 0; |
|
272 |
-} |
|
273 |
- |
|
274 |
- |
|
275 |
- |
|
276 |
-/** lookup a group into the group hash (internal version). |
|
277 |
- * @return pointer to grp_record on success, 0 on failure (not found). |
|
278 |
- */ |
|
279 |
-static struct grp_record* grp_hash_lookup(str* group) |
|
280 |
-{ |
|
281 |
- struct str_hash_entry* e; |
|
282 |
- e = str_hash_get(&grp_hash_table, group->s, group->len); |
|
283 |
- return e?(struct grp_record*)&e->u.data[0]:0; |
|
284 |
-} |
|
285 |
- |
|
286 |
- |
|
287 |
- |
|
288 |
-/** lookup a group and if not found create a new group record. |
|
289 |
- * @return pointer to grp_record on succes, 0 on failure ( not found and |
|
290 |
- * failed to create new group record). |
|
291 |
- */ |
|
292 |
-static struct grp_record* grp_hash_get_create(str* group) |
|
293 |
-{ |
|
294 |
- struct grp_record* ret; |
|
295 |
- |
|
296 |
- ret = grp_hash_lookup(group); |
|
297 |
- if (ret) |
|
298 |
- return ret; |
|
299 |
- return grp_hash_add(group); |
|
300 |
-} |
|
301 |
- |
|
302 |
- |
|
303 |
- |
|
304 |
-/** adds new counter to the hash table (no checks, internal version). |
|
305 |
- * @return pointer to new record on success, 0 on error. |
|
306 |
- */ |
|
307 |
-static struct counter_record* cnt_hash_add( |
|
308 |
- str* group, str* name, |
|
309 |
- int flags, counter_cbk_f cbk, |
|
310 |
- void* param, const char* doc) |
|
311 |
-{ |
|
312 |
- struct str_hash_entry* e; |
|
313 |
- struct counter_record* cnt_rec; |
|
314 |
- struct grp_record* grp_rec; |
|
315 |
- struct counter_record** p; |
|
316 |
- counter_array_t* v; |
|
317 |
- int doc_len; |
|
318 |
- int n; |
|
319 |
- |
|
320 |
- e = 0; |
|
321 |
- if (cnts_no >= MAX_COUNTER_ID) |
|
322 |
- /* too many counters */ |
|
323 |
- goto error; |
|
324 |
- grp_rec = grp_hash_get_create(group); |
|
325 |
- if (grp_rec == 0) |
|
326 |
- /* non existing group an no new one could be created */ |
|
327 |
- goto error; |
|
328 |
- doc_len = doc?strlen(doc):0; |
|
329 |
- /* cnt_rec copied at &e->u.data[0] */ |
|
330 |
- e = pkg_malloc(sizeof(struct str_hash_entry) - sizeof(e->u.data) + |
|
331 |
- sizeof(*cnt_rec) + name->len + 1 + group->len + 1 + |
|
332 |
- doc_len + 1); |
|
333 |
- if (e == 0) |
|
334 |
- goto error; |
|
335 |
- cnt_rec = (struct counter_record*)&e->u.data[0]; |
|
336 |
- cnt_rec->group.s = (char*)(cnt_rec + 1); |
|
337 |
- cnt_rec->group.len = group->len; |
|
338 |
- cnt_rec->name.s = cnt_rec->group.s + group->len + 1; |
|
339 |
- cnt_rec->name.len = name->len; |
|
340 |
- cnt_rec->doc.s = cnt_rec->name.s + name->len +1; |
|
341 |
- cnt_rec->doc.len = doc_len; |
|
342 |
- cnt_rec->h.id = cnts_no++; |
|
343 |
- cnt_rec->flags = flags; |
|
344 |
- cnt_rec->cbk_param = param; |
|
345 |
- cnt_rec->cbk = cbk; |
|
346 |
- cnt_rec->grp_next = 0; |
|
347 |
- memcpy(cnt_rec->group.s, group->s, group->len + 1); |
|
348 |
- memcpy(cnt_rec->name.s, name->s, name->len + 1); |
|
349 |
- if (doc) |
|
350 |
- memcpy(cnt_rec->doc.s, doc, doc_len + 1); |
|
351 |
- else |
|
352 |
- cnt_rec->doc.s[0] = 0; |
|
353 |
- e->key = cnt_rec->name; |
|
354 |
- e->flags = 0; |
|
355 |
- /* check to see if it fits in the prefork tmp. vals array. |
|
356 |
- This array contains only one "row", is allocated in pkg and |
|
357 |
- is used only until counters_prefork_init() (after that the |
|
358 |
- array is replaced with a shm version with all the needed rows). |
|
359 |
- */ |
|
360 |
- if (cnt_rec->h.id >= _cnts_row_len || _cnts_vals == 0) { |
|
361 |
- /* array to small or not yet allocated => reallocate/allocate it |
|
362 |
- (min size PREINIT_CNTS_VALS_SIZE, max MAX_COUNTER_ID) |
|
363 |
- */ |
|
364 |
- n = (cnt_rec->h.id < PREINIT_CNTS_VALS_SIZE) ? |
|
365 |
- PREINIT_CNTS_VALS_SIZE : |
|
366 |
- ((2 * (cnt_rec->h.id + (cnt_rec->h.id == 0)) < MAX_COUNTER_ID)? |
|
367 |
- (2 * (cnt_rec->h.id + (cnt_rec->h.id == 0))) : |
|
368 |
- MAX_COUNTER_ID + 1); |
|
369 |
- v = pkg_realloc(_cnts_vals, n * sizeof(*_cnts_vals)); |
|
370 |
- if (v == 0) |
|
371 |
- /* realloc/malloc error */ |
|
372 |
- goto error; |
|
373 |
- _cnts_vals = v; |
|
374 |
- /* zero newly allocated memory */ |
|
375 |
- memset(&_cnts_vals[_cnts_row_len], 0, |
|
376 |
- (n - _cnts_row_len) * sizeof(*_cnts_vals)); |
|
377 |
- _cnts_row_len = n; /* record new length */ |
|
378 |
- } |
|
379 |
- /* add a pointer to it in the records array */ |
|
380 |
- if (cnt_id2record_size <= cnt_rec->h.id) { |
|
381 |
- /* must increase the array */ |
|
382 |
- p = pkg_realloc(cnt_id2record, |
|
383 |
- 2 * cnt_id2record_size * sizeof(*cnt_id2record)); |
|
384 |
- if (p == 0) |
|
385 |
- goto error; |
|
386 |
- cnt_id2record = p; |
|
387 |
- cnt_id2record_size *= 2; |
|
388 |
- memset(&cnt_id2record[cnt_rec->h.id], 0, |
|
389 |
- (cnt_id2record_size - cnt_rec->h.id) * sizeof(*cnt_id2record)); |
|
390 |
- } |
|
391 |
- cnt_id2record[cnt_rec->h.id] = cnt_rec; |
|
392 |
- /* add into the hash */ |
|
393 |
- str_hash_add(&cnts_hash_table, e); |
|
394 |
- /* insert it sorted in the per group list */ |
|
395 |
- for (p = &grp_rec->first; *p; p = &((*p)->grp_next)) |
|
396 |
- if (strcmp(cnt_rec->name.s, (*p)->name.s) < 0) |
|
397 |
- break; |
|
398 |
- cnt_rec->grp_next = *p; |
|
399 |
- *p = cnt_rec; |
|
400 |
- return cnt_rec; |
|
401 |
-error: |
|
402 |
- if (e) |
|
403 |
- pkg_free(e); |
|
404 |
- return 0; |
|
405 |
-} |
|
406 |
- |
|
407 |
- |
|
408 |
- |
|
409 |
-/** lookup a (group, name) pair into the cnts hash (internal version). |
|
410 |
- * @param group - counter group name. If "" the first matching counter with |
|
411 |
- * the given name will be returned (k compat). |
|
412 |
- * @param name |
|
413 |
- * @return pointer to counter_record on success, 0 on failure (not found). |
|
414 |
- */ |
|
415 |
-static struct counter_record* cnt_hash_lookup(str* group, str* name) |
|
416 |
-{ |
|
417 |
- struct str_hash_entry* e; |
|
418 |
- struct str_hash_entry* first; |
|
419 |
- struct counter_record* cnt_rec; |
|
420 |
- e = str_hash_get(&cnts_hash_table, name->s, name->len); |
|
421 |
- /* fast path */ |
|
422 |
- if (likely(e)) { |
|
423 |
- cnt_rec = (struct counter_record*)&e->u.data[0]; |
|
424 |
- if (likely( group->len == 0 || |
|
425 |
- (cnt_rec->group.len == group->len && |
|
426 |
- memcmp(cnt_rec->group.s, group->s, group->len) == 0))) |
|
427 |
- return cnt_rec; |
|
428 |
- } else |
|
429 |
- return 0; |
|
430 |
- /* search between records with same name, but different groups */ |
|
431 |
- first = e; |
|
432 |
- do { |
|
433 |
- cnt_rec = (struct counter_record*)&e->u.data[0]; |
|
434 |
- if (cnt_rec->group.len == group->len && |
|
435 |
- cnt_rec->name.len == name->len && |
|
436 |
- memcmp(cnt_rec->group.s, group->s, group->len) == 0 && |
|
437 |
- memcmp(cnt_rec->name.s, name->s, name->len) == 0) |
|
438 |
- /* found */ |
|
439 |
- return cnt_rec; |
|
440 |
- e = e->next; |
|
441 |
- } while(e != first); |
|
442 |
- return 0; |
|
443 |
-} |
|
444 |
- |
|
445 |
- |
|
446 |
- |
|
447 |
-/** lookup a counter and if not found create a new counter record. |
|
448 |
- * @return pointer to counter_record on succes, 0 on failure ( not found and |
|
449 |
- * failed to create new group record). |
|
450 |
- */ |
|
451 |
-static struct counter_record* cnt_hash_get_create( |
|
452 |
- str* group, str* name, |
|
453 |
- int flags, |
|
454 |
- counter_cbk_f cbk, |
|
455 |
- void* param, const char* doc) |
|
456 |
-{ |
|
457 |
- struct counter_record* ret; |
|
458 |
- |
|
459 |
- ret = cnt_hash_lookup(group, name); |
|
460 |
- if (ret) |
|
461 |
- return ret; |
|
462 |
- return cnt_hash_add(group, name, flags, cbk, param, doc); |
|
463 |
-} |
|
464 |
- |
|
465 |
- |
|
466 |
- |
|
467 |
-/** register a new counter. |
|
468 |
- * Can be called only before forking (e.g. from mod_init() or |
|
469 |
- * init_child(PROC_INIT)). |
|
470 |
- * @param handle - result parameter, it will be filled with the counter |
|
471 |
- * handle on success (can be null if not needed). |
|
472 |
- * @param group - group name |
|
473 |
- * @param name - counter name (group.name must be unique). |
|
474 |
- * @param flags - counter flags: one of CNT_F_*. |
|
475 |
- * @param cbk - read callback function (if set it will be called each time |
|
476 |
- * someone will call counter_get()). |
|
477 |
- * @param cbk_param - callback param. |
|
478 |
- * @param doc - description/documentation string. |
|
479 |
- * @param reg_flags - register flags: 1 - don't fail if counter already |
|
480 |
- * registered (act like counter_lookup(handle, group, name). |
|
481 |
- * @return 0 on succes, < 0 on error (-1 not init or malloc error, -2 already |
|
482 |
- * registered (and register_flags & 1 == 0). |
|
483 |
- */ |
|
484 |
-int counter_register( counter_handle_t* handle, const char* group, |
|
485 |
- const char* name, int flags, |
|
486 |
- counter_cbk_f cbk, void* cbk_param, |
|
487 |
- const char* doc, |
|
488 |
- int reg_flags) |
|
489 |
-{ |
|
490 |
- str grp; |
|
491 |
- str n; |
|
492 |
- struct counter_record* cnt_rec; |
|
493 |
- |
|
494 |
- if (unlikely(cnts_max_rows)) { |
|
495 |
- /* too late */ |
|
496 |
- BUG("late attempt to register counter: %s.%s\n", group, name); |
|
497 |
- goto error; |
|
498 |
- } |
|
499 |
- n.s = (char*)name; |
|
500 |
- n.len = strlen(name); |
|
501 |
- if (unlikely(group == 0 || *group == 0)) { |
|
502 |
- BUG("attempt to register counter %s without a group\n", name); |
|
503 |
- goto error; |
|
504 |
- } |
|
505 |
- grp.s = (char*)group; |
|
506 |
- grp.len = strlen(group); |
|
507 |
- cnt_rec = cnt_hash_lookup(&grp, &n); |
|
508 |
- if (cnt_rec) { |
|
509 |
- if (reg_flags & 1) |
|
510 |
- goto found; |
|
511 |
- else { |
|
512 |
- if (handle) handle->id = 0; |
|
513 |
- return -2; |
|
514 |
- } |
|
515 |
- } else |
|
516 |
- cnt_rec = cnt_hash_get_create(&grp, &n, flags, cbk, cbk_param, doc); |
|
517 |
- if (unlikely(cnt_rec == 0)) |
|
518 |
- goto error; |
|
519 |
-found: |
|
520 |
- if (handle) *handle = cnt_rec->h; |
|
521 |
- return 0; |
|
522 |
-error: |
|
523 |
- if (handle) handle->id = 0; |
|
524 |
- return -1; |
|
525 |
-} |
|
526 |
- |
|
527 |
- |
|
528 |
- |
|
529 |
-/** fill in the handle of an existing counter (str parameters). |
|
530 |
- * @param handle - filled with the corresp. handle on success. |
|
531 |
- * @param group - counter group name. If "" the first matching |
|
532 |
- * counter with the given name will be returned |
|
533 |
- * (k compat). |
|
534 |
- * @param name - counter name. |
|
535 |
- * @return 0 on success, < 0 on error |
|
536 |
- */ |
|
537 |
-int counter_lookup_str(counter_handle_t* handle, str* group, str* name) |
|
538 |
-{ |
|
539 |
- struct counter_record* cnt_rec; |
|
540 |
- |
|
541 |
- cnt_rec = cnt_hash_lookup(group, name); |
|
542 |
- if (likely(cnt_rec)) { |
|
543 |
- *handle = cnt_rec->h; |
|
544 |
- return 0; |
|
545 |
- } |
|
546 |
- handle->id = 0; |
|
547 |
- return -1; |
|
548 |
-} |
|
549 |
- |
|
550 |
- |
|
551 |
- |
|
552 |
-/** fill in the handle of an existing counter (asciiz parameters). |
|
553 |
- * @param handle - filled with the corresp. handle on success. |
|
554 |
- * @param group - counter group name. If 0 or "" the first matching |
|
555 |
- * counter with the given name will be returned |
|
556 |
- * (k compat). |
|
557 |
- * @param name - counter name. |
|
558 |
- * @return 0 on success, < 0 on error |
|
559 |
- */ |
|
560 |
-int counter_lookup(counter_handle_t* handle, |
|
561 |
- const char* group, const char* name) |
|
562 |
-{ |
|
563 |
- str grp; |
|
564 |
- str n; |
|
565 |
- |
|
566 |
- n.s = (char*)name; |
|
567 |
- n.len = strlen(name); |
|
568 |
- grp.s = (char*)group; |
|
569 |
- grp.len = group?strlen(group):0; |
|
570 |
- return counter_lookup_str(handle, &grp, &n); |
|
571 |
-} |
|
572 |
- |
|
573 |
- |
|
574 |
- |
|
575 |
-/** register all the counters declared in a null-terminated array. |
|
576 |
- * @param group - counters group. |
|
577 |
- * @param defs - null terminated array containing counters definitions. |
|
578 |
- * @return 0 on success, < 0 on error ( - (counter_number+1)) |
|
579 |
- */ |
|
580 |
-int counter_register_array(const char* group, counter_def_t* defs) |
|
581 |
-{ |
|
582 |
- int r; |
|
583 |
- |
|
584 |
- for (r=0; defs[r].name; r++) |
|
585 |
- if (counter_register( defs[r].handle, |
|
586 |
- group, defs[r].name, defs[r].flags, |
|
587 |
- defs[r].get_cbk, defs[r].get_cbk_param, |
|
588 |
- defs[r].descr, 0) <0) |
|
589 |
- return -(r+1); /* return - (idx of bad counter + 1) */ |
|
590 |
- return 0; |
|
591 |
-} |
|
592 |
- |
|
593 |
- |
|
594 |
- |
|
595 |
-/** get the value of the counter, bypassing callbacks. |
|
596 |
- * @param handle - counter handle obtained using counter_lookup() or |
|
597 |
- * counter_register(). |
|
598 |
- * @return counter value. |
|
599 |
- */ |
|
600 |
-counter_val_t counter_get_raw_val(counter_handle_t handle) |
|
601 |
-{ |
|
602 |
- int r; |
|
603 |
- counter_val_t ret; |
|
604 |
- |
|
605 |
- if (unlikely(_cnts_vals == 0)) { |
|
606 |
- /* not init yet */ |
|
607 |
- BUG("counters not fully initialized yet\n"); |
|
608 |
- return 0; |
|
609 |
- } |
|
610 |
- if (unlikely(handle.id >= cnts_no || (short)handle.id < 0)) { |
|
611 |
- BUG("invalid counter id %d (max %d)\n", handle.id, cnts_no - 1); |
|
612 |
- return 0; |
|
613 |
- } |
|
614 |
- ret = 0; |
|
615 |
- for (r = 0; r < cnts_max_rows; r++) |
|
616 |
- ret += counter_pprocess_val(r, handle); |
|
617 |
- return ret; |
|
618 |
-} |
|
619 |
- |
|
620 |
- |
|
621 |
- |
|
622 |
-/** get the value of the counter, using the callbacks (if defined). |
|
623 |
- * @param handle - counter handle obtained using counter_lookup() or |
|
624 |
- * counter_register(). |
|
625 |
- * @return counter value. */ |
|
626 |
-counter_val_t counter_get_val(counter_handle_t handle) |
|
627 |
-{ |
|
628 |
- struct counter_record* cnt_rec; |
|
629 |
- |
|
630 |
- if (unlikely(_cnts_vals == 0 || cnt_id2record == 0)) { |
|
631 |
- /* not init yet */ |
|
632 |
- BUG("counters not fully initialized yet\n"); |
|
633 |
- return 0; |
|
634 |
- } |
|
635 |
- cnt_rec = cnt_id2record[handle.id]; |
|
636 |
- if (unlikely(cnt_rec->cbk)) |
|
637 |
- return cnt_rec->cbk(handle, cnt_rec->cbk_param); |
|
638 |
- return counter_get_raw_val(handle); |
|
639 |
-} |
|
640 |
- |
|
641 |
- |
|
642 |
- |
|
643 |
-/** reset the counter. |
|
644 |
- * Reset a counter, unless it has the CNT_F_NO_RESET flag set. |
|
645 |
- * @param handle - counter handle obtained using counter_lookup() or |
|
646 |
- * counter_register(). |
|
647 |
- * Note: it's racy. |
|
648 |
- */ |
|
649 |
-void counter_reset(counter_handle_t handle) |
|
650 |
-{ |
|
651 |
- int r; |
|
652 |
- |
|
653 |
- if (unlikely(_cnts_vals == 0 || cnt_id2record == 0)) { |
|
654 |
- /* not init yet */ |
|
655 |
- BUG("counters not fully initialized yet\n"); |
|
656 |
- return; |
|
657 |
- } |
|
658 |
- if (unlikely(handle.id >= cnts_no)) { |
|
659 |
- BUG("invalid counter id %d (max %d)\n", handle.id, cnts_no - 1); |
|
660 |
- return; |
|
661 |
- } |
|
662 |
- if (unlikely(cnt_id2record[handle.id]->flags & CNT_F_NO_RESET)) |
|
663 |
- return; |
|
664 |
- for (r=0; r < cnts_max_rows; r++) |
|
665 |
- counter_pprocess_val(r, handle) = 0; |
|
666 |
- return; |
|
667 |
-} |
|
668 |
- |
|
669 |
- |
|
670 |
- |
|
671 |
-/** return the name for counter handle. |
|
672 |
- * @param handle - counter handle obtained using counter_lookup() or |
|
673 |
- * counter_register(). |
|
674 |
- * @return asciiz pointer on success, 0 on error. |
|
675 |
- */ |
|
676 |
-char* counter_get_name(counter_handle_t handle) |
|
677 |
-{ |
|
678 |
- if (unlikely(_cnts_vals == 0 || cnt_id2record == 0)) { |
|
679 |
- /* not init yet */ |
|
680 |
- BUG("counters not fully initialized yet\n"); |
|
681 |
- goto error; |
|
682 |
- } |
|
683 |
- if (unlikely(handle.id >= cnts_no)) { |
|
684 |
- BUG("invalid counter id %d (max %d)\n", handle.id, cnts_no - 1); |
|
685 |
- goto error; |
|
686 |
- } |
|
687 |
- return cnt_id2record[handle.id]->name.s; |
|
688 |
-error: |
|
689 |
- return 0; |
|
690 |
-} |
|
691 |
- |
|
692 |
- |
|
693 |
- |
|
694 |
-/** return the group name for counter handle. |
|
695 |
- * @param handle - counter handle obtained using counter_lookup() or |
|
696 |
- * counter_register(). |
|
697 |
- * @return asciiz pointer on success, 0 on error. |
|
698 |
- */ |
|
699 |
-char* counter_get_group(counter_handle_t handle) |
|
700 |
-{ |
|
701 |
- if (unlikely(_cnts_vals == 0 || cnt_id2record == 0)) { |
|
702 |
- /* not init yet */ |
|
703 |
- BUG("counters not fully initialized yet\n"); |
|
704 |
- goto error; |
|
705 |
- } |
|
706 |
- if (unlikely(handle.id >= cnts_no)) { |
|
707 |
- BUG("invalid counter id %d (max %d)\n", handle.id, cnts_no - 1); |
|
708 |
- goto error; |
|
709 |
- } |
|
710 |
- return cnt_id2record[handle.id]->group.s; |
|
711 |
-error: |
|
712 |
- return 0; |
|
713 |
-} |
|
714 |
- |
|
715 |
- |
|
716 |
- |
|
717 |
-/** return the description (doc) string for a given counter. |
|
718 |
- * @param handle - counter handle obtained using counter_lookup() or |
|
719 |
- * counter_register(). |
|
720 |
- * @return asciiz pointer on success, 0 on error. |
|
721 |
- */ |
|
722 |
-char* counter_get_doc(counter_handle_t handle) |
|
723 |
-{ |
|
724 |
- if (unlikely(_cnts_vals == 0 || cnt_id2record == 0)) { |
|
725 |
- /* not init yet */ |
|
726 |
- BUG("counters not fully initialized yet\n"); |
|
727 |
- goto error; |
|
728 |
- } |
|
729 |
- if (unlikely(handle.id >= cnts_no)) { |
|
730 |
- BUG("invalid counter id %d (max %d)\n", handle.id, cnts_no - 1); |
|
731 |
- goto error; |
|
732 |
- } |
|
733 |
- return cnt_id2record[handle.id]->doc.s; |
|
734 |
-error: |
|
735 |
- return 0; |
|
736 |
-} |
|
737 |
- |
|
738 |
- |
|
739 |
- |
|
740 |
-/** iterate on all the counter group names. |
|
741 |
- * @param cbk - pointer to a callback function that will be called for each |
|
742 |
- * group name. |
|
743 |
- * @param p - parameter that will be passed to the callback function |
|
744 |
- * (along the group name). |
|
745 |
- */ |
|
746 |
-void counter_iterate_grp_names(void (*cbk)(void* p, str* grp_name), void* p) |
|
747 |
-{ |
|
748 |
- int r; |
|
749 |
- |
|
750 |
- for (r=0; r < grp_sorted_crt_size; r++) |
|
751 |
- cbk(p, &grp_sorted[r]->group); |
|
752 |
-} |
|
753 |
- |
|
754 |
- |
|
755 |
- |
|
756 |
-/** iterate on all the variable names in a specified group. |
|
757 |
- * @param group - group name. |
|
758 |
- * @param cbk - pointer to a callback function that will be called for each |
|
759 |
- * variable name. |
|
760 |
- * @param p - parameter that will be passed to the callback function |
|
761 |
- * (along the variable name). |
|
762 |
- */ |
|
763 |
-void counter_iterate_grp_var_names( const char* group, |
|
764 |
- void (*cbk)(void* p, str* var_name), |
|
765 |
- void* p) |
|
766 |
-{ |
|
767 |
- struct counter_record* r; |
|
768 |
- struct grp_record* g; |
|
769 |
- str grp; |
|
770 |
- |
|
771 |
- grp.s = (char*)group; |
|
772 |
- grp.len = strlen(group); |
|
773 |
- g = grp_hash_lookup(&grp); |
|
774 |
- if (g) |
|
775 |
- for (r = g->first; r; r = r->grp_next) |
|
776 |
- cbk(p, &r->name); |
|
777 |
-} |
|
778 |
- |
|
779 |
- |
|
780 |
- |
|
781 |
-/** iterate on all the variable names and handles in a specified group. |
|
782 |
- * @param group - group name. |
|
783 |
- * @param cbk - pointer to a callback function that will be called for each |
|
784 |
- * [variable name, variable handle] pair. |
|
785 |
- * @param p - parameter that will be passed to the callback function |
|
786 |
- * (along the group name, variable name and variable handle). |
|
787 |
- */ |
|
788 |
-void counter_iterate_grp_vars(const char* group, |
|
789 |
- void (*cbk)(void* p, str* g, str* n, |
|
790 |
- counter_handle_t h), |
|
791 |
- void *p) |
|
792 |
-{ |
|
793 |
- struct counter_record* r; |
|
794 |
- struct grp_record* g; |
|
795 |
- str grp; |
|
796 |
- |
|
797 |
- grp.s = (char*)group; |
|
798 |
- grp.len = strlen(group); |
|
799 |
- g = grp_hash_lookup(&grp); |
|
800 |
- if (g) |
|
801 |
- for (r = g->first; r; r = r->grp_next) |
|
802 |
- cbk(p, &r->group, &r->name, r->h); |
|
803 |
-} |
|
804 |
- |
|
805 |
-#ifdef STATISTICS |
|
806 |
- |
|
807 |
- |
|
808 |
-/** internal wrapper for kamailio type stat callbacks. |
|
809 |
- * sr counter callbacks are different from the kamailio type stat callbacks. |
|
810 |
- * This function is meant as a sr counter callback that will call |
|
811 |
- * k stat callback passed as parameter. |
|
812 |
- * @param h - not used. |
|
813 |
- * @param param - k stat callback function pointer (stat_function). |
|
814 |
- * @return result of calling the passed k stat_function. |
|
815 |
- */ |
|
816 |
-static counter_val_t cnt_cbk_wrapper(counter_handle_t h, void* param) |
|
817 |
-{ |
|
818 |
- stat_function k_stat_f; |
|
819 |
- |
|
820 |
- k_stat_f = param; |
|
821 |
- return k_stat_f(); |
|
822 |
-} |
|
823 |
- |
|
824 |
- |
|
825 |
- |
|
826 |
-int register_stat( char *module, char *name, stat_var **pvar, int flags) |
|
827 |
-{ |
|
828 |
- int cnt_flags; |
|
829 |
- counter_handle_t h; |
|
830 |
- int ret; |
|
831 |
- |
|
832 |
- if (module == 0 || name == 0 || pvar == 0) { |
|
833 |
- BUG("invalid parameters (%p, %p, %p)\n", module, name, pvar); |
|
834 |
- return -1; |
|
835 |
- } |
|
836 |
- /* translate kamailio stat flags into sr counter flags */ |
|
837 |
- cnt_flags = (flags & STAT_NO_RESET) ? CNT_F_NO_RESET : 0; |
|
838 |
- if (flags & STAT_IS_FUNC) |
|
839 |
- ret = counter_register(&h, module, name, cnt_flags, |
|
840 |
- cnt_cbk_wrapper,(stat_function)pvar, |
|
841 |
- "kamailio statistic (no description)", |
|
842 |
- 0); |
|
843 |
- else |
|
844 |
- ret = counter_register(&h, module, name, cnt_flags, 0, 0, |
|
845 |
- "kamailio statistic (no description)", 0); |
|
846 |
- if (ret < 0) { |
|
847 |
- if (ret == -2) |
|
848 |
- ERR("counter %s.%s already registered\n", module, name); |
|
849 |
- goto error; |
|
850 |
- } |
|
851 |
- if (!(flags & STAT_IS_FUNC)) |
|
852 |
- *pvar = (void*)(unsigned long)h.id; |
|
853 |
- return 0; |
|
854 |
-error: |
|
855 |
- if (!(flags & STAT_IS_FUNC)) |
|
856 |
- *pvar = 0; |
|
857 |
- return -1; |
|
858 |
-} |
|
859 |
- |
|
860 |
- |
|
861 |
- |
|
862 |
-int register_module_stats(char *module, stat_export_t *stats) |
|
863 |
-{ |
|
864 |
- if (module == 0 || *module == 0) { |
|
865 |
- BUG("null or empty module name\n"); |
|
866 |
- goto error; |
|
867 |
- } |
|
868 |
- if (stats == 0 || stats[0].name == 0) |
|
869 |
- /* empty stats */ |
|
870 |
- return 0; |
|
871 |
- for (; stats->name; stats++) |
|
872 |
- if (register_stat(module, stats->name, stats->stat_pointer, |
|
873 |
- stats->flags) < 0 ){ |
|
874 |
- ERR("failed to add statistic %s.%s\n", module, stats->name); |
|
875 |
- goto error; |
|
876 |
- } |
|
877 |
- return 0; |
|
878 |
-error: |
|
879 |
- return -1; |
|
880 |
-} |
|
881 |
- |
|
882 |
-#endif /* STATISTICS */ |
|
883 |
- |
|
884 |
-/* vi: set ts=4 sw=4 tw=79:ai:cindent: */ |
- instead of kcore stats wrapers, use directly counters.h from core
- parse of sst header moved to sst module (only use)
- string helper functions compacted in strutils.h
- statistics helper functions used only by snmpstats module moved to it
... | ... |
@@ -802,4 +802,83 @@ void counter_iterate_grp_vars(const char* group, |
802 | 802 |
cbk(p, &r->group, &r->name, r->h); |
803 | 803 |
} |
804 | 804 |
|
805 |
+#ifdef STATISTICS |
|
806 |
+ |
|
807 |
+ |
|
808 |
+/** internal wrapper for kamailio type stat callbacks. |
|
809 |
+ * sr counter callbacks are different from the kamailio type stat callbacks. |
|
810 |
+ * This function is meant as a sr counter callback that will call |
|
811 |
+ * k stat callback passed as parameter. |
|
812 |
+ * @param h - not used. |
|
813 |
+ * @param param - k stat callback function pointer (stat_function). |
|
814 |
+ * @return result of calling the passed k stat_function. |
|
815 |
+ */ |
|
816 |
+static counter_val_t cnt_cbk_wrapper(counter_handle_t h, void* param) |
|
817 |
+{ |
|
818 |
+ stat_function k_stat_f; |
|