From: oetiker Date: Mon, 20 Apr 2009 06:48:01 +0000 (+0000) Subject: This patch includes utility functions to support dynamically sized arrays. X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=4445ea8dfeb4f30fd181c922141303fa49e01c5a;p=rrdtool.git This patch includes utility functions to support dynamically sized arrays. This simplifies the code that manages some of the dynamic structures inside rrdcached. A few data types have been changed to size_t. -- kevin git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1796 a5681a0c-68f1-0310-ab6d-d61299d08faa --- diff --git a/doc/Makefile.am b/doc/Makefile.am index f5f2cb1..74a5455 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -13,7 +13,7 @@ POD = bin_dec_hex.pod rrddump.pod rrdgraph_examples.pod rrdre rpntutorial.pod rrdfirst.pod rrdgraph_rpn.pod rrdtool.pod rrdcached.pod \ rrd-beginners.pod rrdinfo.pod rrdtune.pod rrdbuild.pod rrdflush.pod \ rrdcgi.pod rrdgraph.pod rrdlast.pod rrdlastupdate.pod \ - rrdcreate.pod rrdgraph_data.pod rrdresize.pod rrdtutorial.pod + rrdcreate.pod rrdgraph_data.pod rrdresize.pod rrdtutorial.pod librrd.pod if BUILD_LIBDBI POD += rrdgraph_libdbi.pod diff --git a/doc/librrd.pod b/doc/librrd.pod new file mode 100644 index 0000000..52cf18e --- /dev/null +++ b/doc/librrd.pod @@ -0,0 +1,61 @@ +=pod + +=head1 NAME + +librrd - RRD library functions + +=head1 DESCRIPTION + +B contains most of the functionality in B. The command +line utilities and language bindings are often just wrappers around the +code contained in B. + +This manual page documents the B API. + +B This document is a work in progress, and should be considered +incomplete as long as this warning persists. For more information about +the B functions, always consult the source code. + +=head1 UTILITY FUNCTIONS + +=over + +=item B + +Generates random numbers just like random(). This further ensures that +the random number generator is seeded exactly once per process. + +=item B + +Dynamically resize the array pointed to by C. C is a +pointer to the current size of C. Upon successful realloc(), the +C is incremented by 1 and the C pointer is stored at the +end of the new C. Returns 1 on success, 0 on failure. + + type **arr = NULL; + type *elem = "whatever"; + size_t arr_size = 0; + if (!rrd_add_ptr(&arr, &arr_size, elem)) + handle_failure(); + +=item B + +Like C, except adds a C of the source string. + + char **arr = NULL; + size_t arr_size = NULL; + char *str = "example text"; + if (!rrd_add_strdup(&arr, &arr_size, str)) + handle_failure(); + +=item B + +Free an array of pointers allocated by C or +C. Also frees the array pointer itself. On return, the +source pointer will be NULL and the count will be zero. + + /* created as above */ + rrd_free_ptrs(&arr, &arr_size); + /* here, arr == NULL && arr_size == 0 */ + +=back diff --git a/src/librrd.sym.in.in b/src/librrd.sym.in.in index 0a7a699..f947fe5 100644 --- a/src/librrd.sym.in.in +++ b/src/librrd.sym.in.in @@ -1,3 +1,5 @@ +rrd_add_ptr +rrd_add_strdup rrd_clear_error rrd_close rrd_cmd_flush @@ -12,6 +14,7 @@ rrd_first rrd_first_r rrd_free rrd_free_context +rrd_free_ptrs rrd_freemem rrd_get_context rrd_get_error diff --git a/src/rrd.h b/src/rrd.h index fd506d9..0227ed4 100644 --- a/src/rrd.h +++ b/src/rrd.h @@ -323,6 +323,10 @@ int rrd_proc_start_end( long rrd_random(void); + int rrd_add_ptr(void ***dest, size_t *dest_size, void *src); + int rrd_add_strdup(char ***dest, size_t *dest_size, char *src); + void rrd_free_ptrs(void ***src, size_t *cnt); + /* * The following functions are _internal_ functions needed to read the raw RRD * files. Since they are _internal_ they may change with the file format and diff --git a/src/rrd_daemon.c b/src/rrd_daemon.c index 7a7ae88..53904a3 100644 --- a/src/rrd_daemon.c +++ b/src/rrd_daemon.c @@ -175,7 +175,7 @@ struct cache_item_s { char *file; char **values; - int values_num; + size_t values_num; time_t last_flush_time; time_t last_update_stamp; #define CI_FLAGS_IN_TREE (1<<0) @@ -244,7 +244,7 @@ static size_t _config_base_dir_len = 0; static int config_write_base_only = 0; static listen_socket_t **config_listen_address_list = NULL; -static int config_listen_address_list_len = 0; +static size_t config_listen_address_list_len = 0; static uint64_t stats_queue_length = 0; static uint64_t stats_updates_received = 0; @@ -642,7 +642,7 @@ static void *free_cache_item(cache_item_t *ci) /* {{{ */ remove_from_queue(ci); - for (int i=0; i < ci->values_num; i++) + for (size_t i=0; i < ci->values_num; i++) free(ci->values[i]); free (ci->values); @@ -745,20 +745,12 @@ static gboolean tree_callback_flush (gpointer key, gpointer value, /* {{{ */ else if (((cfd->now - ci->last_flush_time) >= config_flush_interval) && (ci->values_num <= 0)) { - char **temp; - - temp = (char **) rrd_realloc (cfd->keys, - sizeof (char *) * (cfd->keys_num + 1)); - if (temp == NULL) + assert ((char *) key == ci->file); + if (!rrd_add_ptr((void ***)&cfd->keys, &cfd->keys_num, (void *)key)) { - RRDD_LOG (LOG_ERR, "tree_callback_flush: realloc failed."); + RRDD_LOG (LOG_ERR, "tree_callback_flush: rrd_add_ptrs failed."); return (FALSE); } - cfd->keys = temp; - /* Make really sure this points to the _same_ place */ - assert ((char *) key == ci->file); - cfd->keys[cfd->keys_num] = (char *) key; - cfd->keys_num++; } return (FALSE); @@ -863,9 +855,8 @@ static void *queue_thread_main (void *args __attribute__((unused))) /* {{{ */ cache_item_t *ci; char *file; char **values; - int values_num; + size_t values_num; int status; - int i; /* Now, check if there's something to store away. If not, wait until * something comes in. if we are shutting down, do not wait around. */ @@ -906,7 +897,7 @@ static void *queue_thread_main (void *args __attribute__((unused))) /* {{{ */ pthread_mutex_unlock (&cache_lock); rrd_clear_error (); - status = rrd_update_r (file, NULL, values_num, (void *) values); + status = rrd_update_r (file, NULL, (int) values_num, (void *) values); if (status != 0) { RRDD_LOG (LOG_NOTICE, "queue_thread_main: " @@ -917,10 +908,7 @@ static void *queue_thread_main (void *args __attribute__((unused))) /* {{{ */ journal_write("wrote", file); pthread_cond_broadcast(&ci->flushed); - for (i = 0; i < values_num; i++) - free (values[i]); - - free(values); + rrd_free_ptrs((void ***) &values, &values_num); free(file); if (status == 0) @@ -1227,7 +1215,7 @@ static int handle_request_pending(HANDLER_PROTO) /* {{{ */ return send_response(sock, RESP_ERR, "%s\n", rrd_strerror(ENOENT)); } - for (int i=0; i < ci->values_num; i++) + for (size_t i=0; i < ci->values_num; i++) add_response_info(sock, "%s\n", ci->values[i]); pthread_mutex_unlock(&cache_lock); @@ -1369,7 +1357,6 @@ static int handle_request_update (HANDLER_PROTO) /* {{{ */ while (buffer_size > 0) { - char **temp; char *value; time_t stamp; char *eostamp; @@ -1400,22 +1387,11 @@ static int handle_request_update (HANDLER_PROTO) /* {{{ */ else ci->last_update_stamp = stamp; - temp = (char **) rrd_realloc (ci->values, - sizeof (char *) * (ci->values_num + 1)); - if (temp == NULL) - { - RRDD_LOG (LOG_ERR, "handle_request_update: realloc failed."); - continue; - } - ci->values = temp; - - ci->values[ci->values_num] = strdup (value); - if (ci->values[ci->values_num] == NULL) + if (!rrd_add_strdup(&ci->values, &ci->values_num, value)) { - RRDD_LOG (LOG_ERR, "handle_request_update: strdup failed."); + RRDD_LOG (LOG_ERR, "handle_request_update: rrd_add_strdup failed."); continue; } - ci->values_num++; values_num++; } @@ -1445,7 +1421,6 @@ static int handle_request_update (HANDLER_PROTO) /* {{{ */ */ static int handle_request_wrote (HANDLER_PROTO) /* {{{ */ { - int i; cache_item_t *ci; const char *file = buffer; @@ -1459,12 +1434,7 @@ static int handle_request_wrote (HANDLER_PROTO) /* {{{ */ } if (ci->values) - { - for (i=0; i < ci->values_num; i++) - free(ci->values[i]); - - free(ci->values); - } + rrd_free_ptrs((void ***) &ci->values, &ci->values_num); wipe_ci_values(ci, now); remove_from_queue(ci); @@ -2434,13 +2404,11 @@ static int daemonize (void) /* {{{ */ /* open all the listen sockets */ if (config_listen_address_list_len > 0) { - for (int i = 0; i < config_listen_address_list_len; i++) - { + for (size_t i = 0; i < config_listen_address_list_len; i++) open_listen_socket (config_listen_address_list[i]); - free_listen_socket (config_listen_address_list[i]); - } - free(config_listen_address_list); + rrd_free_ptrs((void ***) &config_listen_address_list, + &config_listen_address_list_len); } else { @@ -2564,7 +2532,6 @@ static int read_options (int argc, char **argv) /* {{{ */ case 'L': case 'l': { - listen_socket_t **temp; listen_socket_t *new; new = malloc(sizeof(listen_socket_t)); @@ -2575,20 +2542,15 @@ static int read_options (int argc, char **argv) /* {{{ */ } memset(new, 0, sizeof(listen_socket_t)); - temp = (listen_socket_t **) rrd_realloc (config_listen_address_list, - sizeof (listen_socket_t *) * (config_listen_address_list_len + 1)); - if (temp == NULL) - { - fprintf (stderr, "read_options: realloc failed.\n"); - return (2); - } - config_listen_address_list = temp; - strncpy(new->addr, optarg, sizeof(new->addr)-1); new->privilege = (option == 'l') ? PRIV_HIGH : PRIV_LOW; - temp[config_listen_address_list_len] = new; - config_listen_address_list_len++; + if (!rrd_add_ptr((void ***)&config_listen_address_list, + &config_listen_address_list_len, new)) + { + fprintf(stderr, "read_options: rrd_add_ptr failed.\n"); + return (2); + } } break; diff --git a/src/rrd_utils.c b/src/rrd_utils.c index 39d2aca..9ac3e8a 100644 --- a/src/rrd_utils.c +++ b/src/rrd_utils.c @@ -16,6 +16,7 @@ #include "rrd_tool.h" #include +#include #ifdef WIN32 # define random() rand() @@ -34,3 +35,63 @@ long rrd_random(void) return random(); } + +/* rrd_add_ptr: add a pointer to a dynamically sized array of pointers, + * realloc as necessary. returns 1 on success, 0 on failure. + */ + +int rrd_add_ptr(void ***dest, size_t *dest_size, void *src) +{ + void **temp; + + assert(dest != NULL); + + temp = (void **) rrd_realloc(*dest, (*dest_size+1) * sizeof(*dest)); + if (!temp) + return 0; + + *dest = temp; + temp[*dest_size] = src; + (*dest_size)++; + + return 1; +} + +/* like rrd_add_ptr, but calls strdup() on a string first. */ +int rrd_add_strdup(char ***dest, size_t *dest_size, char *src) +{ + char *dup_src; + int add_ok; + + assert(dest != NULL); + assert(src != NULL); + + dup_src = strdup(src); + if (!dup_src) + return 0; + + add_ok = rrd_add_ptr((void ***)dest, dest_size, (void *)dup_src); + if (!add_ok) + free(dup_src); + + return add_ok; +} + +void rrd_free_ptrs(void ***src, size_t *cnt) +{ + void **sp; + + assert(src != NULL); + sp = *src; + + if (sp == NULL) + return; + + while (*cnt > 0) { + (*cnt)--; + free(sp[*cnt]); + } + + free (sp); + *src = NULL; +}