/src/opensips/mem/rpm_mem.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Shared memory functions |
3 | | * |
4 | | * Copyright (C) 2001-2003 FhG Fokus |
5 | | * |
6 | | * This file is part of opensips, a free SIP server. |
7 | | * |
8 | | * opensips 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 | | * opensips is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU General Public License |
19 | | * along with this program; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | | */ |
22 | | |
23 | | |
24 | | #include <stdlib.h> |
25 | | |
26 | | #include "shm_mem.h" |
27 | | #include "rpm_mem.h" |
28 | | #include "../config.h" |
29 | | #include "../globals.h" |
30 | | |
31 | | #include <unistd.h> |
32 | | #include <sys/mman.h> |
33 | | #include <sys/types.h> /*open*/ |
34 | | #include <sys/stat.h> |
35 | | #include <fcntl.h> |
36 | | |
37 | | |
38 | | enum osips_mm mem_allocator_rpm = MM_NONE; |
39 | | unsigned long rpm_mem_size = 0; |
40 | | char *rpm_mem_file = RESTART_PERSISTENCY_MEM_FILE; |
41 | | |
42 | | int set_rpm_mm(const char *mm_name) |
43 | 0 | { |
44 | | #ifdef INLINE_ALLOC |
45 | | LM_NOTICE("this is an inlined allocator build (see opensips -V), " |
46 | | "cannot set a custom rpm allocator (%s)\n", mm_name); |
47 | | return 0; |
48 | | #endif |
49 | |
|
50 | 0 | if (parse_mm(mm_name, &mem_allocator_rpm) < 0) |
51 | 0 | return -1; |
52 | | |
53 | 0 | return 0; |
54 | 0 | } |
55 | | |
56 | | #ifndef INLINE_ALLOC |
57 | | #ifdef DBG_MALLOC |
58 | | void *(*gen_rpm_malloc)(void *blk, unsigned long size, |
59 | | const char *file, const char *func, unsigned int line); |
60 | | void *(*gen_rpm_malloc_unsafe)(void *blk, unsigned long size, |
61 | | const char *file, const char *func, unsigned int line); |
62 | | void *(*gen_rpm_realloc)(void *blk, void *p, unsigned long size, |
63 | | const char *file, const char *func, unsigned int line); |
64 | | void *(*gen_rpm_realloc_unsafe)(void *blk, void *p, unsigned long size, |
65 | | const char *file, const char *func, unsigned int line); |
66 | | void (*gen_rpm_free)(void *blk, void *p, |
67 | | const char *file, const char *func, unsigned int line); |
68 | | void (*gen_rpm_free_unsafe)(void *blk, void *p, |
69 | | const char *file, const char *func, unsigned int line); |
70 | | #else |
71 | | void *(*gen_rpm_malloc)(void *blk, unsigned long size); |
72 | | void *(*gen_rpm_malloc_unsafe)(void *blk, unsigned long size); |
73 | | void *(*gen_rpm_realloc)(void *blk, void *p, unsigned long size); |
74 | | void *(*gen_rpm_realloc_unsafe)(void *blk, void *p, unsigned long size); |
75 | | void (*gen_rpm_free)(void *blk, void *p); |
76 | | void (*gen_rpm_free_unsafe)(void *blk, void *p); |
77 | | #endif |
78 | | void (*gen_rpm_info)(void *blk, struct mem_info *info); |
79 | | void (*gen_rpm_status)(void *blk); |
80 | | unsigned long (*gen_rpm_get_size)(void *blk); |
81 | | unsigned long (*gen_rpm_get_used)(void *blk); |
82 | | unsigned long (*gen_rpm_get_rused)(void *blk); |
83 | | unsigned long (*gen_rpm_get_mused)(void *blk); |
84 | | unsigned long (*gen_rpm_get_free)(void *blk); |
85 | | unsigned long (*gen_rpm_get_frags)(void *blk); |
86 | | #endif |
87 | | |
88 | | #if defined(HP_MALLOC) |
89 | | stat_var *rpm_used; |
90 | | stat_var *rpm_rused; |
91 | | stat_var *rpm_frags; |
92 | | #endif |
93 | | |
94 | | #ifdef STATISTICS |
95 | | stat_export_t rpm_stats[] = { |
96 | | {"rpm_total_size" , STAT_IS_FUNC, (stat_var**)rpm_get_size }, |
97 | | |
98 | | #if defined HP_MALLOC && defined INLINE_ALLOC |
99 | | {"rpm_used_size" , STAT_NO_RESET, &rpm_used }, |
100 | | {"rpm_real_used_size" ,STAT_NO_RESET, &rpm_rused }, |
101 | | {"rpm_fragments" , STAT_NO_RESET, &rpm_frags }, |
102 | | #else |
103 | | /* for HP_MALLOC, these still need to be edited to stats @ startup */ |
104 | | {"rpm_used_size" , STAT_IS_FUNC, (stat_var**)rpm_get_used }, |
105 | | {"rpm_real_used_size" , STAT_IS_FUNC, (stat_var**)rpm_get_rused }, |
106 | | {"rpm_fragments" , STAT_IS_FUNC, (stat_var**)rpm_get_frags }, |
107 | | #endif |
108 | | |
109 | | {"rpm_max_used_size" , STAT_IS_FUNC, (stat_var**)rpm_get_mused }, |
110 | | {"rpm_free_size" , STAT_IS_FUNC, (stat_var**)rpm_get_free }, |
111 | | {0,0,0} |
112 | | }; |
113 | | #endif |
114 | | |
115 | | void rpm_mem_destroy(void); |
116 | | |
117 | | struct rpm_key { |
118 | | str key; |
119 | | void *value; |
120 | | struct rpm_key *next; |
121 | | }; |
122 | | gen_lock_t *rpm_keys_lock; |
123 | | |
124 | | struct _rpm_map_block { |
125 | | unsigned magic; /* magic code used to check if file is valid - |
126 | | should match - RPM_MAGIC_CODE */ |
127 | | unsigned long size; /* size of the block */ |
128 | | enum osips_mm alloc; /* allocator type */ |
129 | | void *mapped_address; /* address where file should be mapped */ |
130 | | void *block_address; /* block where the OpenSIPS memory starts */ |
131 | | struct rpm_key *keys; /* pointer to keys */ |
132 | | } __attribute__((__packed__)) *rpm_map_block = NULL; |
133 | | |
134 | | |
135 | | #if defined F_MALLOC || defined Q_MALLOC |
136 | | gen_lock_t *rpmem_lock; |
137 | | #endif |
138 | | |
139 | | #ifdef HP_MALLOC |
140 | | gen_lock_t *rpmem_locks; |
141 | | #endif |
142 | | |
143 | | static void* rpm_mempool=INVALID_MAP; |
144 | | void *rpm_block=NULL; |
145 | | |
146 | | #if !defined INLINE_ALLOC && defined HP_MALLOC |
147 | | /* startup optimization */ |
148 | | int rpm_use_global_lock; |
149 | | #endif |
150 | | |
151 | | int rpm_mem_init_allocs(void) |
152 | 0 | { |
153 | | #ifdef HP_MALLOC |
154 | | int i; |
155 | | #endif |
156 | |
|
157 | 0 | #ifndef INLINE_ALLOC |
158 | 0 | if (mem_allocator_rpm == MM_NONE) |
159 | 0 | mem_allocator_rpm = mem_allocator; |
160 | |
|
161 | | #ifdef HP_MALLOC |
162 | | if (mem_allocator_rpm == MM_HP_MALLOC |
163 | | || mem_allocator_rpm == MM_HP_MALLOC_DBG) { |
164 | | rpm_stats[3].flags = STAT_NO_RESET; |
165 | | rpm_stats[3].stat_pointer = &rpm_used; |
166 | | rpm_stats[4].flags = STAT_NO_RESET; |
167 | | rpm_stats[4].stat_pointer = &rpm_rused; |
168 | | rpm_stats[5].flags = STAT_NO_RESET; |
169 | | rpm_stats[5].stat_pointer = &rpm_frags; |
170 | | } else { |
171 | | rpm_use_global_lock = 1; |
172 | | } |
173 | | #endif |
174 | |
|
175 | 0 | switch (mem_allocator_rpm) { |
176 | | #ifdef F_MALLOC |
177 | | case MM_F_MALLOC: |
178 | | gen_rpm_malloc = (osips_block_malloc_f)fm_malloc; |
179 | | gen_rpm_malloc_unsafe = (osips_block_malloc_f)fm_malloc; |
180 | | gen_rpm_realloc = (osips_block_realloc_f)fm_realloc; |
181 | | gen_rpm_realloc_unsafe = (osips_block_realloc_f)fm_realloc; |
182 | | gen_rpm_free = (osips_block_free_f)fm_free; |
183 | | gen_rpm_free_unsafe = (osips_block_free_f)fm_free; |
184 | | gen_rpm_info = (osips_mem_info_f)fm_info; |
185 | | gen_rpm_status = (osips_mem_status_f)fm_status; |
186 | | gen_rpm_get_size = (osips_get_mmstat_f)fm_get_size; |
187 | | gen_rpm_get_used = (osips_get_mmstat_f)fm_get_used; |
188 | | gen_rpm_get_rused = (osips_get_mmstat_f)fm_get_real_used; |
189 | | gen_rpm_get_mused = (osips_get_mmstat_f)fm_get_max_real_used; |
190 | | gen_rpm_get_free = (osips_get_mmstat_f)fm_get_free; |
191 | | gen_rpm_get_frags = (osips_get_mmstat_f)fm_get_frags; |
192 | | break; |
193 | | #endif |
194 | 0 | #ifdef Q_MALLOC |
195 | 0 | case MM_Q_MALLOC: |
196 | 0 | gen_rpm_malloc = (osips_block_malloc_f)qm_malloc; |
197 | 0 | gen_rpm_malloc_unsafe = (osips_block_malloc_f)qm_malloc; |
198 | 0 | gen_rpm_realloc = (osips_block_realloc_f)qm_realloc; |
199 | 0 | gen_rpm_realloc_unsafe = (osips_block_realloc_f)qm_realloc; |
200 | 0 | gen_rpm_free = (osips_block_free_f)qm_free; |
201 | 0 | gen_rpm_free_unsafe = (osips_block_free_f)qm_free; |
202 | 0 | gen_rpm_info = (osips_mem_info_f)qm_info; |
203 | 0 | gen_rpm_status = (osips_mem_status_f)qm_status; |
204 | 0 | gen_rpm_get_size = (osips_get_mmstat_f)qm_get_size; |
205 | 0 | gen_rpm_get_used = (osips_get_mmstat_f)qm_get_used; |
206 | 0 | gen_rpm_get_rused = (osips_get_mmstat_f)qm_get_real_used; |
207 | 0 | gen_rpm_get_mused = (osips_get_mmstat_f)qm_get_max_real_used; |
208 | 0 | gen_rpm_get_free = (osips_get_mmstat_f)qm_get_free; |
209 | 0 | gen_rpm_get_frags = (osips_get_mmstat_f)qm_get_frags; |
210 | 0 | break; |
211 | 0 | #endif |
212 | | #ifdef HP_MALLOC |
213 | | case MM_HP_MALLOC: |
214 | | gen_rpm_malloc = (osips_block_malloc_f)hp_rpm_malloc; |
215 | | gen_rpm_malloc_unsafe = (osips_block_malloc_f)hp_rpm_malloc_unsafe; |
216 | | gen_rpm_realloc = (osips_block_realloc_f)hp_rpm_realloc; |
217 | | gen_rpm_realloc_unsafe = (osips_block_realloc_f)hp_rpm_realloc_unsafe; |
218 | | gen_rpm_free = (osips_block_free_f)hp_rpm_free; |
219 | | gen_rpm_free_unsafe = (osips_block_free_f)hp_rpm_free_unsafe; |
220 | | gen_rpm_info = (osips_mem_info_f)hp_info; |
221 | | gen_rpm_status = (osips_mem_status_f)hp_status; |
222 | | gen_rpm_get_size = (osips_get_mmstat_f)hp_rpm_get_size; |
223 | | gen_rpm_get_used = (osips_get_mmstat_f)hp_rpm_get_used; |
224 | | gen_rpm_get_rused = (osips_get_mmstat_f)hp_rpm_get_real_used; |
225 | | gen_rpm_get_mused = (osips_get_mmstat_f)hp_rpm_get_max_real_used; |
226 | | gen_rpm_get_free = (osips_get_mmstat_f)hp_rpm_get_free; |
227 | | gen_rpm_get_frags = (osips_get_mmstat_f)hp_rpm_get_frags; |
228 | | break; |
229 | | #endif |
230 | | #ifdef DBG_MALLOC |
231 | | #ifdef F_MALLOC |
232 | | case MM_F_MALLOC_DBG: |
233 | | gen_rpm_malloc = (osips_block_malloc_f)fm_malloc_dbg; |
234 | | gen_rpm_malloc_unsafe = (osips_block_malloc_f)fm_malloc_dbg; |
235 | | gen_rpm_realloc = (osips_block_realloc_f)fm_realloc_dbg; |
236 | | gen_rpm_realloc_unsafe = (osips_block_realloc_f)fm_realloc_dbg; |
237 | | gen_rpm_free = (osips_block_free_f)fm_free_dbg; |
238 | | gen_rpm_free_unsafe = (osips_block_free_f)fm_free_dbg; |
239 | | gen_rpm_info = (osips_mem_info_f)fm_info; |
240 | | gen_rpm_status = (osips_mem_status_f)fm_status_dbg; |
241 | | gen_rpm_get_size = (osips_get_mmstat_f)fm_get_size; |
242 | | gen_rpm_get_used = (osips_get_mmstat_f)fm_get_used; |
243 | | gen_rpm_get_rused = (osips_get_mmstat_f)fm_get_real_used; |
244 | | gen_rpm_get_mused = (osips_get_mmstat_f)fm_get_max_real_used; |
245 | | gen_rpm_get_free = (osips_get_mmstat_f)fm_get_free; |
246 | | gen_rpm_get_frags = (osips_get_mmstat_f)fm_get_frags; |
247 | | break; |
248 | | #endif |
249 | | #ifdef Q_MALLOC |
250 | | case MM_Q_MALLOC_DBG: |
251 | | gen_rpm_malloc = (osips_block_malloc_f)qm_malloc_dbg; |
252 | | gen_rpm_malloc_unsafe = (osips_block_malloc_f)qm_malloc_dbg; |
253 | | gen_rpm_realloc = (osips_block_realloc_f)qm_realloc_dbg; |
254 | | gen_rpm_realloc_unsafe = (osips_block_realloc_f)qm_realloc_dbg; |
255 | | gen_rpm_free = (osips_block_free_f)qm_free_dbg; |
256 | | gen_rpm_free_unsafe = (osips_block_free_f)qm_free_dbg; |
257 | | gen_rpm_info = (osips_mem_info_f)qm_info; |
258 | | gen_rpm_status = (osips_mem_status_f)qm_status_dbg; |
259 | | gen_rpm_get_size = (osips_get_mmstat_f)qm_get_size; |
260 | | gen_rpm_get_used = (osips_get_mmstat_f)qm_get_used; |
261 | | gen_rpm_get_rused = (osips_get_mmstat_f)qm_get_real_used; |
262 | | gen_rpm_get_mused = (osips_get_mmstat_f)qm_get_max_real_used; |
263 | | gen_rpm_get_free = (osips_get_mmstat_f)qm_get_free; |
264 | | gen_rpm_get_frags = (osips_get_mmstat_f)qm_get_frags; |
265 | | break; |
266 | | #endif |
267 | | #ifdef HP_MALLOC |
268 | | case MM_HP_MALLOC_DBG: |
269 | | gen_rpm_malloc = (osips_block_malloc_f)hp_rpm_malloc_dbg; |
270 | | gen_rpm_malloc_unsafe = (osips_block_malloc_f)hp_rpm_malloc_unsafe_dbg; |
271 | | gen_rpm_realloc = (osips_block_realloc_f)hp_rpm_realloc_dbg; |
272 | | gen_rpm_realloc_unsafe = (osips_block_realloc_f)hp_rpm_realloc_unsafe_dbg; |
273 | | gen_rpm_free = (osips_block_free_f)hp_rpm_free_dbg; |
274 | | gen_rpm_free_unsafe = (osips_block_free_f)hp_rpm_free_unsafe_dbg; |
275 | | gen_rpm_info = (osips_mem_info_f)hp_info; |
276 | | gen_rpm_status = (osips_mem_status_f)hp_status_dbg; |
277 | | gen_rpm_get_size = (osips_get_mmstat_f)hp_rpm_get_size; |
278 | | gen_rpm_get_used = (osips_get_mmstat_f)hp_rpm_get_used; |
279 | | gen_rpm_get_rused = (osips_get_mmstat_f)hp_rpm_get_real_used; |
280 | | gen_rpm_get_mused = (osips_get_mmstat_f)hp_rpm_get_max_real_used; |
281 | | gen_rpm_get_free = (osips_get_mmstat_f)hp_rpm_get_free; |
282 | | gen_rpm_get_frags = (osips_get_mmstat_f)hp_rpm_get_frags; |
283 | | break; |
284 | | #endif |
285 | | #endif |
286 | 0 | default: |
287 | 0 | LM_ERR("current build does not include support for " |
288 | 0 | "selected allocator (%s)\n", mm_str(mem_allocator_rpm)); |
289 | 0 | return -1; |
290 | 0 | } |
291 | | |
292 | 0 | #endif |
293 | | |
294 | | /* store locks in sharem memory, so we don't have to clean them up */ |
295 | | #ifdef HP_MALLOC |
296 | | /* lock_alloc cannot be used yet! */ |
297 | | rpmem_locks = shm_malloc(HP_TOTAL_HASH_SIZE * sizeof *rpmem_locks); |
298 | | if (!rpmem_locks) { |
299 | | LM_CRIT("could not allocate the rp shm lock array\n"); |
300 | | return -1; |
301 | | } |
302 | | |
303 | | for (i = 0; i < HP_TOTAL_HASH_SIZE; i++) |
304 | | if (!lock_init(&rpmem_locks[i])) { |
305 | | LM_CRIT("could not initialize rp lock\n"); |
306 | | return -1; |
307 | | } |
308 | | #endif |
309 | | |
310 | 0 | #if defined F_MALLOC || defined Q_MALLOC |
311 | 0 | rpmem_lock = shm_malloc(sizeof *rpmem_lock); |
312 | 0 | if (!rpmem_lock) { |
313 | 0 | LM_CRIT("could not allocate the rp shm lock\n"); |
314 | 0 | return -1; |
315 | 0 | } |
316 | | |
317 | 0 | if (!lock_init(rpmem_lock)) { |
318 | 0 | LM_CRIT("could not initialize rp lock\n"); |
319 | 0 | return -1; |
320 | 0 | } |
321 | 0 | #endif |
322 | | |
323 | 0 | rpm_keys_lock = shm_malloc(sizeof *rpm_keys_lock); |
324 | 0 | if (!rpm_keys_lock) { |
325 | 0 | LM_CRIT("could not allocate the rpm keys lock\n"); |
326 | 0 | return -1; |
327 | 0 | } |
328 | | |
329 | 0 | if (!lock_init(rpm_keys_lock)) { |
330 | 0 | LM_CRIT("could not initialize rpm keys lock\n"); |
331 | 0 | return -1; |
332 | 0 | } |
333 | | #if defined HP_MALLOC && defined INLINE_ALLOC |
334 | | hp_init_rpm_statistics(rpm_block); |
335 | | #endif |
336 | | |
337 | 0 | return 0; |
338 | 0 | } |
339 | | |
340 | | int rpm_mem_init_mallocs(void* mempool, unsigned long pool_size) |
341 | 0 | { |
342 | 0 | #ifndef INLINE_ALLOC |
343 | 0 | if (mem_allocator_rpm == MM_NONE) |
344 | 0 | mem_allocator_rpm = mem_allocator; |
345 | 0 | #endif |
346 | |
|
347 | | #ifdef INLINE_ALLOC |
348 | | #if defined F_MALLOC |
349 | | rpm_block = fm_malloc_init(mempool, pool_size, "rpm"); |
350 | | #elif defined Q_MALLOC |
351 | | rpm_block = qm_malloc_init(mempool, pool_size, "rpm"); |
352 | | #elif defined HP_MALLOC |
353 | | rpm_block = hp_pkg_malloc_init(mempool, pool_size, "rpm"); |
354 | | #endif |
355 | | #else |
356 | 0 | switch (mem_allocator_rpm) { |
357 | | #ifdef F_MALLOC |
358 | | case MM_F_MALLOC: |
359 | | rpm_block = fm_malloc_init(mempool, pool_size, "rpm"); |
360 | | break; |
361 | | #endif |
362 | 0 | #ifdef Q_MALLOC |
363 | 0 | case MM_Q_MALLOC: |
364 | 0 | rpm_block = qm_malloc_init(mempool, pool_size, "rpm"); |
365 | 0 | break; |
366 | 0 | #endif |
367 | | #ifdef HP_MALLOC |
368 | | case MM_HP_MALLOC: |
369 | | rpm_block = hp_shm_malloc_init(mempool, pool_size, "rpm"); |
370 | | break; |
371 | | #endif |
372 | | #ifdef DBG_MALLOC |
373 | | #ifdef F_MALLOC |
374 | | case MM_F_MALLOC_DBG: |
375 | | rpm_block = fm_malloc_init(mempool, pool_size, "rpm"); |
376 | | break; |
377 | | #endif |
378 | | #ifdef Q_MALLOC |
379 | | case MM_Q_MALLOC_DBG: |
380 | | rpm_block = qm_malloc_init(mempool, pool_size, "rpm"); |
381 | | break; |
382 | | #endif |
383 | | #ifdef HP_MALLOC |
384 | | case MM_HP_MALLOC_DBG: |
385 | | rpm_block = hp_pkg_malloc_init(mempool, pool_size, "rpm"); |
386 | | break; |
387 | | #endif |
388 | | #endif |
389 | 0 | default: |
390 | 0 | LM_ERR("current build does not include support for " |
391 | 0 | "selected allocator (%s)\n", mm_str(mem_allocator_rpm)); |
392 | 0 | return -1; |
393 | 0 | } |
394 | | |
395 | 0 | #endif |
396 | | |
397 | 0 | if (!rpm_block){ |
398 | 0 | LM_CRIT("could not initialize restart persistent malloc\n"); |
399 | 0 | return -1; |
400 | 0 | } |
401 | | |
402 | 0 | LM_DBG("success\n"); |
403 | |
|
404 | 0 | return 0; |
405 | 0 | } |
406 | | |
407 | | /* Loads a restart persistency file in memory |
408 | | * Returns 0 if load is success, -1 on error, or 1 if the cache is invalid */ |
409 | | int load_rpm_file(void) |
410 | 0 | { |
411 | 0 | struct _rpm_map_block tmp; |
412 | 0 | int fd, ret; |
413 | 0 | int bytes_needed, bytes_read; |
414 | 0 | enum osips_mm alloc; |
415 | |
|
416 | 0 | fd = open(rpm_mem_file, O_RDWR); |
417 | 0 | if (fd < 0) { |
418 | 0 | LM_ERR("cannot open restart persistency file: %s\n", rpm_mem_file); |
419 | 0 | return -1; |
420 | 0 | } |
421 | | /* read the block */ |
422 | 0 | bytes_read = 0; |
423 | 0 | bytes_needed = sizeof(tmp); |
424 | 0 | do { |
425 | 0 | ret = read(fd, ((char *)&tmp) + bytes_read, bytes_needed); |
426 | 0 | if (ret < 0) { |
427 | 0 | if (errno == EINTR) |
428 | 0 | continue; |
429 | 0 | LM_ERR("could not read from restart persistency file: %s (%d: %s)\n", |
430 | 0 | rpm_mem_file, errno, strerror(errno)); |
431 | 0 | close(fd); |
432 | 0 | return -1; |
433 | 0 | } |
434 | 0 | bytes_read += ret; |
435 | 0 | bytes_needed -= ret; |
436 | 0 | } while(bytes_needed > 0); |
437 | | |
438 | | /* check if the file is a valid cache file */ |
439 | 0 | if (tmp.magic != RPM_MAGIC_CODE) { |
440 | 0 | LM_WARN("restart persistency file %s does not have the expected magic: %u\n", |
441 | 0 | rpm_mem_file, tmp.magic); |
442 | 0 | goto recreate; |
443 | 0 | } |
444 | 0 | if (tmp.size != rpm_mem_size) { |
445 | 0 | LM_WARN("restart persistency file %s size=%lu != expected size=%lu\n", |
446 | 0 | rpm_mem_file, tmp.size, rpm_mem_size); |
447 | 0 | goto recreate; |
448 | 0 | } |
449 | | |
450 | | #ifdef INLINE_ALLOC |
451 | | alloc = MM_NONE; |
452 | | #else |
453 | 0 | if (mem_allocator_rpm != MM_NONE) |
454 | 0 | alloc = mem_allocator; |
455 | 0 | else |
456 | 0 | alloc = mem_allocator_rpm; |
457 | 0 | #endif |
458 | |
|
459 | 0 | if (tmp.alloc != alloc) { |
460 | 0 | LM_WARN("restart persistency file %s different alloc==%d != expected=%d\n", |
461 | 0 | rpm_mem_file, tmp.alloc, alloc); |
462 | 0 | goto recreate; |
463 | 0 | } |
464 | | |
465 | | /* rewind the head of the fd */ |
466 | 0 | lseek(fd, 0, SEEK_SET); |
467 | | |
468 | | /* it all looks good here - lets map it */ |
469 | 0 | rpm_mempool = shm_getmem(fd, tmp.mapped_address, rpm_mem_size); |
470 | 0 | if (rpm_mempool == INVALID_MAP) { |
471 | 0 | LM_CRIT("could not map persistency file %s at expected location: %p\n", |
472 | 0 | rpm_mem_file, tmp.mapped_address); |
473 | 0 | goto recreate; |
474 | 0 | } |
475 | 0 | close(fd); |
476 | |
|
477 | 0 | rpm_block = tmp.block_address; |
478 | 0 | rpm_map_block = rpm_mempool; |
479 | 0 | if (rpm_mem_init_allocs() < 0) { |
480 | 0 | rpm_mem_destroy(); |
481 | 0 | return 1; |
482 | 0 | } |
483 | | |
484 | 0 | return 0; |
485 | | |
486 | 0 | recreate: |
487 | 0 | close(fd); |
488 | 0 | return 1; |
489 | 0 | } |
490 | | |
491 | | |
492 | | int init_rpm_mallocs(void) |
493 | 0 | { |
494 | 0 | struct stat fst; |
495 | 0 | int n, fd; |
496 | | |
497 | | /* if any of the rpm settings is set, then we should turn rpm_enabled on */ |
498 | | /* if no custom memory was set, then use the shm size */ |
499 | 0 | if (!rpm_mem_size) |
500 | 0 | rpm_mem_size = shm_mem_size; |
501 | |
|
502 | 0 | LM_INFO("using %ld Mb of restart persistent shared memory\n", |
503 | 0 | rpm_mem_size/1024/1024); |
504 | | |
505 | | /* check if the file exists */ |
506 | 0 | n = stat(rpm_mem_file, &fst); |
507 | 0 | if (n == 0) { |
508 | | /* check the size of the file */ |
509 | 0 | if (fst.st_size != rpm_mem_size) { |
510 | 0 | LM_WARN("restart persistency cache (%s) size %ld is different than " |
511 | 0 | "the size we are running with %ld: creating a new cache!\n", |
512 | 0 | rpm_mem_file, (long)fst.st_size, rpm_mem_size); |
513 | 0 | } else if (load_rpm_file() == 0) |
514 | 0 | return 0; /* memblock loaded just fine */ |
515 | 0 | LM_INFO("restart persistent cache is invalid: creating a new one!\n"); |
516 | 0 | } else if (errno != ENOENT) { |
517 | 0 | LM_ERR("could not access file (or path) to the cache: %s (%d: %s)\n", |
518 | 0 | rpm_mem_file, errno, strerror(errno)); |
519 | 0 | return -1; |
520 | 0 | } else |
521 | 0 | LM_DBG("restart persistent cache does not exist: %s. Creating it!\n", |
522 | 0 | rpm_mem_file); |
523 | | |
524 | 0 | fd = open(rpm_mem_file, O_RDWR|O_CREAT|O_TRUNC, 0600); |
525 | 0 | if (fd < 0) { |
526 | 0 | LM_ERR("could not create the restart persistency memory file %s (%d: %s)\n", |
527 | 0 | rpm_mem_file, errno, strerror(errno)); |
528 | 0 | return -1; |
529 | 0 | } |
530 | 0 | lseek(fd, 0, SEEK_SET); |
531 | 0 | if (ftruncate(fd, rpm_mem_size) < 0) { |
532 | 0 | LM_ERR("could not set restart persistency file size %lu\n", rpm_mem_size); |
533 | 0 | goto error; |
534 | 0 | } |
535 | | |
536 | | /* all good - let's map the file */ |
537 | 0 | for (n = 0; n < RPM_MAP_RETRIES; n++) { |
538 | 0 | rpm_mempool = shm_getmem(fd, RPM_MAP_ADDRESS + n * rpm_mem_size, |
539 | 0 | rpm_mem_size); |
540 | 0 | if (rpm_mempool != INVALID_MAP) |
541 | 0 | break; |
542 | 0 | LM_WARN("could not map file at address %p - tried %d times\n", |
543 | 0 | RPM_MAP_ADDRESS + n * rpm_mem_size, n); |
544 | 0 | } |
545 | 0 | if (n == RPM_MAP_RETRIES) { |
546 | | /* last chance: map it anywhere and hope it will be available next |
547 | | * time */ |
548 | 0 | rpm_mempool = shm_getmem(fd, NULL, rpm_mem_size); |
549 | 0 | if (rpm_mempool == INVALID_MAP) { |
550 | 0 | LM_CRIT("could not find available memory zone for restart persistent file!\n"); |
551 | 0 | goto error; |
552 | 0 | } |
553 | 0 | } |
554 | 0 | close(fd); |
555 | | |
556 | | /* finally, we've got a mempool - populate the block */ |
557 | 0 | rpm_map_block = rpm_mempool; |
558 | 0 | memset(rpm_mempool, 0, sizeof(*rpm_map_block)); |
559 | |
|
560 | 0 | rpm_map_block->magic = RPM_MAGIC_CODE; |
561 | 0 | rpm_map_block->size = rpm_mem_size; |
562 | 0 | rpm_map_block->mapped_address = rpm_mempool; |
563 | 0 | rpm_map_block->block_address = (char *)rpm_map_block + sizeof(*rpm_map_block); |
564 | |
|
565 | 0 | if (rpm_mem_init_mallocs(rpm_map_block->block_address, |
566 | 0 | rpm_mem_size - sizeof(*rpm_map_block)) < 0) { |
567 | 0 | rpm_mem_destroy(); |
568 | 0 | return -1; |
569 | 0 | } |
570 | | /* update in case of realigned */ |
571 | 0 | rpm_map_block->block_address = rpm_block; |
572 | |
|
573 | 0 | if (rpm_mem_init_allocs() < 0) { |
574 | 0 | rpm_mem_destroy(); |
575 | 0 | return -1; |
576 | 0 | } |
577 | | |
578 | 0 | return 0; |
579 | | |
580 | 0 | error: |
581 | 0 | close(fd); |
582 | 0 | return -1; |
583 | 0 | } |
584 | | |
585 | | void rpm_relmem(void *mempool, unsigned long size) |
586 | 0 | { |
587 | 0 | if (mempool && (mempool!=INVALID_MAP)) |
588 | 0 | munmap(mempool, size); |
589 | 0 | } |
590 | | |
591 | | void rpm_mem_destroy(void) |
592 | 0 | { |
593 | | #ifdef HP_MALLOC |
594 | | int j; |
595 | | #endif |
596 | 0 | if (0 |
597 | 0 | #if defined F_MALLOC || defined Q_MALLOC |
598 | 0 | || rpmem_lock |
599 | 0 | #endif |
600 | | #ifdef HP_MALLOC |
601 | | || rpmem_locks |
602 | | #endif |
603 | 0 | ) { |
604 | 0 | #if defined F_MALLOC || defined Q_MALLOC |
605 | 0 | if (rpmem_lock) { |
606 | 0 | LM_DBG("destroying the shared memory lock\n"); |
607 | 0 | lock_destroy(rpmem_lock); /* we don't need to dealloc it*/ |
608 | 0 | rpmem_lock = NULL; |
609 | 0 | } |
610 | 0 | #endif |
611 | |
|
612 | | #if defined HP_MALLOC |
613 | | if (rpmem_locks) { |
614 | | for (j = 0; j < HP_TOTAL_HASH_SIZE; j++) |
615 | | lock_destroy(&rpmem_locks[j]); |
616 | | rpmem_locks = NULL; |
617 | | } |
618 | | #endif |
619 | 0 | } |
620 | 0 | rpm_relmem(rpm_mempool, rpm_mem_size); |
621 | 0 | rpm_mempool=INVALID_MAP; |
622 | 0 | rpm_block = NULL; |
623 | 0 | } |
624 | | |
625 | | int rpm_init_mem(void) |
626 | 0 | { |
627 | 0 | if (rpm_mempool==INVALID_MAP) { |
628 | | /* memory pool not yet initialized */ |
629 | 0 | if (init_rpm_mallocs() < 0) { |
630 | 0 | LM_ERR("could not initialize restart persistent memory!\n"); |
631 | 0 | rpm_mempool = 0; |
632 | 0 | return -1; |
633 | 0 | } |
634 | 0 | } |
635 | 0 | if (rpm_mempool == 0) { |
636 | | /* memory pool could not be init */ |
637 | 0 | LM_DBG("restart persistency could not be initialized!\n"); |
638 | 0 | return -1; |
639 | 0 | } |
640 | 0 | return 0; |
641 | 0 | } |
642 | | |
643 | | void *rpm_key_get(char *key) |
644 | 0 | { |
645 | 0 | struct rpm_key *k; |
646 | 0 | int len; |
647 | 0 | void *ret = NULL; |
648 | |
|
649 | 0 | if (!rpm_map_block || !rpm_map_block->keys) |
650 | 0 | return NULL; |
651 | | |
652 | 0 | len = strlen(key); |
653 | 0 | lock_get(rpm_keys_lock); |
654 | 0 | for (k = rpm_map_block->keys; k; k = k->next) |
655 | 0 | if (len == k->key.len && memcmp(k->key.s, key, len) == 0) { |
656 | 0 | ret = k->value; |
657 | 0 | goto end; |
658 | 0 | } |
659 | 0 | end: |
660 | 0 | lock_release(rpm_keys_lock); |
661 | 0 | return ret; |
662 | 0 | } |
663 | | |
664 | | int rpm_key_set(char *key, void *val) |
665 | 0 | { |
666 | 0 | struct rpm_key *k; |
667 | 0 | int len; |
668 | |
|
669 | 0 | if (!rpm_map_block) |
670 | 0 | return -2; |
671 | | |
672 | 0 | len = strlen(key); |
673 | 0 | lock_get(rpm_keys_lock); |
674 | 0 | for (k = rpm_map_block->keys; k; k = k->next) |
675 | 0 | if (len == k->key.len && memcmp(k->key.s, key, len) == 0) |
676 | 0 | break; |
677 | |
|
678 | 0 | if (k != NULL) { |
679 | 0 | k->value = val; |
680 | 0 | lock_release(rpm_keys_lock); |
681 | 0 | return 0; |
682 | 0 | } |
683 | | /* key does not exist - add it now */ |
684 | 0 | k = rpm_malloc(sizeof(*k) + len); |
685 | 0 | if (!k) { |
686 | 0 | LM_ERR("could not add mem for rp key!\n"); |
687 | 0 | lock_release(rpm_keys_lock); |
688 | 0 | return -1; |
689 | 0 | } |
690 | 0 | k->key.s = (char *)(k+1); |
691 | 0 | memcpy(k->key.s, key, len); |
692 | 0 | k->key.len = len; |
693 | 0 | k->value = val; |
694 | 0 | k->next = rpm_map_block->keys; |
695 | 0 | rpm_map_block->keys = k; |
696 | 0 | lock_release(rpm_keys_lock); |
697 | 0 | return 0; |
698 | 0 | } |
699 | | |
700 | | int rpm_key_del(char *key) |
701 | 0 | { |
702 | 0 | struct rpm_key *k, *p; |
703 | 0 | int len; |
704 | |
|
705 | 0 | if (!rpm_map_block) |
706 | 0 | return -2; |
707 | 0 | if (!rpm_map_block->keys) |
708 | 0 | return -1; |
709 | | |
710 | 0 | len = strlen(key); |
711 | 0 | lock_get(rpm_keys_lock); |
712 | 0 | for (p = NULL, k = rpm_map_block->keys; k; p = k, k = k->next) |
713 | 0 | if (len == k->key.len && memcmp(k->key.s, key, len) == 0) |
714 | 0 | break; |
715 | 0 | if (!k) { |
716 | 0 | LM_DBG("could not find key %s\n", key); |
717 | 0 | lock_release(rpm_keys_lock); |
718 | 0 | return -1; |
719 | 0 | } |
720 | 0 | if (!p) { |
721 | | /* first element */ |
722 | 0 | rpm_map_block->keys = k->next; |
723 | 0 | } else { |
724 | 0 | p->next = k->next; |
725 | 0 | } |
726 | 0 | lock_release(rpm_keys_lock); |
727 | 0 | rpm_free(k); |
728 | 0 | return 0; |
729 | 0 | } |