]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/mem_pool.c
Fix segfault with print_memory_pool_stats()
[bacula/bacula] / bacula / src / lib / mem_pool.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU Affero 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
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *  Bacula memory pool routines.
30  *
31  *  The idea behind these routines is that there will be
32  *  pools of memory that are pre-allocated for quick
33  *  access. The pools will have a fixed memory size on allocation
34  *  but if need be, the size can be increased. This is
35  *  particularly useful for filename
36  *  buffers where 256 bytes should be sufficient in 99.99%
37  *  of the cases, but when it isn't we want to be able to
38  *  increase the size.
39  *
40  *  A major advantage of the pool memory aside from the speed
41  *  is that the buffer carrys around its size, so to ensure that
42  *  there is enough memory, simply call the check_pool_memory_size()
43  *  with the desired size and it will adjust only if necessary.
44  *
45  *           Kern E. Sibbald
46  *
47  */
48
49 #include "bacula.h"
50 #ifdef HAVE_MALLOC_TRIM
51 #include <malloc.h>
52 #endif
53
54 struct s_pool_ctl {
55    int32_t size;                      /* default size */
56    int32_t max_allocated;             /* max allocated */
57    int32_t max_used;                  /* max buffers used */
58    int32_t in_use;                    /* number in use */
59    struct abufhead *free_buf;         /* pointer to free buffers */
60 };
61
62 /* Bacula Name length plus extra */
63 #define NLEN (MAX_NAME_LENGTH+2)
64
65 /* #define STRESS_TEST_POOL */
66 #ifndef STRESS_TEST_POOL
67 /*
68  * Define default Pool buffer sizes
69  */
70 static struct s_pool_ctl pool_ctl[] = {
71    {  256,  256, 0, 0, NULL },        /* PM_NOPOOL no pooling */
72    {  NLEN, NLEN,0, 0, NULL },        /* PM_NAME Bacula name */
73    {  256,  256, 0, 0, NULL },        /* PM_FNAME filename buffers */
74    {  512,  512, 0, 0, NULL },        /* PM_MESSAGE message buffer */
75    { 1024, 1024, 0, 0, NULL },        /* PM_EMSG error message buffer */
76   {  4096, 4096, 0, 0, NULL }         /* PM_BSOCK message buffer */
77 };
78 #else
79
80 /* This is used ONLY when stress testing the code */
81 static struct s_pool_ctl pool_ctl[] = {
82    {   20,   20, 0, 0, NULL },        /* PM_NOPOOL no pooling */
83    {  NLEN, NLEN,0, 0, NULL },        /* PM_NAME Bacula name */
84    {   20,   20, 0, 0, NULL },        /* PM_FNAME filename buffers */
85    {   20,   20, 0, 0, NULL },        /* PM_MESSAGE message buffer */
86    {   20,   20, 0, 0, NULL },        /* PM_EMSG error message buffer */
87    {   20,   20, 0, 0, NULL }         /* PM_BSOCK message buffer */
88 };
89 #endif
90
91
92 /*  Memory allocation control structures and storage.  */
93 struct abufhead {
94    int32_t ablen;                     /* Buffer length in bytes */
95    int32_t pool;                      /* pool */
96    struct abufhead *next;             /* pointer to next free buffer */
97    int32_t bnet_size;                 /* dummy for bnet_send() */
98 };
99
100 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
101
102 #ifdef SMARTALLOC
103
104 #define HEAD_SIZE BALIGN(sizeof(struct abufhead))
105
106 POOLMEM *sm_get_pool_memory(const char *fname, int lineno, int pool)
107 {
108    struct abufhead *buf;
109
110    if (pool > PM_MAX) {
111       Emsg2(M_ABORT, 0, _("MemPool index %d larger than max %d\n"), pool, PM_MAX);
112    }
113    P(mutex);
114    if (pool_ctl[pool].free_buf) {
115       buf = pool_ctl[pool].free_buf;
116       pool_ctl[pool].free_buf = buf->next;
117       pool_ctl[pool].in_use++;
118       if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
119          pool_ctl[pool].max_used = pool_ctl[pool].in_use;
120       }
121       V(mutex);
122       Dmsg3(1800, "sm_get_pool_memory reuse %p to %s:%d\n", buf, fname, lineno);
123       sm_new_owner(fname, lineno, (char *)buf);
124       return (POOLMEM *)((char *)buf+HEAD_SIZE);
125    }
126
127    if ((buf = (struct abufhead *)sm_malloc(fname, lineno, pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
128       V(mutex);
129       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), pool_ctl[pool].size);
130    }
131    buf->ablen = pool_ctl[pool].size;
132    buf->pool = pool;
133    pool_ctl[pool].in_use++;
134    if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
135       pool_ctl[pool].max_used = pool_ctl[pool].in_use;
136    }
137    V(mutex);
138    Dmsg3(1800, "sm_get_pool_memory give %p to %s:%d\n", buf, fname, lineno);
139    return (POOLMEM *)((char *)buf+HEAD_SIZE);
140 }
141
142 /* Get nonpool memory of size requested */
143 POOLMEM *sm_get_memory(const char *fname, int lineno, int32_t size)
144 {
145    struct abufhead *buf;
146    int pool = 0;
147
148    if ((buf = (struct abufhead *)sm_malloc(fname, lineno, size+HEAD_SIZE)) == NULL) {
149       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
150    }
151    buf->ablen = size;
152    buf->pool = pool;
153    buf->next = NULL;
154    pool_ctl[pool].in_use++;
155    if (pool_ctl[pool].in_use > pool_ctl[pool].max_used)
156       pool_ctl[pool].max_used = pool_ctl[pool].in_use;
157    return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
158 }
159
160 /* Return the size of a memory buffer */
161 int32_t sm_sizeof_pool_memory(const char *fname, int lineno, POOLMEM *obuf)
162 {
163    char *cp = (char *)obuf;
164
165    if (obuf == NULL) {
166       Emsg0(M_ABORT, 0, _("obuf is NULL\n"));
167    }
168    cp -= HEAD_SIZE;
169    return ((struct abufhead *)cp)->ablen;
170 }
171
172 /* Realloc pool memory buffer */
173 POOLMEM *sm_realloc_pool_memory(const char *fname, int lineno, POOLMEM *obuf, int32_t size)
174 {
175    char *cp = (char *)obuf;
176    void *buf;
177    int pool;
178
179    ASSERT(obuf);
180    P(mutex);
181    cp -= HEAD_SIZE;
182    buf = sm_realloc(fname, lineno, cp, size+HEAD_SIZE);
183    if (buf == NULL) {
184       V(mutex);
185       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
186    }
187    ((struct abufhead *)buf)->ablen = size;
188    pool = ((struct abufhead *)buf)->pool;
189    if (size > pool_ctl[pool].max_allocated) {
190       pool_ctl[pool].max_allocated = size;
191    }
192    V(mutex);
193    return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
194 }
195
196 POOLMEM *sm_check_pool_memory_size(const char *fname, int lineno, POOLMEM *obuf, int32_t size)
197 {
198    ASSERT(obuf);
199    if (size <= sizeof_pool_memory(obuf)) {
200       return obuf;
201    }
202    return realloc_pool_memory(obuf, size);
203 }
204
205 /* Free a memory buffer */
206 void sm_free_pool_memory(const char *fname, int lineno, POOLMEM *obuf)
207 {
208    struct abufhead *buf;
209    int pool;
210
211    ASSERT(obuf);
212    P(mutex);
213    buf = (struct abufhead *)((char *)obuf - HEAD_SIZE);
214    pool = buf->pool;
215    pool_ctl[pool].in_use--;
216    if (pool == 0) {
217       free((char *)buf);              /* free nonpooled memory */
218    } else {                           /* otherwise link it to the free pool chain */
219 #ifdef DEBUG
220       struct abufhead *next;
221       /* Don't let him free the same buffer twice */
222       for (next=pool_ctl[pool].free_buf; next; next=next->next) {
223          if (next == buf) {
224             Dmsg4(1800, "free_pool_memory %p pool=%d from %s:%d\n", buf, pool, fname, lineno);
225             Dmsg4(1800, "bad free_pool_memory %p pool=%d from %s:%d\n", buf, pool, fname, lineno);
226             V(mutex);                 /* unblock the pool */
227             ASSERT(next != buf);      /* attempt to free twice */
228          }
229       }
230 #endif
231       buf->next = pool_ctl[pool].free_buf;
232       pool_ctl[pool].free_buf = buf;
233    }
234    Dmsg4(1800, "free_pool_memory %p pool=%d from %s:%d\n", buf, pool, fname, lineno);
235    V(mutex);
236 }
237
238 #else
239
240 /* =========  NO SMARTALLOC  =========================================  */
241
242 POOLMEM *get_pool_memory(int pool)
243 {
244    struct abufhead *buf;
245
246    P(mutex);
247    if (pool_ctl[pool].free_buf) {
248       buf = pool_ctl[pool].free_buf;
249       pool_ctl[pool].free_buf = buf->next;
250       V(mutex);
251       return (POOLMEM *)((char *)buf+HEAD_SIZE);
252    }
253
254    if ((buf=malloc(pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
255       V(mutex);
256       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), pool_ctl[pool].size);
257    }
258    buf->ablen = pool_ctl[pool].size;
259    buf->pool = pool;
260    buf->next = NULL;
261    pool_ctl[pool].in_use++;
262    if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
263       pool_ctl[pool].max_used = pool_ctl[pool].in_use;
264    }
265    V(mutex);
266    return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
267 }
268
269 /* Get nonpool memory of size requested */
270 POOLMEM *get_memory(int32_t size)
271 {
272    struct abufhead *buf;
273    int pool = 0;
274
275    if ((buf=malloc(size+HEAD_SIZE)) == NULL) {
276       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
277    }
278    buf->ablen = size;
279    buf->pool = pool;
280    buf->next = NULL;
281    pool_ctl[pool].in_use++;
282    if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
283       pool_ctl[pool].max_used = pool_ctl[pool].in_use;
284    }
285    return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
286 }
287
288 /* Return the size of a memory buffer */
289 int32_t sizeof_pool_memory(POOLMEM *obuf)
290 {
291    char *cp = (char *)obuf;
292
293    ASSERT(obuf);
294    cp -= HEAD_SIZE;
295    return ((struct abufhead *)cp)->ablen;
296 }
297
298 /* Realloc pool memory buffer */
299 POOLMEM *realloc_pool_memory(POOLMEM *obuf, int32_t size)
300 {
301    char *cp = (char *)obuf;
302    void *buf;
303    int pool;
304
305    ASSERT(obuf);
306    P(mutex);
307    cp -= HEAD_SIZE;
308    buf = realloc(cp, size+HEAD_SIZE);
309    if (buf == NULL) {
310       V(mutex);
311       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
312    }
313    ((struct abufhead *)buf)->ablen = size;
314    pool = ((struct abufhead *)buf)->pool;
315    if (size > pool_ctl[pool].max_allocated) {
316       pool_ctl[pool].max_allocated = size;
317    }
318    V(mutex);
319    return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
320 }
321
322 POOLMEM *check_pool_memory_size(POOLMEM *obuf, int32_t size)
323 {
324    ASSERT(obuf);
325    if (size <= sizeof_pool_memory(obuf)) {
326       return obuf;
327    }
328    return realloc_pool_memory(obuf, size);
329 }
330
331 /* Free a memory buffer */
332 void free_pool_memory(POOLMEM *obuf)
333 {
334    struct abufhead *buf;
335    int pool;
336
337    ASSERT(obuf);
338    P(mutex);
339    buf = (struct abufhead *)((char *)obuf - HEAD_SIZE);
340    pool = buf->pool;
341    pool_ctl[pool].in_use--;
342    if (pool == 0) {
343       free((char *)buf);              /* free nonpooled memory */
344    } else {                           /* otherwise link it to the free pool chain */
345 #ifdef DEBUG
346       struct abufhead *next;
347       /* Don't let him free the same buffer twice */
348       for (next=pool_ctl[pool].free_buf; next; next=next->next) {
349          if (next == buf) {
350             V(mutex);
351             ASSERT(next != buf);  /* attempt to free twice */
352          }
353       }
354 #endif
355       buf->next = pool_ctl[pool].free_buf;
356       pool_ctl[pool].free_buf = buf;
357    }
358    Dmsg2(1800, "free_pool_memory %p pool=%d\n", buf, pool);
359    V(mutex);
360 }
361 #endif /* SMARTALLOC */
362
363 /*
364  * Clean up memory pool periodically
365  *
366  */
367 static time_t last_garbage_collection = 0;
368 const int garbage_interval = 24 * 60 * 60;  /* garbage collect every 24 hours */
369
370 void garbage_collect_memory_pool()
371 {
372    time_t now;
373
374    Dmsg0(200, "garbage collect memory pool\n");
375    P(mutex);
376    if (last_garbage_collection == 0) {
377       last_garbage_collection = time(NULL);
378       V(mutex);
379       return;
380    }
381    now = time(NULL);
382    if (now >= last_garbage_collection + garbage_interval) {
383       last_garbage_collection = now;
384       V(mutex);
385       garbage_collect_memory();
386    } else {
387       V(mutex);
388    }
389 }
390
391 /* Release all freed pooled memory */
392 void close_memory_pool()
393 {
394    struct abufhead *buf, *next;
395    int count = 0;
396    uint64_t bytes = 0;
397    char ed1[50];
398
399    sm_check(__FILE__, __LINE__, false);
400    P(mutex);
401    for (int i=1; i<=PM_MAX; i++) {
402       buf = pool_ctl[i].free_buf;
403       while (buf) {
404          next = buf->next;
405          count++;
406          bytes += sizeof_pool_memory((char *)buf);
407          free((char *)buf);
408          buf = next;
409       }
410       pool_ctl[i].free_buf = NULL;
411    }
412    Dmsg2(001, "Freed mem_pool count=%d size=%s\n", count, edit_uint64_with_commas(bytes, ed1));
413    if (debug_level >= 1) {
414       print_memory_pool_stats();
415    }
416    V(mutex);
417
418 }
419
420 /*
421  * Garbage collect and trim memory if possible
422  *  This should be called after all big memory usages
423  *  if possible.
424  */
425 void garbage_collect_memory()
426 {
427    close_memory_pool();         /* release free chain */
428 #ifdef HAVE_MALLOC_TRIM
429    P(mutex);
430    malloc_trim(8192);
431    V(mutex);
432 #endif
433 }
434
435 #ifdef DEBUG
436 static const char *pool_name(int pool)
437 {
438    static const char *name[] = {"NoPool", "NAME  ", "FNAME ", "MSG   ", "EMSG  ", "BSOCK "};
439    static char buf[30];
440
441    if (pool >= 0 && pool <= PM_MAX) {
442       return name[pool];
443    }
444    sprintf(buf, "%-6d", pool);
445    return buf;
446 }
447
448 /* Print staticstics on memory pool usage
449  */
450 void print_memory_pool_stats()
451 {
452    Pmsg0(-1, "Pool   Maxsize  Maxused  Inuse\n");
453    for (int i=0; i<=PM_MAX; i++)
454       Pmsg4(-1, "%5s  %7d  %7d  %5d\n", pool_name(i), pool_ctl[i].max_allocated,
455          pool_ctl[i].max_used, pool_ctl[i].in_use);
456
457    Pmsg0(-1, "\n");
458 }
459
460 #else
461 void print_memory_pool_stats() {}
462 #endif /* DEBUG */
463
464 /*
465  * Concatenate a string (str) onto a pool memory buffer pm
466  *   Returns: length of concatenated string
467  */
468 int pm_strcat(POOLMEM **pm, const char *str)
469 {
470    int pmlen = strlen(*pm);
471    int len;
472
473    if (!str) str = "";
474
475    len = strlen(str) + 1;
476    *pm = check_pool_memory_size(*pm, pmlen + len);
477    memcpy(*pm+pmlen, str, len);
478    return pmlen + len - 1;
479 }
480
481 int pm_strcat(POOLMEM *&pm, const char *str)
482 {
483    int pmlen = strlen(pm);
484    int len;
485
486    if (!str) str = "";
487
488    len = strlen(str) + 1;
489    pm = check_pool_memory_size(pm, pmlen + len);
490    memcpy(pm+pmlen, str, len);
491    return pmlen + len - 1;
492 }
493
494 int pm_strcat(POOLMEM *&pm, POOL_MEM &str)
495 {
496    int pmlen = strlen(pm);
497    int len = strlen(str.c_str()) + 1;
498
499    pm = check_pool_memory_size(pm, pmlen + len);
500    memcpy(pm+pmlen, str.c_str(), len);
501    return pmlen + len - 1;
502 }
503
504 int pm_strcat(POOL_MEM &pm, const char *str)
505 {
506    int pmlen = strlen(pm.c_str());
507    int len;
508
509    if (!str) str = "";
510
511    len = strlen(str) + 1;
512    pm.check_size(pmlen + len);
513    memcpy(pm.c_str()+pmlen, str, len);
514    return pmlen + len - 1;
515 }
516
517 /*
518  * Copy a string (str) into a pool memory buffer pm
519  *   Returns: length of string copied
520  */
521 int pm_strcpy(POOLMEM **pm, const char *str)
522 {
523    int len;
524
525    if (!str) str = "";
526
527    len = strlen(str) + 1;
528    *pm = check_pool_memory_size(*pm, len);
529    memcpy(*pm, str, len);
530    return len - 1;
531 }
532
533 int pm_strcpy(POOLMEM *&pm, const char *str)
534 {
535    int len;
536
537    if (!str) str = "";
538
539    len = strlen(str) + 1;
540    pm = check_pool_memory_size(pm, len);
541    memcpy(pm, str, len);
542    return len - 1;
543 }
544
545 int pm_strcpy(POOLMEM *&pm, POOL_MEM &str)
546 {
547    int len = strlen(str.c_str()) + 1;
548
549    pm = check_pool_memory_size(pm, len);
550    memcpy(pm, str.c_str(), len);
551    return len - 1;
552 }
553
554 int pm_strcpy(POOL_MEM &pm, const char *str)
555 {
556    int len;
557
558    if (!str) str = "";
559
560    len = strlen(str) + 1;
561    pm.check_size(len);
562    memcpy(pm.c_str(), str, len);
563    return len - 1;
564 }
565
566 /*
567  * Copy data into a pool memory buffer pm
568  *   Returns: length of data copied
569  */
570 int pm_memcpy(POOLMEM **pm, const char *data, int32_t n)
571 {
572    *pm = check_pool_memory_size(*pm, n);
573    memcpy(*pm, data, n);
574    return n;
575 }
576
577 int pm_memcpy(POOLMEM *&pm, const char *data, int32_t n)
578 {
579    pm = check_pool_memory_size(pm, n);
580    memcpy(pm, data, n);
581    return n;
582 }
583
584 int pm_memcpy(POOLMEM *&pm, POOL_MEM &data, int32_t n)
585 {
586    pm = check_pool_memory_size(pm, n);
587    memcpy(pm, data.c_str(), n);
588    return n;
589 }
590
591 int pm_memcpy(POOL_MEM &pm, const char *data, int32_t n)
592 {
593    pm.check_size(n);
594    memcpy(pm.c_str(), data, n);
595    return n;
596 }
597
598 /* ==============  CLASS POOL_MEM   ============== */
599
600 /* Return the size of a memory buffer */
601 int32_t POOL_MEM::max_size()
602 {
603    int32_t size;
604    char *cp = mem;
605    cp -= HEAD_SIZE;
606    size = ((struct abufhead *)cp)->ablen;
607    Dmsg1(900, "max_size=%d\n", size);
608    return size;
609 }
610
611 void POOL_MEM::realloc_pm(int32_t size)
612 {
613    char *cp = mem;
614    char *buf;
615    int pool;
616
617    P(mutex);
618    cp -= HEAD_SIZE;
619    buf = (char *)realloc(cp, size+HEAD_SIZE);
620    if (buf == NULL) {
621       V(mutex);
622       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
623    }
624    Dmsg2(900, "Old buf=%p new buf=%p\n", cp, buf);
625    ((struct abufhead *)buf)->ablen = size;
626    pool = ((struct abufhead *)buf)->pool;
627    if (size > pool_ctl[pool].max_allocated) {
628       pool_ctl[pool].max_allocated = size;
629    }
630    mem = buf+HEAD_SIZE;
631    V(mutex);
632    Dmsg3(900, "Old buf=%p new buf=%p mem=%p\n", cp, buf, mem);
633 }
634
635 int POOL_MEM::strcat(const char *str)
636 {
637    int pmlen = strlen(mem);
638    int len;
639
640    if (!str) str = "";
641
642    len = strlen(str) + 1;
643    check_size(pmlen + len);
644    memcpy(mem+pmlen, str, len);
645    return pmlen + len - 1;
646 }
647
648 int POOL_MEM::strcpy(const char *str)
649 {
650    int len;
651
652    if (!str) str = "";
653
654    len = strlen(str) + 1;
655    check_size(len);
656    memcpy(mem, str, len);
657    return len - 1;
658 }