X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fdaemon%2Futils_cache.c;h=0caf22c550304fa49bd20f95548d418c35da825b;hb=464c89681dae3bdf9b30470469161da6ac5aeb37;hp=530bdbb105fb190e1284797b61400dfe135990cd;hpb=79963d13c1884d1d92667cc502ad20758b084a12;p=collectd.git diff --git a/src/daemon/utils_cache.c b/src/daemon/utils_cache.c index 530bdbb1..0caf22c5 100644 --- a/src/daemon/utils_cache.c +++ b/src/daemon/utils_cache.c @@ -222,74 +222,50 @@ int uc_init(void) { } /* int uc_init */ int uc_check_timeout(void) { - cdtime_t now; - cache_entry_t *ce; - - char **keys = NULL; - cdtime_t *keys_time = NULL; - cdtime_t *keys_interval = NULL; - int keys_len = 0; - - char *key; - c_avl_iterator_t *iter; + cdtime_t now = cdtime(); - int status; + struct { + char *key; + cdtime_t time; + cdtime_t interval; + } *expired = NULL; + size_t expired_num = 0; pthread_mutex_lock(&cache_lock); - now = cdtime(); - /* Build a list of entries to be flushed */ - iter = c_avl_get_iterator(cache_tree); + c_avl_iterator_t *iter = c_avl_get_iterator(cache_tree); + char *key = NULL; + cache_entry_t *ce = NULL; while (c_avl_iterator_next(iter, (void *)&key, (void *)&ce) == 0) { - char **tmp; - cdtime_t *tmp_time; - /* If the entry is fresh enough, continue. */ if ((now - ce->last_update) < (ce->interval * timeout_g)) continue; - /* If entry has not been updated, add to `keys' array */ - tmp = realloc((void *)keys, (keys_len + 1) * sizeof(char *)); + void *tmp = realloc(expired, (expired_num + 1) * sizeof(*expired)); if (tmp == NULL) { ERROR("uc_check_timeout: realloc failed."); continue; } - keys = tmp; - - tmp_time = realloc(keys_time, (keys_len + 1) * sizeof(*keys_time)); - if (tmp_time == NULL) { - ERROR("uc_check_timeout: realloc failed."); - continue; - } - keys_time = tmp_time; + expired = tmp; - tmp_time = realloc(keys_interval, (keys_len + 1) * sizeof(*keys_interval)); - if (tmp_time == NULL) { - ERROR("uc_check_timeout: realloc failed."); - continue; - } - keys_interval = tmp_time; + expired[expired_num].key = strdup(key); + expired[expired_num].time = ce->last_time; + expired[expired_num].interval = ce->interval; - keys[keys_len] = strdup(key); - if (keys[keys_len] == NULL) { + if (expired[expired_num].key == NULL) { ERROR("uc_check_timeout: strdup failed."); continue; } - keys_time[keys_len] = ce->last_time; - keys_interval[keys_len] = ce->interval; - keys_len++; + expired_num++; } /* while (c_avl_iterator_next) */ c_avl_iterator_destroy(iter); pthread_mutex_unlock(&cache_lock); - if (keys_len == 0) { - /* realloc() may have been called for these. */ - sfree(keys); - sfree(keys_time); - sfree(keys_interval); + if (expired_num == 0) { + sfree(expired); return (0); } @@ -298,50 +274,42 @@ int uc_check_timeout(void) { * including plugin specific meta data, rates, history, …. This must be done * without holding the lock, otherwise we will run into a deadlock if a * plugin calls the cache interface. */ - for (int i = 0; i < keys_len; i++) { - value_list_t vl = VALUE_LIST_INIT; - - vl.values = NULL; - vl.values_len = 0; - vl.meta = NULL; - - status = parse_identifier_vl(keys[i], &vl); - if (status != 0) { - ERROR("uc_check_timeout: parse_identifier_vl (\"%s\") failed.", keys[i]); + for (size_t i = 0; i < expired_num; i++) { + value_list_t vl = { + .time = expired[i].time, .interval = expired[i].interval, + }; + + if (parse_identifier_vl(expired[i].key, &vl) != 0) { + ERROR("uc_check_timeout: parse_identifier_vl (\"%s\") failed.", + expired[i].key); continue; } - vl.time = keys_time[i]; - vl.interval = keys_interval[i]; - plugin_dispatch_missing(&vl); - } /* for (i = 0; i < keys_len; i++) */ + } /* for (i = 0; i < expired_num; i++) */ /* Now actually remove all the values from the cache. We don't re-evaluate * the timestamp again, so in theory it is possible we remove a value after * it is updated here. */ pthread_mutex_lock(&cache_lock); - for (int i = 0; i < keys_len; i++) { - key = NULL; - ce = NULL; - - status = c_avl_remove(cache_tree, keys[i], (void *)&key, (void *)&ce); - if (status != 0) { - ERROR("uc_check_timeout: c_avl_remove (\"%s\") failed.", keys[i]); - sfree(keys[i]); + for (size_t i = 0; i < expired_num; i++) { + char *key = NULL; + cache_entry_t *value = NULL; + + if (c_avl_remove(cache_tree, expired[i].key, (void *)&key, + (void *)&value) != 0) { + ERROR("uc_check_timeout: c_avl_remove (\"%s\") failed.", expired[i].key); + sfree(expired[i].key); continue; } - - sfree(keys[i]); sfree(key); - cache_free(ce); - } /* for (i = 0; i < keys_len; i++) */ - pthread_mutex_unlock(&cache_lock); + cache_free(value); - sfree(keys); - sfree(keys_time); - sfree(keys_interval); + sfree(expired[i].key); + } /* for (i = 0; i < expired_num; i++) */ + pthread_mutex_unlock(&cache_lock); + sfree(expired); return (0); } /* int uc_check_timeout */ @@ -970,5 +938,3 @@ int uc_meta_data_exists(const value_list_t *vl, const char *key, _Bool *value) UC_WRAP(meta_data_get_boolean) #undef UC_WRAP - - /* vim: set sw=2 ts=8 sts=2 tw=78 : */