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