Add conditionally compiled mechanism to "show buffers" to give a list of the currently allocated buffers, with a trace for each one of the calls that led to its creation.

This commit is contained in:
counterpoint
2015-11-11 09:03:48 +00:00
parent 72072778de
commit 1fc6b00211
3 changed files with 140 additions and 3 deletions

View File

@ -35,6 +35,8 @@
* 15/07/2014 Mark Riddoch Addition of properties * 15/07/2014 Mark Riddoch Addition of properties
* 28/08/2014 Mark Riddoch Adition of tail pointer to speed * 28/08/2014 Mark Riddoch Adition of tail pointer to speed
* the gwbuf_append process * the gwbuf_append process
* 09/11/2015 Martin Brampton Add buffer tracing (conditional compilation),
* accessed by "show buffers" maxadmin command
* *
* @endverbatim * @endverbatim
*/ */
@ -47,6 +49,13 @@
#include <log_manager.h> #include <log_manager.h>
#include <errno.h> #include <errno.h>
#if defined(BUFFER_TRACE)
#include <hashtable.h>
#include <execinfo.h>
static HASHTABLE *buffer_hashtable = NULL;
#endif
/** Defined in log_manager.cc */ /** Defined in log_manager.cc */
extern int lm_enabled_logfiles_bitmask; extern int lm_enabled_logfiles_bitmask;
extern size_t log_ses_count[]; extern size_t log_ses_count[];
@ -56,6 +65,12 @@ static buffer_object_t* gwbuf_remove_buffer_object(
GWBUF* buf, GWBUF* buf,
buffer_object_t* bufobj); buffer_object_t* bufobj);
#if defined(BUFFER_TRACE)
static void gwbuf_add_to_hashtable(GWBUF *buf);
static int bhashfn (void *key);
static int bcmpfn (void *key1, void *key2);
static void gwbuf_remove_from_hashtable(GWBUF *buf);
#endif
/** /**
* Allocate a new gateway buffer structure of size bytes. * Allocate a new gateway buffer structure of size bytes.
@ -119,9 +134,111 @@ retblock:
"Error : Memory allocation failed due to %s.", "Error : Memory allocation failed due to %s.",
strerror_r(errno, errbuf, sizeof(errbuf))))); strerror_r(errno, errbuf, sizeof(errbuf)))));
} }
#if defined(BUFFER_TRACE)
else
{
gwbuf_add_to_hashtable(rval);
}
#endif
return rval; return rval;
} }
#if defined(BUFFER_TRACE)
/**
* Store a trace of buffer creation
*
* @param buf The buffer to record
*/
static void
gwbuf_add_to_hashtable(GWBUF *buf)
{
void *array[16];
size_t size, i, total;
char **strings;
char *tracetext;
size = backtrace (array, 16);
strings = backtrace_symbols (array, size);
total = (2 * size) + 1;
for (i = 0; i < size; i++)
{
total += strlen(strings[i]);
}
tracetext = (char *)malloc(total);
if (tracetext)
{
char *ptr = tracetext;
for (i = 0; i < size; i++)
{
sprintf(ptr, "\t%s\n", strings[i]);
ptr += (strlen(strings[i]) + 2);
}
free (strings);
if (NULL == buffer_hashtable)
{
buffer_hashtable = hashtable_alloc(10000, bhashfn, bcmpfn);
hashtable_memory_fns(buffer_hashtable,NULL,NULL,NULL,(HASHMEMORYFN)free);
}
hashtable_add(buffer_hashtable, buf, (void *)tracetext);
}
}
/**
* Hash a buffer (address) to an integer
*
* @param key The pointer to the buffer
*/
static int
bhashfn(void *key)
{
return (int)((uintptr_t) key % INT_MAX);
}
/**
* Compare two buffer keys (pointers)
*
* @param key1 The pointer to the first buffer
* @param key2 The pointer to the second buffer
*/
static int
bcmpfn(void *key1, void *key2)
{
return key1 == key2 ? 0 : 1;
}
/**
* Remove a buffer from the store of buffer traces
*
* @param buf The buffer to be removed
*/
static void
gwbuf_remove_from_hashtable(GWBUF *buf)
{
hashtable_delete(buffer_hashtable, buf);
}
/**
* Print all buffer traces via a given print DCB
*
* @param pdcb Print DCB for output
*/
void
dprintAllBuffers(void *pdcb)
{
void *buf;
char *backtrace;
HASHITERATOR *buffers = hashtable_iterator(buffer_hashtable);
while (NULL != (buf = hashtable_next(buffers)))
{
dcb_printf((DCB *)pdcb, "Buffer: %p\n", (void *)buf);
backtrace = hashtable_fetch(buffer_hashtable, buf);
dcb_printf((DCB *)pdcb, "%s", backtrace);
}
hashtable_iterator_free(buffers);
}
#endif
/** /**
* Free a gateway buffer * Free a gateway buffer
* *
@ -162,6 +279,9 @@ BUF_PROPERTY *prop;
buf->hint = buf->hint->next; buf->hint = buf->hint->next;
hint_free(h); hint_free(h);
} }
#if defined(BUFFER_TRACE)
gwbuf_remove_from_hashtable(buf);
#endif
free(buf); free(buf);
} }
@ -201,6 +321,9 @@ GWBUF *rval;
rval->tail = rval; rval->tail = rval;
rval->next = NULL; rval->next = NULL;
CHK_GWBUF(rval); CHK_GWBUF(rval);
#if defined(BUFFER_TRACE)
gwbuf_add_to_hashtable(rval);
#endif
return rval; return rval;
} }
@ -268,6 +391,9 @@ GWBUF *gwbuf_clone_portion(
clonebuf->next = NULL; clonebuf->next = NULL;
clonebuf->tail = clonebuf; clonebuf->tail = clonebuf;
CHK_GWBUF(clonebuf); CHK_GWBUF(clonebuf);
#if defined(BUFFER_TRACE)
gwbuf_add_to_hashtable(clonebuf);
#endif
return clonebuf; return clonebuf;
} }

View File

@ -43,6 +43,7 @@
* 03/10/2014 Martin Brampton Pointer arithmetic standard conformity * 03/10/2014 Martin Brampton Pointer arithmetic standard conformity
* Add more buffer handling macros * Add more buffer handling macros
* Add gwbuf_rtrim (handle chains) * Add gwbuf_rtrim (handle chains)
* 09/11/2014 Martin Brampton Add dprintAllBuffers (conditional compilation)
* *
* @endverbatim * @endverbatim
*/ */
@ -52,7 +53,6 @@
#include <spinlock.h> #include <spinlock.h>
#include <stdint.h> #include <stdint.h>
EXTERN_C_BLOCK_BEGIN EXTERN_C_BLOCK_BEGIN
/** /**
@ -202,6 +202,9 @@ void gwbuf_add_buffer_object(GWBUF* buf,
void* data, void* data,
void (*donefun_fp)(void *)); void (*donefun_fp)(void *));
void* gwbuf_get_buffer_object_data(GWBUF* buf, bufobj_id_t id); void* gwbuf_get_buffer_object_data(GWBUF* buf, bufobj_id_t id);
#if defined(BUFFER_TRACE)
extern void dprintAllBuffers(void *pdcb);
#endif
EXTERN_C_BLOCK_END EXTERN_C_BLOCK_END

View File

@ -43,7 +43,8 @@
* 29/05/14 Mark Riddoch Add Filter support * 29/05/14 Mark Riddoch Add Filter support
* 16/10/14 Mark Riddoch Add show eventq * 16/10/14 Mark Riddoch Add show eventq
* 05/03/15 Massimiliano Pinto Added enable/disable feedback * 05/03/15 Massimiliano Pinto Added enable/disable feedback
* 27/05/15 Martin Brampton Add show persistent [server] * 27/05/15 Martin Brampton Add show persistent [server]
* 06/11/15 Martin Brampton Add show buffers (conditional compilation)
* *
* @endverbatim * @endverbatim
*/ */
@ -60,6 +61,7 @@
#include <atomic.h> #include <atomic.h>
#include <server.h> #include <server.h>
#include <spinlock.h> #include <spinlock.h>
#include <buffer.h>
#include <dcb.h> #include <dcb.h>
#include <poll.h> #include <poll.h>
#include <users.h> #include <users.h>
@ -107,6 +109,12 @@ static void telnetdShowUsers(DCB *);
* The subcommands of the show command * The subcommands of the show command
*/ */
struct subcommand showoptions[] = { struct subcommand showoptions[] = {
#if defined(BUFFER_TRACE)
{ "buffers", 0, dprintAllBuffers,
"Show all buffers with backtrace",
"Show all buffers with backtrace",
{0, 0, 0} },
#endif
{ "dcbs", 0, dprintAllDCBs, { "dcbs", 0, dprintAllDCBs,
"Show all descriptor control blocks (network connections)", "Show all descriptor control blocks (network connections)",
"Show all descriptor control blocks (network connections)", "Show all descriptor control blocks (network connections)",