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-2004 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 as
28 published by the Free Software Foundation; either version 2 of
29 the License, or (at your option) any later version.
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 GNU
34 General Public License for more details.
36 You should have received a copy of the GNU General Public
37 License along with this program; if not, write to the Free
38 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
46 int32_t size; /* default size */
47 int32_t max_allocated; /* max allocated */
48 int32_t max_used; /* max buffers used */
49 int32_t in_use; /* number in use */
50 struct abufhead *free_buf; /* pointer to free buffers */
53 /* Bacula Name length plus extra */
54 #define NLEN (MAX_NAME_LENGTH+2)
56 /* #define STRESS_TEST_POOL */
57 #ifndef STRESS_TEST_POOL
59 * Define default Pool buffer sizes
61 static struct s_pool_ctl pool_ctl[] = {
62 { 256, 256, 0, 0, NULL }, /* PM_NOPOOL no pooling */
63 { NLEN, NLEN,0, 0, NULL }, /* PM_NAME Bacula name */
64 { 256, 256, 0, 0, NULL }, /* PM_FNAME filename buffers */
65 { 512, 512, 0, 0, NULL }, /* PM_MESSAGE message buffer */
66 { 1024, 1024, 0, 0, NULL } /* PM_EMSG error message buffer */
70 /* This is used ONLY when stress testing the code */
71 static struct s_pool_ctl pool_ctl[] = {
72 { 20, 20, 0, 0, NULL }, /* PM_NOPOOL no pooling */
73 { NLEN, NLEN,0, 0, NULL }, /* PM_NAME Bacula name */
74 { 20, 20, 0, 0, NULL }, /* PM_FNAME filename buffers */
75 { 20, 20, 0, 0, NULL }, /* PM_MESSAGE message buffer */
76 { 20, 20, 0, 0, NULL } /* PM_EMSG error message buffer */
81 /* Memory allocation control structures and storage. */
83 int32_t ablen; /* Buffer length in bytes */
84 int32_t pool; /* pool */
85 struct abufhead *next; /* pointer to next free buffer */
88 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
93 #define HEAD_SIZE BALIGN(sizeof(struct abufhead))
95 POOLMEM *sm_get_pool_memory(const char *fname, int lineno, int pool)
100 Emsg2(M_ABORT, 0, "MemPool index %d larger than max %d\n", pool, PM_MAX);
103 if (pool_ctl[pool].free_buf) {
104 buf = pool_ctl[pool].free_buf;
105 pool_ctl[pool].free_buf = buf->next;
106 pool_ctl[pool].in_use++;
107 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
108 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
111 Dmsg3(1800, "sm_get_pool_memory reuse %x to %s:%d\n", buf, fname, lineno);
112 sm_new_owner(fname, lineno, (char *)buf);
113 return (POOLMEM *)((char *)buf+HEAD_SIZE);
116 if ((buf = (struct abufhead *)sm_malloc(fname, lineno, pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
118 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", pool_ctl[pool].size);
120 buf->ablen = pool_ctl[pool].size;
122 pool_ctl[pool].in_use++;
123 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
124 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
127 Dmsg3(1800, "sm_get_pool_memory give %x to %s:%d\n", buf, fname, lineno);
128 return (POOLMEM *)((char *)buf+HEAD_SIZE);
131 /* Get nonpool memory of size requested */
132 POOLMEM *sm_get_memory(const char *fname, int lineno, int32_t size)
134 struct abufhead *buf;
137 if ((buf = (struct abufhead *)sm_malloc(fname, lineno, size+HEAD_SIZE)) == NULL) {
138 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
143 pool_ctl[pool].in_use++;
144 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used)
145 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
146 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
150 /* Return the size of a memory buffer */
151 int32_t sm_sizeof_pool_memory(const char *fname, int lineno, POOLMEM *obuf)
153 char *cp = (char *)obuf;
157 return ((struct abufhead *)cp)->ablen;
160 /* Realloc pool memory buffer */
161 POOLMEM *sm_realloc_pool_memory(const char *fname, int lineno, POOLMEM *obuf, int32_t size)
163 char *cp = (char *)obuf;
170 buf = sm_realloc(fname, lineno, cp, size+HEAD_SIZE);
173 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
175 ((struct abufhead *)buf)->ablen = size;
176 pool = ((struct abufhead *)buf)->pool;
177 if (size > pool_ctl[pool].max_allocated) {
178 pool_ctl[pool].max_allocated = size;
181 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
184 POOLMEM *sm_check_pool_memory_size(const char *fname, int lineno, POOLMEM *obuf, int32_t size)
187 if (size <= sizeof_pool_memory(obuf)) {
190 return realloc_pool_memory(obuf, size);
193 /* Free a memory buffer */
194 void sm_free_pool_memory(const char *fname, int lineno, POOLMEM *obuf)
196 struct abufhead *buf;
201 buf = (struct abufhead *)((char *)obuf - HEAD_SIZE);
203 pool_ctl[pool].in_use--;
205 free((char *)buf); /* free nonpooled memory */
206 } else { /* otherwise link it to the free pool chain */
208 struct abufhead *next;
209 /* Don't let him free the same buffer twice */
210 for (next=pool_ctl[pool].free_buf; next; next=next->next) {
212 Dmsg4(1800, "bad free_pool_memory %x pool=%d from %s:%d\n", buf, pool, fname, lineno);
213 V(mutex); /* unblock the pool */
214 ASSERT(next != buf); /* attempt to free twice */
218 buf->next = pool_ctl[pool].free_buf;
219 pool_ctl[pool].free_buf = buf;
221 Dmsg4(1800, "free_pool_memory %x pool=%d from %s:%d\n", buf, pool, fname, lineno);
228 /* ========= NO SMARTALLOC ========================================= */
230 POOLMEM *get_pool_memory(int pool)
232 struct abufhead *buf;
235 if (pool_ctl[pool].free_buf) {
236 buf = pool_ctl[pool].free_buf;
237 pool_ctl[pool].free_buf = buf->next;
239 return (POOLMEM *)((char *)buf+HEAD_SIZE);
242 if ((buf=malloc(pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
244 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", pool_ctl[pool].size);
246 buf->ablen = pool_ctl[pool].size;
249 pool_ctl[pool].in_use++;
250 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
251 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
254 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
257 /* Get nonpool memory of size requested */
258 POOLMEM *get_memory(int32_t size)
260 struct abufhead *buf;
263 if ((buf=malloc(size+HEAD_SIZE)) == NULL) {
264 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
269 pool_ctl[pool].in_use++;
270 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
271 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
273 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
277 /* Return the size of a memory buffer */
278 int32_t sizeof_pool_memory(POOLMEM *obuf)
280 char *cp = (char *)obuf;
284 return ((struct abufhead *)cp)->ablen;
289 /* Realloc pool memory buffer */
290 POOLMEM *realloc_pool_memory(POOLMEM *obuf, int32_t size)
292 char *cp = (char *)obuf;
299 buf = realloc(cp, size+HEAD_SIZE);
302 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
304 ((struct abufhead *)buf)->ablen = size;
305 pool = ((struct abufhead *)buf)->pool;
306 if (size > pool_ctl[pool].max_allocated) {
307 pool_ctl[pool].max_allocated = size;
310 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
314 POOLMEM *check_pool_memory_size(POOLMEM *obuf, int32_t size)
317 if (size <= sizeof_pool_memory(obuf)) {
320 return realloc_pool_memory(obuf, size);
323 /* Free a memory buffer */
324 void free_pool_memory(POOLMEM *obuf)
326 struct abufhead *buf;
331 buf = (struct abufhead *)((char *)obuf - HEAD_SIZE);
333 pool_ctl[pool].in_use--;
335 free((char *)buf); /* free nonpooled memory */
336 } else { /* otherwise link it to the free pool chain */
338 struct abufhead *next;
339 /* Don't let him free the same buffer twice */
340 for (next=pool_ctl[pool].free_buf; next; next=next->next) {
343 ASSERT(next != buf); /* attempt to free twice */
347 buf->next = pool_ctl[pool].free_buf;
348 pool_ctl[pool].free_buf = buf;
350 Dmsg2(1800, "free_pool_memory %x pool=%d\n", buf, pool);
354 #endif /* SMARTALLOC */
361 /* Release all pooled memory */
362 void close_memory_pool()
364 struct abufhead *buf, *next;
366 sm_check(__FILE__, __LINE__, false);
368 for (int i=1; i<=PM_MAX; i++) {
369 buf = pool_ctl[i].free_buf;
375 pool_ctl[i].free_buf = NULL;
382 static const char *pool_name(int pool)
384 static const char *name[] = {"NoPool", "NAME ", "FNAME ", "MSG ", "EMSG "};
387 if (pool >= 0 && pool <= PM_MAX) {
390 sprintf(buf, "%-6d", pool);
394 /* Print staticstics on memory pool usage
396 void print_memory_pool_stats()
398 Pmsg0(-1, "Pool Maxsize Maxused Inuse\n");
399 for (int i=0; i<=PM_MAX; i++)
400 Pmsg4(-1, "%5s %7d %7d %5d\n", pool_name(i), pool_ctl[i].max_allocated,
401 pool_ctl[i].max_used, pool_ctl[i].in_use);
407 void print_memory_pool_stats() {}
412 * Concatenate a string (str) onto a pool memory buffer pm
413 * Returns: length of concatenated string
415 int pm_strcat(POOLMEM **pm, const char *str)
417 int pmlen = strlen(*pm);
418 int len = strlen(str) + 1;
420 *pm = check_pool_memory_size(*pm, pmlen + len);
421 memcpy(*pm+pmlen, str, len);
422 return pmlen + len - 1;
425 int pm_strcat(POOLMEM *&pm, const char *str)
427 int pmlen = strlen(pm);
428 int len = strlen(str) + 1;
430 pm = check_pool_memory_size(pm, pmlen + len);
431 memcpy(pm+pmlen, str, len);
432 return pmlen + len - 1;
436 int pm_strcat(POOLMEM *&pm, POOL_MEM &str)
438 int pmlen = strlen(pm);
439 int len = strlen(str.c_str()) + 1;
441 pm = check_pool_memory_size(pm, pmlen + len);
442 memcpy(pm+pmlen, str.c_str(), len);
443 return pmlen + len - 1;
446 int pm_strcat(POOL_MEM &pm, const char *str)
448 int pmlen = strlen(pm.c_str());
449 int len = strlen(str) + 1;
451 pm.check_size(pmlen + len);
452 memcpy(pm.c_str()+pmlen, str, len);
453 return pmlen + len - 1;
458 * Copy a string (str) into a pool memory buffer pm
459 * Returns: length of string copied
461 int pm_strcpy(POOLMEM **pm, const char *str)
463 int len = strlen(str) + 1;
465 *pm = check_pool_memory_size(*pm, len);
466 memcpy(*pm, str, len);
470 int pm_strcpy(POOLMEM *&pm, const char *str)
472 int len = strlen(str) + 1;
474 pm = check_pool_memory_size(pm, len);
475 memcpy(pm, str, len);
479 int pm_strcpy(POOLMEM *&pm, POOL_MEM &str)
481 int len = strlen(str.c_str()) + 1;
483 pm = check_pool_memory_size(pm, len);
484 memcpy(pm, str.c_str(), len);
489 int pm_strcpy(POOL_MEM &pm, const char *str)
491 int len = strlen(str) + 1;
493 memcpy(pm.c_str(), str, len);
497 /* ============== CLASS POOL_MEM ============== */
499 /* Return the size of a memory buffer */
500 int32_t POOL_MEM::max_size()
505 size = ((struct abufhead *)cp)->ablen;
506 Dmsg1(000, "max_size=%d\n", size);
510 void POOL_MEM::realloc_pm(int32_t size)
518 buf = (char *)realloc(cp, size+HEAD_SIZE);
521 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
523 Dmsg2(000, "Old buf=0x%x new buf=0x%x\n", cp, buf);
524 ((struct abufhead *)buf)->ablen = size;
525 pool = ((struct abufhead *)buf)->pool;
526 if (size > pool_ctl[pool].max_allocated) {
527 pool_ctl[pool].max_allocated = size;
531 Dmsg3(000, "Old buf=0x%x new buf=0x%x mem=0x%x\n", cp, buf, mem);
534 int POOL_MEM::strcat(const char *str)
536 int pmlen = strlen(mem);
537 int len = strlen(str) + 1;
539 check_size(pmlen + len);
540 memcpy(mem+pmlen, str, len);
541 return pmlen + len - 1;
545 int POOL_MEM::strcpy(const char *str)
547 int len = strlen(str) + 1;
549 memcpy(mem, str, len);