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