]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/mem_pool.c
Detect mount/junction points and ignore junctions in Windows
[bacula/bacula] / bacula / src / lib / mem_pool.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2010 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
51 struct s_pool_ctl {
52    int32_t size;                      /* default size */
53    int32_t max_allocated;             /* max allocated */
54    int32_t max_used;                  /* max buffers used */
55    int32_t in_use;                    /* number in use */
56    struct abufhead *free_buf;         /* pointer to free buffers */
57 };
58
59 /* Bacula Name length plus extra */
60 #define NLEN (MAX_NAME_LENGTH+2)
61
62 /* #define STRESS_TEST_POOL */
63 #ifndef STRESS_TEST_POOL
64 /*
65  * Define default Pool buffer sizes
66  */
67 static struct s_pool_ctl pool_ctl[] = {
68    {  256,  256, 0, 0, NULL },        /* PM_NOPOOL no pooling */
69    {  NLEN, NLEN,0, 0, NULL },        /* PM_NAME Bacula name */
70    {  256,  256, 0, 0, NULL },        /* PM_FNAME filename buffers */
71    {  512,  512, 0, 0, NULL },        /* PM_MESSAGE message buffer */
72    { 1024, 1024, 0, 0, NULL }         /* PM_EMSG error message buffer */
73 };
74 #else
75
76 /* This is used ONLY when stress testing the code */
77 static struct s_pool_ctl pool_ctl[] = {
78    {   20,   20, 0, 0, NULL },        /* PM_NOPOOL no pooling */
79    {  NLEN, NLEN,0, 0, NULL },        /* PM_NAME Bacula name */
80    {   20,   20, 0, 0, NULL },        /* PM_FNAME filename buffers */
81    {   20,   20, 0, 0, NULL },        /* PM_MESSAGE message buffer */
82    {   20,   20, 0, 0, NULL }         /* PM_EMSG error message buffer */
83 };
84 #endif
85
86
87 /*  Memory allocation control structures and storage.  */
88 struct abufhead {
89    int32_t ablen;                     /* Buffer length in bytes */
90    int32_t pool;                      /* pool */
91    struct abufhead *next;             /* pointer to next free buffer */
92    int32_t bnet_size;                 /* dummy for bnet_send() */
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(1800, "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(1800, "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 #ifdef DEBUG
215       struct abufhead *next;
216       /* Don't let him free the same buffer twice */
217       for (next=pool_ctl[pool].free_buf; next; next=next->next) {
218          if (next == buf) {
219             Dmsg4(1800, "free_pool_memory %p pool=%d from %s:%d\n", buf, pool, fname, lineno);
220             Dmsg4(1800, "bad free_pool_memory %p pool=%d from %s:%d\n", buf, pool, fname, lineno);
221             V(mutex);                 /* unblock the pool */
222             ASSERT(next != buf);      /* attempt to free twice */
223          }
224       }
225 #endif
226       buf->next = pool_ctl[pool].free_buf;
227       pool_ctl[pool].free_buf = buf;
228    }
229    Dmsg4(1800, "free_pool_memory %p pool=%d from %s:%d\n", buf, pool, fname, lineno);
230    V(mutex);
231 }
232
233 #else
234
235 /* =========  NO SMARTALLOC  =========================================  */
236
237 POOLMEM *get_pool_memory(int pool)
238 {
239    struct abufhead *buf;
240
241    P(mutex);
242    if (pool_ctl[pool].free_buf) {
243       buf = pool_ctl[pool].free_buf;
244       pool_ctl[pool].free_buf = buf->next;
245       V(mutex);
246       return (POOLMEM *)((char *)buf+HEAD_SIZE);
247    }
248
249    if ((buf=malloc(pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
250       V(mutex);
251       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), pool_ctl[pool].size);
252    }
253    buf->ablen = pool_ctl[pool].size;
254    buf->pool = pool;
255    buf->next = NULL;
256    pool_ctl[pool].in_use++;
257    if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
258       pool_ctl[pool].max_used = pool_ctl[pool].in_use;
259    }
260    V(mutex);
261    return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
262 }
263
264 /* Get nonpool memory of size requested */
265 POOLMEM *get_memory(int32_t size)
266 {
267    struct abufhead *buf;
268    int pool = 0;
269
270    if ((buf=malloc(size+HEAD_SIZE)) == NULL) {
271       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
272    }
273    buf->ablen = size;
274    buf->pool = pool;
275    buf->next = NULL;
276    pool_ctl[pool].in_use++;
277    if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
278       pool_ctl[pool].max_used = pool_ctl[pool].in_use;
279    }
280    return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
281 }
282
283 /* Return the size of a memory buffer */
284 int32_t sizeof_pool_memory(POOLMEM *obuf)
285 {
286    char *cp = (char *)obuf;
287
288    ASSERT(obuf);
289    cp -= HEAD_SIZE;
290    return ((struct abufhead *)cp)->ablen;
291 }
292
293 /* Realloc pool memory buffer */
294 POOLMEM *realloc_pool_memory(POOLMEM *obuf, int32_t size)
295 {
296    char *cp = (char *)obuf;
297    void *buf;
298    int pool;
299
300    ASSERT(obuf);
301    P(mutex);
302    cp -= HEAD_SIZE;
303    buf = realloc(cp, size+HEAD_SIZE);
304    if (buf == NULL) {
305       V(mutex);
306       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
307    }
308    ((struct abufhead *)buf)->ablen = size;
309    pool = ((struct abufhead *)buf)->pool;
310    if (size > pool_ctl[pool].max_allocated) {
311       pool_ctl[pool].max_allocated = size;
312    }
313    V(mutex);
314    return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
315 }
316
317 POOLMEM *check_pool_memory_size(POOLMEM *obuf, int32_t size)
318 {
319    ASSERT(obuf);
320    if (size <= sizeof_pool_memory(obuf)) {
321       return obuf;
322    }
323    return realloc_pool_memory(obuf, size);
324 }
325
326 /* Free a memory buffer */
327 void free_pool_memory(POOLMEM *obuf)
328 {
329    struct abufhead *buf;
330    int pool;
331
332    ASSERT(obuf);
333    P(mutex);
334    buf = (struct abufhead *)((char *)obuf - HEAD_SIZE);
335    pool = buf->pool;
336    pool_ctl[pool].in_use--;
337    if (pool == 0) {
338       free((char *)buf);              /* free nonpooled memory */
339    } else {                           /* otherwise link it to the free pool chain */
340 #ifdef DEBUG
341       struct abufhead *next;
342       /* Don't let him free the same buffer twice */
343       for (next=pool_ctl[pool].free_buf; next; next=next->next) {
344          if (next == buf) {
345             V(mutex);
346             ASSERT(next != buf);  /* attempt to free twice */
347          }
348       }
349 #endif
350       buf->next = pool_ctl[pool].free_buf;
351       pool_ctl[pool].free_buf = buf;
352    }
353    Dmsg2(1800, "free_pool_memory %p pool=%d\n", buf, pool);
354    V(mutex);
355 }
356 #endif /* SMARTALLOC */
357
358 /*
359  * Clean up memory pool periodically
360  *
361  */
362 static time_t last_garbage_collection = 0;
363 const int garbage_interval = 24 * 60 * 60;  /* garbage collect every 24 hours */
364
365 void garbage_collect_memory_pool()
366 {
367    time_t now;
368
369    Dmsg0(200, "garbage collect memory pool\n");
370    P(mutex);
371    if (last_garbage_collection == 0) {
372       last_garbage_collection = time(NULL);
373       V(mutex);
374       return;
375    }
376    now = time(NULL);
377    if (now >= last_garbage_collection + garbage_interval) {
378       last_garbage_collection = now;
379       V(mutex);
380       close_memory_pool();
381    } else {
382       V(mutex);
383    }
384 }
385
386 /* Release all pooled memory */
387 void close_memory_pool()
388 {
389    struct abufhead *buf, *next;
390    int count = 0;
391    uint64_t bytes = 0;
392    char ed1[50];
393
394    sm_check(__FILE__, __LINE__, false);
395    P(mutex);
396    for (int i=1; i<=PM_MAX; i++) {
397       buf = pool_ctl[i].free_buf;
398       while (buf) {
399          next = buf->next;
400          count++;
401          bytes += sizeof_pool_memory((char *)buf);
402          free((char *)buf);
403          buf = next;
404       }
405       pool_ctl[i].free_buf = NULL;
406    }
407    Dmsg2(001, "Freed mem_pool count=%d size=%s\n", count, edit_uint64_with_commas(bytes, ed1));
408    if (debug_level >= 1) {
409       print_memory_pool_stats();
410    }
411    V(mutex);
412
413 }
414
415 #ifdef DEBUG
416 static const char *pool_name(int pool)
417 {
418    static const char *name[] = {"NoPool", "NAME  ", "FNAME ", "MSG   ", "EMSG  "};
419    static char buf[30];
420
421    if (pool >= 0 && pool <= PM_MAX) {
422       return name[pool];
423    }
424    sprintf(buf, "%-6d", pool);
425    return buf;
426 }
427
428 /* Print staticstics on memory pool usage
429  */
430 void print_memory_pool_stats()
431 {
432    Pmsg0(-1, "Pool   Maxsize  Maxused  Inuse\n");
433    for (int i=0; i<=PM_MAX; i++)
434       Pmsg4(-1, "%5s  %7d  %7d  %5d\n", pool_name(i), pool_ctl[i].max_allocated,
435          pool_ctl[i].max_used, pool_ctl[i].in_use);
436
437    Pmsg0(-1, "\n");
438 }
439
440 #else
441 void print_memory_pool_stats() {}
442 #endif /* DEBUG */
443
444 /*
445  * Concatenate a string (str) onto a pool memory buffer pm
446  *   Returns: length of concatenated string
447  */
448 int pm_strcat(POOLMEM **pm, const char *str)
449 {
450    int pmlen = strlen(*pm);
451    int len;
452
453    if (!str) str = "";
454
455    len = strlen(str) + 1;
456    *pm = check_pool_memory_size(*pm, pmlen + len);
457    memcpy(*pm+pmlen, str, len);
458    return pmlen + len - 1;
459 }
460
461 int pm_strcat(POOLMEM *&pm, const char *str)
462 {
463    int pmlen = strlen(pm);
464    int len;
465
466    if (!str) str = "";
467
468    len = strlen(str) + 1;
469    pm = check_pool_memory_size(pm, pmlen + len);
470    memcpy(pm+pmlen, str, len);
471    return pmlen + len - 1;
472 }
473
474 int pm_strcat(POOLMEM *&pm, POOL_MEM &str)
475 {
476    int pmlen = strlen(pm);
477    int len = strlen(str.c_str()) + 1;
478
479    pm = check_pool_memory_size(pm, pmlen + len);
480    memcpy(pm+pmlen, str.c_str(), len);
481    return pmlen + len - 1;
482 }
483
484 int pm_strcat(POOL_MEM &pm, const char *str)
485 {
486    int pmlen = strlen(pm.c_str());
487    int len;
488
489    if (!str) str = "";
490
491    len = strlen(str) + 1;
492    pm.check_size(pmlen + len);
493    memcpy(pm.c_str()+pmlen, str, len);
494    return pmlen + len - 1;
495 }
496
497 /*
498  * Copy a string (str) into a pool memory buffer pm
499  *   Returns: length of string copied
500  */
501 int pm_strcpy(POOLMEM **pm, const char *str)
502 {
503    int len;
504
505    if (!str) str = "";
506
507    len = strlen(str) + 1;
508    *pm = check_pool_memory_size(*pm, len);
509    memcpy(*pm, str, len);
510    return len - 1;
511 }
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, POOL_MEM &str)
526 {
527    int len = strlen(str.c_str()) + 1;
528
529    pm = check_pool_memory_size(pm, len);
530    memcpy(pm, str.c_str(), len);
531    return len - 1;
532 }
533
534 int pm_strcpy(POOL_MEM &pm, const char *str)
535 {
536    int len;
537
538    if (!str) str = "";
539
540    len = strlen(str) + 1;
541    pm.check_size(len);
542    memcpy(pm.c_str(), str, len);
543    return len - 1;
544 }
545
546 /*
547  * Copy data into a pool memory buffer pm
548  *   Returns: length of data copied
549  */
550 int pm_memcpy(POOLMEM **pm, const char *data, int32_t n)
551 {
552    *pm = check_pool_memory_size(*pm, n);
553    memcpy(*pm, data, n);
554    return n;
555 }
556
557 int pm_memcpy(POOLMEM *&pm, const char *data, int32_t n)
558 {
559    pm = check_pool_memory_size(pm, n);
560    memcpy(pm, data, n);
561    return n;
562 }
563
564 int pm_memcpy(POOLMEM *&pm, POOL_MEM &data, int32_t n)
565 {
566    pm = check_pool_memory_size(pm, n);
567    memcpy(pm, data.c_str(), n);
568    return n;
569 }
570
571 int pm_memcpy(POOL_MEM &pm, const char *data, int32_t n)
572 {
573    pm.check_size(n);
574    memcpy(pm.c_str(), data, n);
575    return n;
576 }
577
578 /* ==============  CLASS POOL_MEM   ============== */
579
580 /* Return the size of a memory buffer */
581 int32_t POOL_MEM::max_size()
582 {
583    int32_t size;
584    char *cp = mem;
585    cp -= HEAD_SIZE;
586    size = ((struct abufhead *)cp)->ablen;
587    Dmsg1(900, "max_size=%d\n", size);
588    return size;
589 }
590
591 void POOL_MEM::realloc_pm(int32_t size)
592 {
593    char *cp = mem;
594    char *buf;
595    int pool;
596
597    P(mutex);
598    cp -= HEAD_SIZE;
599    buf = (char *)realloc(cp, size+HEAD_SIZE);
600    if (buf == NULL) {
601       V(mutex);
602       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
603    }
604    Dmsg2(900, "Old buf=%p new buf=%p\n", cp, buf);
605    ((struct abufhead *)buf)->ablen = size;
606    pool = ((struct abufhead *)buf)->pool;
607    if (size > pool_ctl[pool].max_allocated) {
608       pool_ctl[pool].max_allocated = size;
609    }
610    mem = buf+HEAD_SIZE;
611    V(mutex);
612    Dmsg3(900, "Old buf=%p new buf=%p mem=%p\n", cp, buf, mem);
613 }
614
615 int POOL_MEM::strcat(const char *str)
616 {
617    int pmlen = strlen(mem);
618    int len;
619
620    if (!str) str = "";
621
622    len = strlen(str) + 1;
623    check_size(pmlen + len);
624    memcpy(mem+pmlen, str, len);
625    return pmlen + len - 1;
626 }
627
628 int POOL_MEM::strcpy(const char *str)
629 {
630    int len;
631
632    if (!str) str = "";
633
634    len = strlen(str) + 1;
635    check_size(len);
636    memcpy(mem, str, len);
637    return len - 1;
638 }