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