diff options
Diffstat (limited to 'libglusterfs/src/circ-buff.c')
| -rw-r--r-- | libglusterfs/src/circ-buff.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/libglusterfs/src/circ-buff.c b/libglusterfs/src/circ-buff.c new file mode 100644 index 000000000..484ce7dc9 --- /dev/null +++ b/libglusterfs/src/circ-buff.c @@ -0,0 +1,202 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include "circ-buff.h" + +void +cb_destroy_data (circular_buffer_t *cb, + void (*destroy_buffer_data) (void *data)) +{ + if (destroy_buffer_data) + destroy_buffer_data (cb->data); + GF_FREE (cb->data); + return; +} + + +/* hold lock while calling this function */ +int +__cb_add_entry_buffer (buffer_t *buffer, void *item) +{ + circular_buffer_t *ptr = NULL; + int ret = -1; + //DO we really need the assert here? + GF_ASSERT (buffer->used_len <= buffer->size_buffer); + + if (buffer->use_once == _gf_true && + buffer->used_len == buffer->size_buffer) { + gf_log ("", GF_LOG_WARNING, "buffer %p is use once buffer", + buffer); + return -1; + } else { + if (buffer->used_len == buffer->size_buffer) { + if (buffer->cb[buffer->w_index]) { + ptr = buffer->cb[buffer->w_index]; + if (ptr->data) { + cb_destroy_data (ptr, + buffer->destroy_buffer_data); + ptr->data = NULL; + GF_FREE (ptr); + } + buffer->cb[buffer->w_index] = NULL; + ptr = NULL; + } + } + + buffer->cb[buffer->w_index] = + GF_CALLOC (1, sizeof (circular_buffer_t), + gf_common_mt_circular_buffer_t); + if (!buffer->cb[buffer->w_index]) + return -1; + + buffer->cb[buffer->w_index]->data = item; + ret = gettimeofday (&buffer->cb[buffer->w_index]->tv, NULL); + if (ret == -1) + gf_log_callingfn ("", GF_LOG_WARNING, "getting time of" + "the day failed"); + buffer->w_index++; + buffer->w_index %= buffer->size_buffer; + //used_buffer size cannot be greater than the total buffer size + + if (buffer->used_len < buffer->size_buffer) + buffer->used_len++; + return buffer->w_index; + } +} + +int +cb_add_entry_buffer (buffer_t *buffer, void *item) +{ + int write_index = -1; + + pthread_mutex_lock (&buffer->lock); + { + write_index = __cb_add_entry_buffer (buffer, item); + } + pthread_mutex_unlock (&buffer->lock); + + return write_index; +} + +void +cb_buffer_show (buffer_t *buffer) +{ + pthread_mutex_lock (&buffer->lock); + { + gf_log ("", GF_LOG_DEBUG, "w_index: %d, size: %"GF_PRI_SIZET + " used_buffer: %d", buffer->w_index, + buffer->size_buffer, + buffer->used_len); + } + pthread_mutex_unlock (&buffer->lock); +} + +void +cb_buffer_dump (buffer_t *buffer, void *data, + int (fn) (circular_buffer_t *buffer, void *data)) +{ + int index = 0; + circular_buffer_t *entry = NULL; + int entries = 0; + int ul = 0; + int w_ind = 0; + int size_buff = 0; + int i = 0; + + ul = buffer->used_len; + w_ind = buffer->w_index; + size_buff = buffer->size_buffer; + + pthread_mutex_lock (&buffer->lock); + { + if (buffer->use_once == _gf_false) { + index = (size_buff + (w_ind - ul))%size_buff; + for (entries = 0; entries < buffer->used_len; + entries++) { + entry = buffer->cb[index]; + if (entry) + fn (entry, data); + else + gf_log_callingfn ("", GF_LOG_WARNING, + "Null entry in " + "circular buffer at " + "index %d.", index); + + index++; + index %= buffer->size_buffer; + } + } else { + for (i = 0; i < buffer->used_len ; i++) { + entry = buffer->cb[i]; + fn (entry, data); + } + } + } + pthread_mutex_unlock (&buffer->lock); +} + +buffer_t * +cb_buffer_new (size_t buffer_size, gf_boolean_t use_once, + void (*destroy_buffer_data) (void *data)) +{ + buffer_t *buffer = NULL; + + buffer = GF_CALLOC (1, sizeof (*buffer), gf_common_mt_buffer_t); + if (!buffer) { + gf_log ("", GF_LOG_ERROR, "could not allocate the " + "buffer"); + goto out; + } + + buffer->cb = GF_CALLOC (buffer_size, + sizeof (circular_buffer_t *), + gf_common_mt_circular_buffer_t); + if (!buffer->cb) { + gf_log ("", GF_LOG_ERROR, "could not allocate the " + "memory for the circular buffer"); + GF_FREE (buffer); + buffer = NULL; + goto out; + } + + buffer->w_index = 0; + buffer->size_buffer = buffer_size; + buffer->use_once = use_once; + buffer->used_len = 0; + buffer->destroy_buffer_data = destroy_buffer_data; + pthread_mutex_init (&buffer->lock, NULL); + +out: + return buffer; +} + +void +cb_buffer_destroy (buffer_t *buffer) +{ + int i = 0; + circular_buffer_t *ptr = NULL; + if (buffer) { + if (buffer->cb) { + for (i = 0; i < buffer->used_len ; i++) { + ptr = buffer->cb[i]; + if (ptr->data) { + cb_destroy_data (ptr, + buffer->destroy_buffer_data); + ptr->data = NULL; + GF_FREE (ptr); + } + } + GF_FREE (buffer->cb); + } + pthread_mutex_destroy (&buffer->lock); + GF_FREE (buffer); + } +} + |
