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