/*
- * Bacula memory pool routines.
+ * Bacula memory pool routines.
*
* The idea behind these routines is that there will be
* pools of memory that are pre-allocated for quick
* access. The pools will have a fixed memory size on allocation
- * but if need be, the size can be increased. This is
+ * but if need be, the size can be increased. This is
* particularly useful for filename
* buffers where 256 bytes should be sufficient in 99.99%
* of the cases, but when it isn't we want to be able to
* there is enough memory, simply call the check_pool_memory_size()
* with the desired size and it will adjust only if necessary.
*
- * Kern E. Sibbald
+ * Kern E. Sibbald
*
* Version $Id$
*/
/*
- Copyright (C) 2000-2003 Kern Sibbald and John Walker
+ Copyright (C) 2000-2004 Kern Sibbald
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
#include "bacula.h"
struct s_pool_ctl {
- int32_t size; /* default size */
- int32_t max_size; /* max allocated */
- int32_t max_used; /* max buffers used */
- int32_t in_use; /* number in use */
- struct abufhead *free_buf; /* pointer to free buffers */
+ int32_t size; /* default size */
+ int32_t max_allocated; /* max allocated */
+ int32_t max_used; /* max buffers used */
+ int32_t in_use; /* number in use */
+ struct abufhead *free_buf; /* pointer to free buffers */
};
/* Bacula Name length plus extra */
* Define default Pool buffer sizes
*/
static struct s_pool_ctl pool_ctl[] = {
- { 256, 256, 0, 0, NULL }, /* PM_NOPOOL no pooling */
- { NLEN, NLEN,0, 0, NULL }, /* PM_NAME Bacula name */
- { 256, 256, 0, 0, NULL }, /* PM_FNAME filename buffers */
- { 512, 512, 0, 0, NULL }, /* PM_MESSAGE message buffer */
- { 1024, 1024, 0, 0, NULL } /* PM_EMSG error message buffer */
+ { 256, 256, 0, 0, NULL }, /* PM_NOPOOL no pooling */
+ { NLEN, NLEN,0, 0, NULL }, /* PM_NAME Bacula name */
+ { 256, 256, 0, 0, NULL }, /* PM_FNAME filename buffers */
+ { 512, 512, 0, 0, NULL }, /* PM_MESSAGE message buffer */
+ { 1024, 1024, 0, 0, NULL } /* PM_EMSG error message buffer */
};
#else
/* This is used ONLY when stress testing the code */
static struct s_pool_ctl pool_ctl[] = {
- { 20, 20, 0, 0, NULL }, /* PM_NOPOOL no pooling */
- { NLEN, NLEN,0, 0, NULL }, /* PM_NAME Bacula name */
- { 20, 20, 0, 0, NULL }, /* PM_FNAME filename buffers */
- { 20, 20, 0, 0, NULL }, /* PM_MESSAGE message buffer */
- { 20, 20, 0, 0, NULL } /* PM_EMSG error message buffer */
+ { 20, 20, 0, 0, NULL }, /* PM_NOPOOL no pooling */
+ { NLEN, NLEN,0, 0, NULL }, /* PM_NAME Bacula name */
+ { 20, 20, 0, 0, NULL }, /* PM_FNAME filename buffers */
+ { 20, 20, 0, 0, NULL }, /* PM_MESSAGE message buffer */
+ { 20, 20, 0, 0, NULL } /* PM_EMSG error message buffer */
};
#endif
/* Memory allocation control structures and storage. */
struct abufhead {
- int32_t ablen; /* Buffer length in bytes */
- int32_t pool; /* pool */
- struct abufhead *next; /* pointer to next free buffer */
+ int32_t ablen; /* Buffer length in bytes */
+ int32_t pool; /* pool */
+ struct abufhead *next; /* pointer to next free buffer */
};
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
#define HEAD_SIZE BALIGN(sizeof(struct abufhead))
-POOLMEM *sm_get_pool_memory(char *fname, int lineno, int pool)
+POOLMEM *sm_get_pool_memory(const char *fname, int lineno, int pool)
{
struct abufhead *buf;
if (pool > PM_MAX) {
- Emsg2(M_ABORT, 0, "MemPool index %d larger than max %d\n", pool, PM_MAX);
+ Emsg2(M_ABORT, 0, _("MemPool index %d larger than max %d\n"), pool, PM_MAX);
}
P(mutex);
if (pool_ctl[pool].free_buf) {
pool_ctl[pool].free_buf = buf->next;
pool_ctl[pool].in_use++;
if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
- pool_ctl[pool].max_used = pool_ctl[pool].in_use;
+ pool_ctl[pool].max_used = pool_ctl[pool].in_use;
}
V(mutex);
- Dmsg3(300, "sm_get_pool_memory reuse %x to %s:%d\n", buf, fname, lineno);
+ Dmsg3(1800, "sm_get_pool_memory reuse %x to %s:%d\n", buf, fname, lineno);
sm_new_owner(fname, lineno, (char *)buf);
return (POOLMEM *)((char *)buf+HEAD_SIZE);
}
-
+
if ((buf = (struct abufhead *)sm_malloc(fname, lineno, pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
V(mutex);
- Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", pool_ctl[pool].size);
+ Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), pool_ctl[pool].size);
}
buf->ablen = pool_ctl[pool].size;
buf->pool = pool;
pool_ctl[pool].max_used = pool_ctl[pool].in_use;
}
V(mutex);
- Dmsg3(300, "sm_get_pool_memory give %x to %s:%d\n", buf, fname, lineno);
+ Dmsg3(1800, "sm_get_pool_memory give %x to %s:%d\n", buf, fname, lineno);
return (POOLMEM *)((char *)buf+HEAD_SIZE);
}
/* Get nonpool memory of size requested */
-POOLMEM *sm_get_memory(char *fname, int lineno, int32_t size)
+POOLMEM *sm_get_memory(const char *fname, int lineno, int32_t size)
{
struct abufhead *buf;
int pool = 0;
- if ((buf = (struct abufhead *) sm_malloc(fname, lineno, size+HEAD_SIZE)) == NULL) {
- Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
+ if ((buf = (struct abufhead *)sm_malloc(fname, lineno, size+HEAD_SIZE)) == NULL) {
+ Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
}
buf->ablen = size;
buf->pool = pool;
/* Return the size of a memory buffer */
-int32_t sm_sizeof_pool_memory(char *fname, int lineno, POOLMEM *obuf)
+int32_t sm_sizeof_pool_memory(const char *fname, int lineno, POOLMEM *obuf)
{
char *cp = (char *)obuf;
}
/* Realloc pool memory buffer */
-POOLMEM *sm_realloc_pool_memory(char *fname, int lineno, POOLMEM *obuf, int32_t size)
+POOLMEM *sm_realloc_pool_memory(const char *fname, int lineno, POOLMEM *obuf, int32_t size)
{
char *cp = (char *)obuf;
void *buf;
buf = sm_realloc(fname, lineno, cp, size+HEAD_SIZE);
if (buf == NULL) {
V(mutex);
- Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
+ Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
}
((struct abufhead *)buf)->ablen = size;
pool = ((struct abufhead *)buf)->pool;
- if (size > pool_ctl[pool].max_size) {
- pool_ctl[pool].max_size = size;
+ if (size > pool_ctl[pool].max_allocated) {
+ pool_ctl[pool].max_allocated = size;
}
V(mutex);
return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
}
-POOLMEM *sm_check_pool_memory_size(char *fname, int lineno, POOLMEM *obuf, int32_t size)
+POOLMEM *sm_check_pool_memory_size(const char *fname, int lineno, POOLMEM *obuf, int32_t size)
{
ASSERT(obuf);
if (size <= sizeof_pool_memory(obuf)) {
}
/* Free a memory buffer */
-void sm_free_pool_memory(char *fname, int lineno, POOLMEM *obuf)
+void sm_free_pool_memory(const char *fname, int lineno, POOLMEM *obuf)
{
struct abufhead *buf;
int pool;
pool = buf->pool;
pool_ctl[pool].in_use--;
if (pool == 0) {
- free((char *)buf); /* free nonpooled memory */
- } else { /* otherwise link it to the free pool chain */
+ free((char *)buf); /* free nonpooled memory */
+ } else { /* otherwise link it to the free pool chain */
#ifdef DEBUG
struct abufhead *next;
/* Don't let him free the same buffer twice */
for (next=pool_ctl[pool].free_buf; next; next=next->next) {
- if (next == buf) {
- Dmsg4(300, "bad free_pool_memory %x pool=%d from %s:%d\n", buf, pool, fname, lineno);
- V(mutex); /* unblock the pool */
- ASSERT(next != buf); /* attempt to free twice */
- }
+ if (next == buf) {
+ Dmsg4(1800, "bad free_pool_memory %x pool=%d from %s:%d\n", buf, pool, fname, lineno);
+ V(mutex); /* unblock the pool */
+ ASSERT(next != buf); /* attempt to free twice */
+ }
}
#endif
buf->next = pool_ctl[pool].free_buf;
pool_ctl[pool].free_buf = buf;
}
- Dmsg4(300, "free_pool_memory %x pool=%d from %s:%d\n", buf, pool, fname, lineno);
+ Dmsg4(1800, "free_pool_memory %x pool=%d from %s:%d\n", buf, pool, fname, lineno);
V(mutex);
}
#else
-/* =================================================================== */
+/* ========= NO SMARTALLOC ========================================= */
POOLMEM *get_pool_memory(int pool)
{
V(mutex);
return (POOLMEM *)((char *)buf+HEAD_SIZE);
}
-
+
if ((buf=malloc(pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
V(mutex);
- Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", pool_ctl[pool].size);
+ Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), pool_ctl[pool].size);
}
buf->ablen = pool_ctl[pool].size;
buf->pool = pool;
int pool = 0;
if ((buf=malloc(size+HEAD_SIZE)) == NULL) {
- Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
+ Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
}
buf->ablen = size;
buf->pool = pool;
return ((struct abufhead *)cp)->ablen;
}
+
+
/* Realloc pool memory buffer */
POOLMEM *realloc_pool_memory(POOLMEM *obuf, int32_t size)
{
buf = realloc(cp, size+HEAD_SIZE);
if (buf == NULL) {
V(mutex);
- Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
+ Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
}
((struct abufhead *)buf)->ablen = size;
pool = ((struct abufhead *)buf)->pool;
- if (size > pool_ctl[pool].max_size) {
- pool_ctl[pool].max_size = size;
+ if (size > pool_ctl[pool].max_allocated) {
+ pool_ctl[pool].max_allocated = size;
}
V(mutex);
return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
}
+
POOLMEM *check_pool_memory_size(POOLMEM *obuf, int32_t size)
{
ASSERT(obuf);
pool = buf->pool;
pool_ctl[pool].in_use--;
if (pool == 0) {
- free((char *)buf); /* free nonpooled memory */
- } else { /* otherwise link it to the free pool chain */
+ free((char *)buf); /* free nonpooled memory */
+ } else { /* otherwise link it to the free pool chain */
#ifdef DEBUG
struct abufhead *next;
/* Don't let him free the same buffer twice */
for (next=pool_ctl[pool].free_buf; next; next=next->next) {
- if (next == buf) {
- V(mutex);
- ASSERT(next != buf); /* attempt to free twice */
- }
+ if (next == buf) {
+ V(mutex);
+ ASSERT(next != buf); /* attempt to free twice */
+ }
}
#endif
buf->next = pool_ctl[pool].free_buf;
pool_ctl[pool].free_buf = buf;
}
- Dmsg2(300, "free_pool_memory %x pool=%d\n", buf, pool);
+ Dmsg2(1800, "free_pool_memory %x pool=%d\n", buf, pool);
V(mutex);
}
void close_memory_pool()
{
struct abufhead *buf, *next;
- int i;
- sm_check(__FILE__, __LINE__, False);
+ sm_check(__FILE__, __LINE__, false);
P(mutex);
- for (i=1; i<=PM_MAX; i++) {
+ for (int i=1; i<=PM_MAX; i++) {
buf = pool_ctl[i].free_buf;
while (buf) {
- next = buf->next;
- free((char *)buf);
- buf = next;
+ next = buf->next;
+ free((char *)buf);
+ buf = next;
}
pool_ctl[i].free_buf = NULL;
}
#ifdef DEBUG
-static char *pool_name(int pool)
+static const char *pool_name(int pool)
{
- static char *name[] = {"NoPool", "FNAME ", "MSG ", "EMSG "};
+ static const char *name[] = {"NoPool", "NAME ", "FNAME ", "MSG ", "EMSG "};
static char buf[30];
if (pool >= 0 && pool <= PM_MAX) {
sprintf(buf, "%-6d", pool);
return buf;
}
-
-/* Print staticstics on memory pool usage
- */
+
+/* Print staticstics on memory pool usage
+ */
void print_memory_pool_stats()
{
- int i;
-
- Dmsg0(-1, "Pool Maxsize Maxused Inuse\n");
- for (i=0; i<=PM_MAX; i++)
- Dmsg4(-1, "%5s %7d %7d %5d\n", pool_name(i), pool_ctl[i].max_size,
- pool_ctl[i].max_used, pool_ctl[i].in_use);
+ Pmsg0(-1, "Pool Maxsize Maxused Inuse\n");
+ for (int i=0; i<=PM_MAX; i++)
+ Pmsg4(-1, "%5s %7d %7d %5d\n", pool_name(i), pool_ctl[i].max_allocated,
+ pool_ctl[i].max_used, pool_ctl[i].in_use);
- Dmsg0(-1, "\n");
+ Pmsg0(-1, "\n");
}
#else
-void print_memory_pool_stats() {}
+void print_memory_pool_stats() {}
#endif /* DEBUG */
+
+
+/*
+ * Concatenate a string (str) onto a pool memory buffer pm
+ * Returns: length of concatenated string
+ */
+int pm_strcat(POOLMEM **pm, const char *str)
+{
+ int pmlen = strlen(*pm);
+ int len = strlen(str) + 1;
+
+ *pm = check_pool_memory_size(*pm, pmlen + len);
+ memcpy(*pm+pmlen, str, len);
+ return pmlen + len - 1;
+}
+
+int pm_strcat(POOLMEM *&pm, const char *str)
+{
+ int pmlen = strlen(pm);
+ int len = strlen(str) + 1;
+
+ pm = check_pool_memory_size(pm, pmlen + len);
+ memcpy(pm+pmlen, str, len);
+ return pmlen + len - 1;
+}
+
+
+int pm_strcat(POOLMEM *&pm, POOL_MEM &str)
+{
+ int pmlen = strlen(pm);
+ int len = strlen(str.c_str()) + 1;
+
+ pm = check_pool_memory_size(pm, pmlen + len);
+ memcpy(pm+pmlen, str.c_str(), len);
+ return pmlen + len - 1;
+}
+
+int pm_strcat(POOL_MEM &pm, const char *str)
+{
+ int pmlen = strlen(pm.c_str());
+ int len = strlen(str) + 1;
+
+ pm.check_size(pmlen + len);
+ memcpy(pm.c_str()+pmlen, str, len);
+ return pmlen + len - 1;
+}
+
+
+/*
+ * Copy a string (str) into a pool memory buffer pm
+ * Returns: length of string copied
+ */
+int pm_strcpy(POOLMEM **pm, const char *str)
+{
+ int len = strlen(str) + 1;
+
+ *pm = check_pool_memory_size(*pm, len);
+ memcpy(*pm, str, len);
+ return len - 1;
+}
+
+int pm_strcpy(POOLMEM *&pm, const char *str)
+{
+ int len = strlen(str) + 1;
+
+ pm = check_pool_memory_size(pm, len);
+ memcpy(pm, str, len);
+ return len - 1;
+}
+
+int pm_strcpy(POOLMEM *&pm, POOL_MEM &str)
+{
+ int len = strlen(str.c_str()) + 1;
+
+ pm = check_pool_memory_size(pm, len);
+ memcpy(pm, str.c_str(), len);
+ return len - 1;
+}
+
+
+int pm_strcpy(POOL_MEM &pm, const char *str)
+{
+ int len = strlen(str) + 1;
+ pm.check_size(len);
+ memcpy(pm.c_str(), str, len);
+ return len - 1;
+}
+
+/* ============== CLASS POOL_MEM ============== */
+
+/* Return the size of a memory buffer */
+int32_t POOL_MEM::max_size()
+{
+ int32_t size;
+ char *cp = mem;
+ cp -= HEAD_SIZE;
+ size = ((struct abufhead *)cp)->ablen;
+ Dmsg1(900, "max_size=%d\n", size);
+ return size;
+}
+
+void POOL_MEM::realloc_pm(int32_t size)
+{
+ char *cp = mem;
+ char *buf;
+ int pool;
+
+ P(mutex);
+ cp -= HEAD_SIZE;
+ buf = (char *)realloc(cp, size+HEAD_SIZE);
+ if (buf == NULL) {
+ V(mutex);
+ Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), size);
+ }
+ Dmsg2(900, "Old buf=0x%x new buf=0x%x\n", cp, buf);
+ ((struct abufhead *)buf)->ablen = size;
+ pool = ((struct abufhead *)buf)->pool;
+ if (size > pool_ctl[pool].max_allocated) {
+ pool_ctl[pool].max_allocated = size;
+ }
+ mem = buf+HEAD_SIZE;
+ V(mutex);
+ Dmsg3(900, "Old buf=0x%x new buf=0x%x mem=0x%x\n", cp, buf, mem);
+}
+
+int POOL_MEM::strcat(const char *str)
+{
+ int pmlen = strlen(mem);
+ int len = strlen(str) + 1;
+
+ check_size(pmlen + len);
+ memcpy(mem+pmlen, str, len);
+ return pmlen + len - 1;
+}
+
+
+int POOL_MEM::strcpy(const char *str)
+{
+ int len = strlen(str) + 1;
+ check_size(len);
+ memcpy(mem, str, len);
+ return len - 1;
+}