2 * Bacula memory pool routines.
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
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.
24 Copyright (C) 2000-2006 Kern Sibbald
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.
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.
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 */
48 /* Bacula Name length plus extra */
49 #define NLEN (MAX_NAME_LENGTH+2)
51 /* #define STRESS_TEST_POOL */
52 #ifndef STRESS_TEST_POOL
54 * Define default Pool buffer sizes
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 */
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 */
76 /* Memory allocation control structures and storage. */
78 int32_t ablen; /* Buffer length in bytes */
79 int32_t pool; /* pool */
80 struct abufhead *next; /* pointer to next free buffer */
83 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
88 #define HEAD_SIZE BALIGN(sizeof(struct abufhead))
90 POOLMEM *sm_get_pool_memory(const char *fname, int lineno, int pool)
95 Emsg2(M_ABORT, 0, _("MemPool index %d larger than max %d\n"), pool, PM_MAX);
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;
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);
111 if ((buf = (struct abufhead *)sm_malloc(fname, lineno, pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
113 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), pool_ctl[pool].size);
115 buf->ablen = pool_ctl[pool].size;
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;
122 Dmsg3(1800, "sm_get_pool_memory give %p to %s:%d\n", buf, fname, lineno);
123 return (POOLMEM *)((char *)buf+HEAD_SIZE);
126 /* Get nonpool memory of size requested */
127 POOLMEM *sm_get_memory(const char *fname, int lineno, int32_t size)
129 struct abufhead *buf;
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);
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);
145 /* Return the size of a memory buffer */
146 int32_t sm_sizeof_pool_memory(const char *fname, int lineno, POOLMEM *obuf)
148 char *cp = (char *)obuf;
152 return ((struct abufhead *)cp)->ablen;
155 /* Realloc pool memory buffer */
156 POOLMEM *sm_realloc_pool_memory(const char *fname, int lineno, POOLMEM *obuf, int32_t size)
158 char *cp = (char *)obuf;
165 buf = sm_realloc(fname, lineno, cp, size+HEAD_SIZE);
168 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
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;
176 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
179 POOLMEM *sm_check_pool_memory_size(const char *fname, int lineno, POOLMEM *obuf, int32_t size)
182 if (size <= sizeof_pool_memory(obuf)) {
185 return realloc_pool_memory(obuf, size);
188 /* Free a memory buffer */
189 void sm_free_pool_memory(const char *fname, int lineno, POOLMEM *obuf)
191 struct abufhead *buf;
196 buf = (struct abufhead *)((char *)obuf - HEAD_SIZE);
198 pool_ctl[pool].in_use--;
200 free((char *)buf); /* free nonpooled memory */
201 } else { /* otherwise link it to the free pool chain */
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) {
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 */
214 buf->next = pool_ctl[pool].free_buf;
215 pool_ctl[pool].free_buf = buf;
217 Dmsg4(1800, "free_pool_memory %p pool=%d from %s:%d\n", buf, pool, fname, lineno);
224 /* ========= NO SMARTALLOC ========================================= */
226 POOLMEM *get_pool_memory(int pool)
228 struct abufhead *buf;
231 if (pool_ctl[pool].free_buf) {
232 buf = pool_ctl[pool].free_buf;
233 pool_ctl[pool].free_buf = buf->next;
235 return (POOLMEM *)((char *)buf+HEAD_SIZE);
238 if ((buf=malloc(pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
240 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), pool_ctl[pool].size);
242 buf->ablen = pool_ctl[pool].size;
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;
250 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
253 /* Get nonpool memory of size requested */
254 POOLMEM *get_memory(int32_t size)
256 struct abufhead *buf;
259 if ((buf=malloc(size+HEAD_SIZE)) == NULL) {
260 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
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;
269 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
273 /* Return the size of a memory buffer */
274 int32_t sizeof_pool_memory(POOLMEM *obuf)
276 char *cp = (char *)obuf;
280 return ((struct abufhead *)cp)->ablen;
285 /* Realloc pool memory buffer */
286 POOLMEM *realloc_pool_memory(POOLMEM *obuf, int32_t size)
288 char *cp = (char *)obuf;
295 buf = realloc(cp, size+HEAD_SIZE);
298 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
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;
306 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
310 POOLMEM *check_pool_memory_size(POOLMEM *obuf, int32_t size)
313 if (size <= sizeof_pool_memory(obuf)) {
316 return realloc_pool_memory(obuf, size);
319 /* Free a memory buffer */
320 void free_pool_memory(POOLMEM *obuf)
322 struct abufhead *buf;
327 buf = (struct abufhead *)((char *)obuf - HEAD_SIZE);
329 pool_ctl[pool].in_use--;
331 free((char *)buf); /* free nonpooled memory */
332 } else { /* otherwise link it to the free pool chain */
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) {
339 ASSERT(next != buf); /* attempt to free twice */
343 buf->next = pool_ctl[pool].free_buf;
344 pool_ctl[pool].free_buf = buf;
346 Dmsg2(1800, "free_pool_memory %p pool=%d\n", buf, pool);
350 #endif /* SMARTALLOC */
354 * Clean up memory pool periodically
357 static time_t last_garbage_collection = 0;
358 const int garbage_interval = 24 * 60 * 60; /* garbage collect every 24 hours */
360 void garbage_collect_memory_pool()
364 Dmsg0(200, "garbage collect memory pool\n");
366 if (last_garbage_collection == 0) {
367 last_garbage_collection = time(NULL);
372 if (now >= last_garbage_collection + garbage_interval) {
373 last_garbage_collection = now;
384 /* Release all pooled memory */
385 void close_memory_pool()
387 struct abufhead *buf, *next;
392 sm_check(__FILE__, __LINE__, false);
394 for (int i=1; i<=PM_MAX; i++) {
395 buf = pool_ctl[i].free_buf;
399 bytes += sizeof_pool_memory((char *)buf);
403 pool_ctl[i].free_buf = NULL;
405 Dmsg2(100, "Freed mem_pool count=%d size=%s\n", count, edit_uint64_with_commas(bytes, ed1));
412 static const char *pool_name(int pool)
414 static const char *name[] = {"NoPool", "NAME ", "FNAME ", "MSG ", "EMSG "};
417 if (pool >= 0 && pool <= PM_MAX) {
420 sprintf(buf, "%-6d", pool);
424 /* Print staticstics on memory pool usage
426 void print_memory_pool_stats()
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);
437 void print_memory_pool_stats() {}
442 * Concatenate a string (str) onto a pool memory buffer pm
443 * Returns: length of concatenated string
445 int pm_strcat(POOLMEM **pm, const char *str)
447 int pmlen = strlen(*pm);
448 int len = strlen(str) + 1;
450 *pm = check_pool_memory_size(*pm, pmlen + len);
451 memcpy(*pm+pmlen, str, len);
452 return pmlen + len - 1;
455 int pm_strcat(POOLMEM *&pm, const char *str)
457 int pmlen = strlen(pm);
458 int len = strlen(str) + 1;
460 pm = check_pool_memory_size(pm, pmlen + len);
461 memcpy(pm+pmlen, str, len);
462 return pmlen + len - 1;
466 int pm_strcat(POOLMEM *&pm, POOL_MEM &str)
468 int pmlen = strlen(pm);
469 int len = strlen(str.c_str()) + 1;
471 pm = check_pool_memory_size(pm, pmlen + len);
472 memcpy(pm+pmlen, str.c_str(), len);
473 return pmlen + len - 1;
476 int pm_strcat(POOL_MEM &pm, const char *str)
478 int pmlen = strlen(pm.c_str());
479 int len = strlen(str) + 1;
481 pm.check_size(pmlen + len);
482 memcpy(pm.c_str()+pmlen, str, len);
483 return pmlen + len - 1;
488 * Copy a string (str) into a pool memory buffer pm
489 * Returns: length of string copied
491 int pm_strcpy(POOLMEM **pm, const char *str)
493 int len = strlen(str) + 1;
495 *pm = check_pool_memory_size(*pm, len);
496 memcpy(*pm, str, len);
500 int pm_strcpy(POOLMEM *&pm, const char *str)
502 int len = strlen(str) + 1;
504 pm = check_pool_memory_size(pm, len);
505 memcpy(pm, str, len);
509 int pm_strcpy(POOLMEM *&pm, POOL_MEM &str)
511 int len = strlen(str.c_str()) + 1;
513 pm = check_pool_memory_size(pm, len);
514 memcpy(pm, str.c_str(), len);
519 int pm_strcpy(POOL_MEM &pm, const char *str)
521 int len = strlen(str) + 1;
523 memcpy(pm.c_str(), str, len);
527 /* ============== CLASS POOL_MEM ============== */
529 /* Return the size of a memory buffer */
530 int32_t POOL_MEM::max_size()
535 size = ((struct abufhead *)cp)->ablen;
536 Dmsg1(900, "max_size=%d\n", size);
540 void POOL_MEM::realloc_pm(int32_t size)
548 buf = (char *)realloc(cp, size+HEAD_SIZE);
551 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
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;
561 Dmsg3(900, "Old buf=%p new buf=%p mem=%p\n", cp, buf, mem);
564 int POOL_MEM::strcat(const char *str)
566 int pmlen = strlen(mem);
567 int len = strlen(str) + 1;
569 check_size(pmlen + len);
570 memcpy(mem+pmlen, str, len);
571 return pmlen + len - 1;
575 int POOL_MEM::strcpy(const char *str)
577 int len = strlen(str) + 1;
579 memcpy(mem, str, len);