]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/mem_pool.c
Fix typo
[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(100, "Freed mem_pool count=%d size=%s\n", count, edit_uint64_with_commas(bytes, ed1));
408    V(mutex);
409
410 }
411
412 #ifdef DEBUG
413 static const char *pool_name(int pool)
414 {
415    static const char *name[] = {"NoPool", "NAME  ", "FNAME ", "MSG   ", "EMSG  "};
416    static char buf[30];
417
418    if (pool >= 0 && pool <= PM_MAX) {
419       return name[pool];
420    }
421    sprintf(buf, "%-6d", pool);
422    return buf;
423 }
424
425 /* Print staticstics on memory pool usage
426  */
427 void print_memory_pool_stats()
428 {
429    Pmsg0(-1, "Pool   Maxsize  Maxused  Inuse\n");
430    for (int i=0; i<=PM_MAX; i++)
431       Pmsg4(-1, "%5s  %7d  %7d  %5d\n", pool_name(i), pool_ctl[i].max_allocated,
432          pool_ctl[i].max_used, pool_ctl[i].in_use);
433
434    Pmsg0(-1, "\n");
435 }
436
437 #else
438 void print_memory_pool_stats() {}
439 #endif /* DEBUG */
440
441 /*
442  * Concatenate a string (str) onto a pool memory buffer pm
443  *   Returns: length of concatenated string
444  */
445 int pm_strcat(POOLMEM **pm, const char *str)
446 {
447    int pmlen = strlen(*pm);
448    int len;
449
450    if (!str) str = "";
451
452    len = strlen(str) + 1;
453    *pm = check_pool_memory_size(*pm, pmlen + len);
454    memcpy(*pm+pmlen, str, len);
455    return pmlen + len - 1;
456 }
457
458 int pm_strcat(POOLMEM *&pm, const char *str)
459 {
460    int pmlen = strlen(pm);
461    int len;
462
463    if (!str) str = "";
464
465    len = strlen(str) + 1;
466    pm = check_pool_memory_size(pm, pmlen + len);
467    memcpy(pm+pmlen, str, len);
468    return pmlen + len - 1;
469 }
470
471 int pm_strcat(POOLMEM *&pm, POOL_MEM &str)
472 {
473    int pmlen = strlen(pm);
474    int len = strlen(str.c_str()) + 1;
475
476    pm = check_pool_memory_size(pm, pmlen + len);
477    memcpy(pm+pmlen, str.c_str(), len);
478    return pmlen + len - 1;
479 }
480
481 int pm_strcat(POOL_MEM &pm, const char *str)
482 {
483    int pmlen = strlen(pm.c_str());
484    int len;
485
486    if (!str) str = "";
487
488    len = strlen(str) + 1;
489    pm.check_size(pmlen + len);
490    memcpy(pm.c_str()+pmlen, str, len);
491    return pmlen + len - 1;
492 }
493
494 /*
495  * Copy a string (str) into a pool memory buffer pm
496  *   Returns: length of string copied
497  */
498 int pm_strcpy(POOLMEM **pm, const char *str)
499 {
500    int len;
501
502    if (!str) str = "";
503
504    len = strlen(str) + 1;
505    *pm = check_pool_memory_size(*pm, len);
506    memcpy(*pm, str, len);
507    return len - 1;
508 }
509
510 int pm_strcpy(POOLMEM *&pm, const char *str)
511 {
512    int len;
513
514    if (!str) str = "";
515
516    len = strlen(str) + 1;
517    pm = check_pool_memory_size(pm, len);
518    memcpy(pm, str, len);
519    return len - 1;
520 }
521
522 int pm_strcpy(POOLMEM *&pm, POOL_MEM &str)
523 {
524    int len = strlen(str.c_str()) + 1;
525
526    pm = check_pool_memory_size(pm, len);
527    memcpy(pm, str.c_str(), len);
528    return len - 1;
529 }
530
531 int pm_strcpy(POOL_MEM &pm, const char *str)
532 {
533    int len;
534
535    if (!str) str = "";
536
537    len = strlen(str) + 1;
538    pm.check_size(len);
539    memcpy(pm.c_str(), str, len);
540    return len - 1;
541 }
542
543 /*
544  * Copy data into a pool memory buffer pm
545  *   Returns: length of data copied
546  */
547 int pm_memcpy(POOLMEM **pm, const char *data, int32_t n)
548 {
549    *pm = check_pool_memory_size(*pm, n);
550    memcpy(*pm, data, n);
551    return n;
552 }
553
554 int pm_memcpy(POOLMEM *&pm, const char *data, int32_t n)
555 {
556    pm = check_pool_memory_size(pm, n);
557    memcpy(pm, data, n);
558    return n;
559 }
560
561 int pm_memcpy(POOLMEM *&pm, POOL_MEM &data, int32_t n)
562 {
563    pm = check_pool_memory_size(pm, n);
564    memcpy(pm, data.c_str(), n);
565    return n;
566 }
567
568 int pm_memcpy(POOL_MEM &pm, const char *data, int32_t n)
569 {
570    pm.check_size(n);
571    memcpy(pm.c_str(), data, n);
572    return n;
573 }
574
575 /* ==============  CLASS POOL_MEM   ============== */
576
577 /* Return the size of a memory buffer */
578 int32_t POOL_MEM::max_size()
579 {
580    int32_t size;
581    char *cp = mem;
582    cp -= HEAD_SIZE;
583    size = ((struct abufhead *)cp)->ablen;
584    Dmsg1(900, "max_size=%d\n", size);
585    return size;
586 }
587
588 void POOL_MEM::realloc_pm(int32_t size)
589 {
590    char *cp = mem;
591    char *buf;
592    int pool;
593
594    P(mutex);
595    cp -= HEAD_SIZE;
596    buf = (char *)realloc(cp, size+HEAD_SIZE);
597    if (buf == NULL) {
598       V(mutex);
599       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
600    }
601    Dmsg2(900, "Old buf=%p new buf=%p\n", cp, buf);
602    ((struct abufhead *)buf)->ablen = size;
603    pool = ((struct abufhead *)buf)->pool;
604    if (size > pool_ctl[pool].max_allocated) {
605       pool_ctl[pool].max_allocated = size;
606    }
607    mem = buf+HEAD_SIZE;
608    V(mutex);
609    Dmsg3(900, "Old buf=%p new buf=%p mem=%p\n", cp, buf, mem);
610 }
611
612 int POOL_MEM::strcat(const char *str)
613 {
614    int pmlen = strlen(mem);
615    int len;
616
617    if (!str) str = "";
618
619    len = strlen(str) + 1;
620    check_size(pmlen + len);
621    memcpy(mem+pmlen, str, len);
622    return pmlen + len - 1;
623 }
624
625 int POOL_MEM::strcpy(const char *str)
626 {
627    int len;
628
629    if (!str) str = "";
630
631    len = strlen(str) + 1;
632    check_size(len);
633    memcpy(mem, str, len);
634    return len - 1;
635 }