Enhance buffer handling by changing gwbuf_free to free the whole list of buffers (although it could contain only one buffer). Add gwbuf_count to give number of buffers in a buffer list (for convenience in debugging). Add gwbuf_alloc_and_load to simplify putting data into a new buffer.

This commit is contained in:
counterpoint
2016-01-08 09:29:10 +00:00
parent 57b79fc663
commit 78b363aec7
2 changed files with 71 additions and 7 deletions

View File

@ -20,7 +20,7 @@
* @file buffer.h - The MaxScale buffer management functions * @file buffer.h - The MaxScale buffer management functions
* *
* The buffer management is based on the principle of a linked list * The buffer management is based on the principle of a linked list
* of variable size buffer, the intention beign to allow longer * of variable size buffer, the intention being to allow longer
* content to be buffered in a list and minimise any need to copy * content to be buffered in a list and minimise any need to copy
* data between buffers. * data between buffers.
* *
@ -37,6 +37,8 @@
* the gwbuf_append process * the gwbuf_append process
* 09/11/2015 Martin Brampton Add buffer tracing (conditional compilation), * 09/11/2015 Martin Brampton Add buffer tracing (conditional compilation),
* accessed by "show buffers" maxadmin command * accessed by "show buffers" maxadmin command
* 20/12/2015 Martin Brampton Change gwbuf_free to free the whole list; add the
* gwbuf_count and gwbuf_alloc_and_load functions.
* *
* @endverbatim * @endverbatim
*/ */
@ -56,6 +58,7 @@
static HASHTABLE *buffer_hashtable = NULL; static HASHTABLE *buffer_hashtable = NULL;
#endif #endif
static void gwbuf_free_one(GWBUF *buf);
static buffer_object_t* gwbuf_remove_buffer_object(GWBUF* buf, static buffer_object_t* gwbuf_remove_buffer_object(GWBUF* buf,
buffer_object_t* bufobj); buffer_object_t* bufobj);
@ -71,7 +74,7 @@ static void gwbuf_remove_from_hashtable(GWBUF *buf);
* *
* For now we allocate memory directly from malloc for buffer the management * For now we allocate memory directly from malloc for buffer the management
* structure and the actual data buffer itself. We may swap at a future date * structure and the actual data buffer itself. We may swap at a future date
* to a more effecient mechanism. * to a more efficient mechanism.
* *
* @param size The size in bytes of the data area required * @param size The size in bytes of the data area required
* @return Pointer to the buffer structure or NULL if memory could not * @return Pointer to the buffer structure or NULL if memory could not
@ -135,6 +138,25 @@ retblock:
return rval; return rval;
} }
/**
* Allocate a new gateway buffer structure of size bytes and load with data.
*
* @param size The size in bytes of the data area required
* @param data Pointer to the data (size bytes) to be loaded
* @return Pointer to the buffer structure or NULL if memory could not
* be allocated.
*/
GWBUF *
gwbuf_alloc_and_load(unsigned int size, void *data)
{
GWBUF *rval;
if ((rval = gwbuf_alloc(size)) != NULL)
{
memcpy(GWBUF_DATA(rval), data, size);
}
return rval;
}
#if defined(BUFFER_TRACE) #if defined(BUFFER_TRACE)
/** /**
* Store a trace of buffer creation * Store a trace of buffer creation
@ -232,17 +254,37 @@ dprintAllBuffers(void *pdcb)
#endif #endif
/** /**
* Free a gateway buffer * Free a list of gateway buffers
* *
* @param buf The buffer to free * @param buf The head of the list of buffers to free
*/ */
void void
gwbuf_free(GWBUF *buf) gwbuf_free(GWBUF *buf)
{
GWBUF *nextbuf;
BUF_PROPERTY *prop;
buffer_object_t *bo;
while (buf)
{
CHK_GWBUF(buf);
nextbuf = buf->next;
gwbuf_free_one(buf);
buf = nextbuf;
}
}
/**
* Free a single gateway buffer
*
* @param buf The buffer to free
*/
static void
gwbuf_free_one(GWBUF *buf)
{ {
BUF_PROPERTY *prop; BUF_PROPERTY *prop;
buffer_object_t *bo; buffer_object_t *bo;
CHK_GWBUF(buf);
if (atomic_add(&buf->sbuf->refcount, -1) == 1) if (atomic_add(&buf->sbuf->refcount, -1) == 1)
{ {
free(buf->sbuf->data); free(buf->sbuf->data);
@ -493,7 +535,7 @@ gwbuf_consume(GWBUF *head, unsigned int length)
head->next->tail = head->tail; head->next->tail = head->tail;
} }
gwbuf_free(head); gwbuf_free_one(head);
} }
ss_dassert(rval == NULL || (rval->end > rval->start)); ss_dassert(rval == NULL || (rval->end > rval->start));
@ -523,6 +565,26 @@ gwbuf_length(GWBUF *head)
return rval; return rval;
} }
/**
* Return the number of individual buffers in the linked list.
*
* Currently not used, provided mainly for use during debugging sessions.
*
* @param head The current head of the linked list
* @return The number of bytes of data in the linked list
*/
int
gwbuf_count(GWBUF *head)
{
int result = 0;
while (head)
{
result++;
head = head->next;
}
return result;
}
/** /**
* Trim bytes form the end of a GWBUF structure. If the * Trim bytes form the end of a GWBUF structure. If the
* buffer has n_bytes or less then it will be freed and * buffer has n_bytes or less then it will be freed and
@ -599,7 +661,7 @@ void gwbuf_set_type(
* @param buf GWBUF where object is added * @param buf GWBUF where object is added
* @param id Type identifier for object * @param id Type identifier for object
* @param data Object data * @param data Object data
* @param donefun_dp Clean-up function to be executed before buffer is freed. * @param donefun_fp Clean-up function to be executed before buffer is freed.
*/ */
void gwbuf_add_buffer_object(GWBUF* buf, void gwbuf_add_buffer_object(GWBUF* buf,
bufobj_id_t id, bufobj_id_t id,

View File

@ -188,6 +188,7 @@ typedef struct gwbuf
* Function prototypes for the API to maniplate the buffers * Function prototypes for the API to maniplate the buffers
*/ */
extern GWBUF *gwbuf_alloc(unsigned int size); extern GWBUF *gwbuf_alloc(unsigned int size);
extern GWBUF *gwbuf_alloc_and_load(unsigned int size, void *data);
extern void gwbuf_free(GWBUF *buf); extern void gwbuf_free(GWBUF *buf);
extern GWBUF *gwbuf_clone(GWBUF *buf); extern GWBUF *gwbuf_clone(GWBUF *buf);
extern GWBUF *gwbuf_append(GWBUF *head, GWBUF *tail); extern GWBUF *gwbuf_append(GWBUF *head, GWBUF *tail);
@ -195,6 +196,7 @@ extern GWBUF *gwbuf_consume(GWBUF *head, unsigned int length);
extern GWBUF *gwbuf_trim(GWBUF *head, unsigned int length); extern GWBUF *gwbuf_trim(GWBUF *head, unsigned int length);
extern GWBUF *gwbuf_rtrim(GWBUF *head, unsigned int length); extern GWBUF *gwbuf_rtrim(GWBUF *head, unsigned int length);
extern unsigned int gwbuf_length(GWBUF *head); extern unsigned int gwbuf_length(GWBUF *head);
extern int gwbuf_count(GWBUF *head);
extern GWBUF *gwbuf_clone_portion(GWBUF *head, size_t offset, size_t len); extern GWBUF *gwbuf_clone_portion(GWBUF *head, size_t offset, size_t len);
extern GWBUF *gwbuf_clone_transform(GWBUF *head, gwbuf_type_t type); extern GWBUF *gwbuf_clone_transform(GWBUF *head, gwbuf_type_t type);
extern GWBUF *gwbuf_clone_all(GWBUF* head); extern GWBUF *gwbuf_clone_all(GWBUF* head);