X-Git-Url: https://arthur.barton.de/gitweb/?a=blobdiff_plain;f=src%2Frrd.c;h=28efff0a15074992287fba30a053c58eb9974da9;hb=fdb1257d906d5d08f41b75216130c4eb1ac9c837;hp=b9b20ee6a1866dab4e642d98b9c36c40ee015b4f;hpb=b475c58273d0f76e51ab43d30b5bc31249fdd0d7;p=netdata.git diff --git a/src/rrd.c b/src/rrd.c old mode 100755 new mode 100644 index b9b20ee6..28efff0a --- a/src/rrd.c +++ b/src/rrd.c @@ -18,6 +18,7 @@ #include "log.h" #include "appconfig.h" +#include "main.h" #include "rrd.h" #define RRD_DEFAULT_GAP_INTERPOLATIONS 1 @@ -42,35 +43,26 @@ int rrd_memory_mode = RRD_MEMORY_MODE_SAVE; // ---------------------------------------------------------------------------- // RRDSET index -static int rrdset_iterator(avl *a) { if(a) {}; return 0; } - static int rrdset_compare(void* a, void* b) { if(((RRDSET *)a)->hash < ((RRDSET *)b)->hash) return -1; else if(((RRDSET *)a)->hash > ((RRDSET *)b)->hash) return 1; else return strcmp(((RRDSET *)a)->id, ((RRDSET *)b)->id); } -avl_tree rrdset_root_index = { - NULL, - rrdset_compare, -#ifdef AVL_LOCK_WITH_MUTEX - PTHREAD_MUTEX_INITIALIZER -#else - PTHREAD_RWLOCK_INITIALIZER -#endif +avl_tree_lock rrdset_root_index = { + { NULL, rrdset_compare }, + AVL_LOCK_INITIALIZER }; -#define rrdset_index_add(st) avl_insert(&rrdset_root_index, (avl *)(st)) -#define rrdset_index_del(st) avl_remove(&rrdset_root_index, (avl *)(st)) +#define rrdset_index_add(st) avl_insert_lock(&rrdset_root_index, (avl *)(st)) +#define rrdset_index_del(st) avl_remove_lock(&rrdset_root_index, (avl *)(st)) static RRDSET *rrdset_index_find(const char *id, uint32_t hash) { - RRDSET *result = NULL, tmp; - strncpy(tmp.id, id, RRD_ID_LENGTH_MAX); - tmp.id[RRD_ID_LENGTH_MAX] = '\0'; + RRDSET tmp; + strncpyz(tmp.id, id, RRD_ID_LENGTH_MAX); tmp.hash = (hash)?hash:simple_hash(tmp.id); - avl_search(&(rrdset_root_index), (avl *)&tmp, rrdset_iterator, (avl **)&result); - return result; + return (RRDSET *)avl_search_lock(&(rrdset_root_index), (avl *) &tmp); } // ---------------------------------------------------------------------------- @@ -78,8 +70,6 @@ static RRDSET *rrdset_index_find(const char *id, uint32_t hash) { #define rrdset_from_avlname(avlname_ptr) ((RRDSET *)((avlname_ptr) - offsetof(RRDSET, avlname))) -static int rrdset_iterator_name(avl *a) { if(a) {}; return 0; } - static int rrdset_compare_name(void* a, void* b) { RRDSET *A = rrdset_from_avlname(a); RRDSET *B = rrdset_from_avlname(b); @@ -91,22 +81,17 @@ static int rrdset_compare_name(void* a, void* b) { else return strcmp(A->name, B->name); } -avl_tree rrdset_root_index_name = { - NULL, - rrdset_compare_name, -#ifdef AVL_LOCK_WITH_MUTEX - PTHREAD_MUTEX_INITIALIZER -#else - PTHREAD_RWLOCK_INITIALIZER -#endif +avl_tree_lock rrdset_root_index_name = { + { NULL, rrdset_compare_name }, + AVL_LOCK_INITIALIZER }; int rrdset_index_add_name(RRDSET *st) { // fprintf(stderr, "ADDING: %s (name: %s)\n", st->id, st->name); - return avl_insert(&rrdset_root_index_name, (avl *)(&st->avlname)); + return avl_insert_lock(&rrdset_root_index_name, (avl *) (&st->avlname)); } -#define rrdset_index_del_name(st) avl_remove(&rrdset_root_index_name, (avl *)(&st->avlname)) +#define rrdset_index_del_name(st) avl_remove_lock(&rrdset_root_index_name, (avl *)(&st->avlname)) static RRDSET *rrdset_index_find_name(const char *name, uint32_t hash) { void *result = NULL; @@ -115,7 +100,7 @@ static RRDSET *rrdset_index_find_name(const char *name, uint32_t hash) { tmp.hash_name = (hash)?hash:simple_hash(tmp.name); // fprintf(stderr, "SEARCHING: %s\n", name); - avl_search(&(rrdset_root_index_name), (avl *)(&(tmp.avlname)), rrdset_iterator_name, (avl **)&result); + result = avl_search_lock(&(rrdset_root_index_name), (avl *) (&(tmp.avlname))); if(result) { RRDSET *st = rrdset_from_avlname(result); if(strcmp(st->magic, RRDSET_MAGIC)) @@ -132,25 +117,21 @@ static RRDSET *rrdset_index_find_name(const char *name, uint32_t hash) { // ---------------------------------------------------------------------------- // RRDDIM index -static int rrddim_iterator(avl *a) { if(a) {}; return 0; } - static int rrddim_compare(void* a, void* b) { if(((RRDDIM *)a)->hash < ((RRDDIM *)b)->hash) return -1; else if(((RRDDIM *)a)->hash > ((RRDDIM *)b)->hash) return 1; else return strcmp(((RRDDIM *)a)->id, ((RRDDIM *)b)->id); } -#define rrddim_index_add(st, rd) avl_insert(&((st)->dimensions_index), (avl *)(rd)) -#define rrddim_index_del(st,rd ) avl_remove(&((st)->dimensions_index), (avl *)(rd)) +#define rrddim_index_add(st, rd) avl_insert_lock(&((st)->dimensions_index), (avl *)(rd)) +#define rrddim_index_del(st,rd ) avl_remove_lock(&((st)->dimensions_index), (avl *)(rd)) static RRDDIM *rrddim_index_find(RRDSET *st, const char *id, uint32_t hash) { - RRDDIM *result = NULL, tmp; - strncpy(tmp.id, id, RRD_ID_LENGTH_MAX); - tmp.id[RRD_ID_LENGTH_MAX] = '\0'; + RRDDIM tmp; + strncpyz(tmp.id, id, RRD_ID_LENGTH_MAX); tmp.hash = (hash)?hash:simple_hash(tmp.id); - avl_search(&(st->dimensions_index), (avl *)&tmp, rrddim_iterator, (avl **)&result); - return result; + return (RRDDIM *)avl_search_lock(&(st->dimensions_index), (avl *) &tmp); } // ---------------------------------------------------------------------------- @@ -222,8 +203,8 @@ int rrd_memory_mode_id(const char *name) int rrddim_algorithm_id(const char *name) { - if(strcmp(name, RRDDIM_ABSOLUTE_NAME) == 0) return RRDDIM_ABSOLUTE; if(strcmp(name, RRDDIM_INCREMENTAL_NAME) == 0) return RRDDIM_INCREMENTAL; + if(strcmp(name, RRDDIM_ABSOLUTE_NAME) == 0) return RRDDIM_ABSOLUTE; if(strcmp(name, RRDDIM_PCENT_OVER_ROW_TOTAL_NAME) == 0) return RRDDIM_PCENT_OVER_ROW_TOTAL; if(strcmp(name, RRDDIM_PCENT_OVER_DIFF_TOTAL_NAME) == 0) return RRDDIM_PCENT_OVER_DIFF_TOTAL; return RRDDIM_ABSOLUTE; @@ -255,15 +236,18 @@ const char *rrddim_algorithm_name(int chart_type) // ---------------------------------------------------------------------------- // chart names -char *rrdset_strncpy_name(char *to, const char *from, int length) +char *rrdset_strncpyz_name(char *to, const char *from, size_t length) { - int i; - for(i = 0; i < length && from[i] ;i++) { - if(from[i] == '.' || isalpha(from[i]) || isdigit(from[i])) to[i] = from[i]; - else to[i] = '_'; + char c, *p = to; + + while (length-- && (c = *from++)) { + if(c != '.' && !isalnum(c)) + c = '_'; + + *p++ = c; } - if(i < length) to[i] = '\0'; - to[length - 1] = '\0'; + + *p = '\0'; return to; } @@ -277,8 +261,8 @@ void rrdset_set_name(RRDSET *st, const char *name) char b[CONFIG_MAX_VALUE + 1]; char n[RRD_ID_LENGTH_MAX + 1]; - snprintf(n, RRD_ID_LENGTH_MAX, "%s.%s", st->type, name); - rrdset_strncpy_name(b, n, CONFIG_MAX_VALUE); + snprintfz(n, RRD_ID_LENGTH_MAX, "%s.%s", st->type, name); + rrdset_strncpyz_name(b, n, CONFIG_MAX_VALUE); st->name = config_get(st->id, "name", b); st->hash_name = simple_hash(st->name); @@ -297,9 +281,9 @@ char *rrdset_cache_dir(const char *id) char b[FILENAME_MAX + 1]; char n[FILENAME_MAX + 1]; - rrdset_strncpy_name(b, id, FILENAME_MAX); + rrdset_strncpyz_name(b, id, FILENAME_MAX); - snprintf(n, FILENAME_MAX, "%s/%s", cache_dir, b); + snprintfz(n, FILENAME_MAX, "%s/%s", cache_dir, b); ret = config_get(id, "cache directory", n); if(rrd_memory_mode == RRD_MEMORY_MODE_MAP || rrd_memory_mode == RRD_MEMORY_MODE_SAVE) { @@ -335,8 +319,13 @@ void rrdset_reset(RRDSET *st) } } -RRDSET *rrdset_create(const char *type, const char *id, const char *name, const char *family, const char *title, const char *units, long priority, int update_every, int chart_type) +RRDSET *rrdset_create(const char *type, const char *id, const char *name, const char *family, const char *context, const char *title, const char *units, long priority, int update_every, int chart_type) { + if(!type || !type[0]) { + fatal("Cannot create rrd stats without a type."); + return NULL; + } + if(!id || !id[0]) { fatal("Cannot create rrd stats without an id."); return NULL; @@ -346,7 +335,13 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const char fullfilename[FILENAME_MAX + 1]; RRDSET *st = NULL; - snprintf(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id); + snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id); + + st = rrdset_find(fullid); + if(st) { + error("Cannot create rrd stats for '%s', it already exists.", fullid); + return st; + } long entries = config_get_number(fullid, "history", rrd_default_history_entries); if(entries < 5) entries = config_set_number(fullid, "history", 5); @@ -360,7 +355,7 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const debug(D_RRD_CALLS, "Creating RRD_STATS for '%s.%s'.", type, id); - snprintf(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir); + snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir); if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) st = (RRDSET *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 0); if(st) { if(strcmp(st->magic, RRDSET_MAGIC) != 0) { @@ -396,6 +391,7 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const st->name = NULL; st->type = NULL; st->family = NULL; + st->context = NULL; st->title = NULL; st->units = NULL; st->dimensions = NULL; @@ -422,10 +418,11 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const st->cache_dir = cache_dir; - st->family = config_get(st->id, "family", family?family:st->id); - st->units = config_get(st->id, "units", units?units:""); - st->type = config_get(st->id, "type", type); st->chart_type = rrdset_type_id(config_get(st->id, "chart type", rrdset_type_name(chart_type))); + st->type = config_get(st->id, "type", type); + st->family = config_get(st->id, "family", family?family:st->type); + st->context = config_get(st->id, "context", context?context:st->id); + st->units = config_get(st->id, "units", units?units:""); st->priority = config_get_number(st->id, "priority", priority); st->enabled = enabled; @@ -440,7 +437,7 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const st->gap_when_lost_iterations_above = (int) ( config_get_number(st->id, "gap when lost iterations above", RRD_DEFAULT_GAP_INTERPOLATIONS) + 2); - avl_init(&st->dimensions_index, rrddim_compare); + avl_init_lock(&st->dimensions_index, rrddim_compare); pthread_rwlock_init(&st->rwlock, NULL); pthread_rwlock_wrlock(&rrdset_root_rwlock); @@ -450,7 +447,7 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const { char varvalue[CONFIG_MAX_VALUE + 1]; - snprintf(varvalue, CONFIG_MAX_VALUE, "%s (%s)", title?title:"", st->name); + snprintfz(varvalue, CONFIG_MAX_VALUE, "%s (%s)", title?title:"", st->name); st->title = config_get(st->id, "title", varvalue); } @@ -475,8 +472,8 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier debug(D_RRD_CALLS, "Adding dimension '%s/%s'.", st->id, id); - rrdset_strncpy_name(filename, id, FILENAME_MAX); - snprintf(fullfilename, FILENAME_MAX, "%s/%s.db", st->cache_dir, filename); + rrdset_strncpyz_name(filename, id, FILENAME_MAX); + snprintfz(fullfilename, FILENAME_MAX, "%s/%s.db", st->cache_dir, filename); if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) rd = (RRDDIM *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 1); if(rd) { struct timeval now; @@ -548,19 +545,19 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier strcpy(rd->magic, RRDDIMENSION_MAGIC); strcpy(rd->cache_filename, fullfilename); - strncpy(rd->id, id, RRD_ID_LENGTH_MAX); + strncpyz(rd->id, id, RRD_ID_LENGTH_MAX); rd->hash = simple_hash(rd->id); - snprintf(varname, CONFIG_MAX_NAME, "dim %s name", rd->id); + snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id); rd->name = config_get(st->id, varname, (name && *name)?name:rd->id); - snprintf(varname, CONFIG_MAX_NAME, "dim %s algorithm", rd->id); + snprintfz(varname, CONFIG_MAX_NAME, "dim %s algorithm", rd->id); rd->algorithm = rrddim_algorithm_id(config_get(st->id, varname, rrddim_algorithm_name(algorithm))); - snprintf(varname, CONFIG_MAX_NAME, "dim %s multiplier", rd->id); + snprintfz(varname, CONFIG_MAX_NAME, "dim %s multiplier", rd->id); rd->multiplier = config_get_number(st->id, varname, multiplier); - snprintf(varname, CONFIG_MAX_NAME, "dim %s divisor", rd->id); + snprintfz(varname, CONFIG_MAX_NAME, "dim %s divisor", rd->id); rd->divisor = config_get_number(st->id, varname, divisor); if(!rd->divisor) rd->divisor = 1; @@ -591,8 +588,8 @@ void rrddim_set_name(RRDSET *st, RRDDIM *rd, const char *name) debug(D_RRD_CALLS, "rrddim_set_name() %s.%s", st->name, rd->name); char varname[CONFIG_MAX_NAME + 1]; - snprintf(varname, CONFIG_MAX_NAME, "dim %s name", rd->id); - config_get(st->id, varname, name); + snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id); + config_set_default(st->id, varname, name); } void rrddim_free(RRDSET *st, RRDDIM *rd) @@ -665,9 +662,8 @@ void rrdset_free_all(void) info("Memory cleanup completed..."); } -void rrdset_save_all(void) -{ - debug(D_RRD_CALLS, "rrdset_save_all()"); +void rrdset_save_all(void) { + info("Saving database..."); RRDSET *st; RRDDIM *rd; @@ -708,12 +704,10 @@ RRDSET *rrdset_find_bytype(const char *type, const char *id) char buf[RRD_ID_LENGTH_MAX + 1]; - strncpy(buf, type, RRD_ID_LENGTH_MAX - 1); - buf[RRD_ID_LENGTH_MAX - 1] = '\0'; + strncpyz(buf, type, RRD_ID_LENGTH_MAX - 1); strcat(buf, "."); int len = (int) strlen(buf); - strncpy(&buf[len], id, (size_t) (RRD_ID_LENGTH_MAX - len)); - buf[RRD_ID_LENGTH_MAX] = '\0'; + strncpyz(&buf[len], id, (size_t) (RRD_ID_LENGTH_MAX - len)); return(rrdset_find(buf)); } @@ -817,11 +811,13 @@ void rrdset_next_plugins(RRDSET *st) unsigned long long rrdset_done(RRDSET *st) { + if(unlikely(netdata_exit)) return 0; + debug(D_RRD_CALLS, "rrdset_done() for chart %s", st->name); RRDDIM *rd, *last; - int oldstate, store_this_entry = 1, first_entry = 0, in_the_same_interpolation_point = 0; - unsigned long long last_ut, now_ut, next_ut; + int oldstate, store_this_entry = 1, first_entry = 0; + unsigned long long last_ut, now_ut, next_ut, stored_entries = 0; if(unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) != 0)) error("Cannot set pthread cancel state to DISABLE."); @@ -830,7 +826,8 @@ unsigned long long rrdset_done(RRDSET *st) pthread_rwlock_rdlock(&st->rwlock); // enable the chart, if it was disabled - st->enabled = 1; + if(unlikely(rrd_delete_unupdated_dimensions) && !st->enabled) + st->enabled = 1; // check if the chart has a long time to be updated if(unlikely(st->usec_since_last_update > st->entries * st->update_every * 1000000ULL)) { @@ -879,7 +876,7 @@ unsigned long long rrdset_done(RRDSET *st) // check if we will re-write the entire data set if(unlikely(usecdiff(&st->last_collected_time, &st->last_updated) > st->update_every * st->entries * 1000000ULL)) { - info("%s: too old data (last updated at %u.%u, last collected at %u.%u). Reseting it. Will not store the next entry.", st->name, st->last_updated.tv_sec, st->last_updated.tv_usec, st->last_collected_time.tv_sec, st->last_collected_time.tv_usec); + info("%s: too old data (last updated at %zu.%zu, last collected at %zu.%zu). Reseting it. Will not store the next entry.", st->name, st->last_updated.tv_sec, st->last_updated.tv_usec, st->last_collected_time.tv_sec, st->last_collected_time.tv_usec); rrdset_reset(st); st->usec_since_last_update = st->update_every * 1000000ULL; @@ -905,7 +902,6 @@ unsigned long long rrdset_done(RRDSET *st) if(unlikely(!first_entry && now_ut < next_ut)) { if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: THIS IS IN THE SAME INTERPOLATION POINT", st->name); - in_the_same_interpolation_point = 1; } if(unlikely(st->debug)) { @@ -1004,10 +1000,6 @@ unsigned long long rrdset_done(RRDSET *st) rd->last_collected_value = rd->collected_value; } - if(!in_the_same_interpolation_point) { - rd->last_calculated_value = rd->calculated_value; - } - rd->calculated_value = (calculated_number)(rd->collected_value - rd->last_collected_value) * (calculated_number)rd->multiplier / (calculated_number)rd->divisor; @@ -1041,10 +1033,6 @@ unsigned long long rrdset_done(RRDSET *st) * (calculated_number)(rd->collected_value - rd->last_collected_value) / (calculated_number)(st->collected_total - st->last_collected_total); - if(!in_the_same_interpolation_point) { - rd->last_calculated_value = rd->calculated_value; - } - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: CALC PCENT-DIFF " CALCULATED_NUMBER_FORMAT " = 100" @@ -1071,7 +1059,7 @@ unsigned long long rrdset_done(RRDSET *st) break; } - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: END " + if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: PHASE2 " " last_collected_value = " COLLECTED_NUMBER_FORMAT " collected_value = " COLLECTED_NUMBER_FORMAT " last_calculated_value = " CALCULATED_NUMBER_FORMAT @@ -1094,7 +1082,7 @@ unsigned long long rrdset_done(RRDSET *st) for( ; likely(next_ut <= now_ut) ; next_ut += st->update_every * 1000000ULL, iterations-- ) { #ifdef NETDATA_INTERNAL_CHECKS - if(iterations <= 0) { error("iterations calculation wrapped!"); } + if(iterations < 0) { error("%s: iterations calculation wrapped! first_ut = %llu, last_ut = %llu, next_ut = %llu, now_ut = %llu", st->name, first_ut, last_ut, next_ut, now_ut); } #endif if(unlikely(st->debug)) { @@ -1203,6 +1191,8 @@ unsigned long long rrdset_done(RRDSET *st) rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS); } + stored_entries++; + if(unlikely(st->debug)) { calculated_number t1 = new_value * (calculated_number)rd->multiplier / (calculated_number)rd->divisor; calculated_number t2 = unpack_storage_number(rd->values[st->current_entry]); @@ -1240,41 +1230,37 @@ unsigned long long rrdset_done(RRDSET *st) } // align next interpolation to last collection point - st->last_updated.tv_sec = st->last_collected_time.tv_sec; - st->last_updated.tv_usec = st->last_collected_time.tv_usec; + if(likely(stored_entries || !store_this_entry)) { + st->last_updated.tv_sec = st->last_collected_time.tv_sec; + st->last_updated.tv_usec = st->last_collected_time.tv_usec; + } for( rd = st->dimensions; likely(rd) ; rd = rd->next ) { if(unlikely(!rd->updated)) continue; - int is_incremental = 0; - if(rd->algorithm == RRDDIM_PCENT_OVER_DIFF_TOTAL || rd->algorithm == RRDDIM_INCREMENTAL) - is_incremental = 1; - - if((is_incremental && !in_the_same_interpolation_point) || !is_incremental || !store_this_entry) { + if(likely(stored_entries || !store_this_entry)) { if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: setting last_collected_value (old: " COLLECTED_NUMBER_FORMAT ") to last_collected_value (new: " COLLECTED_NUMBER_FORMAT ")", st->id, rd->name, rd->last_collected_value, rd->collected_value); rd->last_collected_value = rd->collected_value; if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: setting last_calculated_value (old: " CALCULATED_NUMBER_FORMAT ") to last_calculated_value (new: " CALCULATED_NUMBER_FORMAT ")", st->id, rd->name, rd->last_calculated_value, rd->calculated_value); rd->last_calculated_value = rd->calculated_value; } - else { - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: discarding calculated_value (old: " CALCULATED_NUMBER_FORMAT ") new: 0", st->id, rd->name, rd->calculated_value); - rd->calculated_value = 0; - } + rd->calculated_value = 0; rd->collected_value = 0; rd->updated = 0; - // if this is the first entry of incremental dimensions - // we have to set the first calculated_value to zero - // to eliminate the first spike - if(unlikely(st->counter_done == 1)) switch(rd->algorithm) { - case RRDDIM_PCENT_OVER_DIFF_TOTAL: - case RRDDIM_INCREMENTAL: - rd->calculated_value = 0; - // the next time, a new incremental total will be calculated - break; - } + if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: END " + " last_collected_value = " COLLECTED_NUMBER_FORMAT + " collected_value = " COLLECTED_NUMBER_FORMAT + " last_calculated_value = " CALCULATED_NUMBER_FORMAT + " calculated_value = " CALCULATED_NUMBER_FORMAT + , st->id, rd->name + , rd->last_collected_value + , rd->collected_value + , rd->last_calculated_value + , rd->calculated_value + ); } st->last_collected_total = st->collected_total;