Set value to SN_EMPTY_SLOT if flags is SN_EMPTY_SLOT (#13417)
* set value to SN_EMPTY_SLOT if flags is SN_EMPTY_SLOT * SN_EMPTY_SLOT should be SN_ANOMALOUS_ZERO * added the const attribute to pack_storage_number() * tier1 uses floats * zero should not be empty slot * add unlikely * rename all SN flags to be more meaningful * proper check for zero double value * properly check if pages are full with empty points Co-authored-by: Costa Tsaousis <costa@netdata.cloud>
Emmanuel Vasilakis committed
Jul 26, 2022 at 11:37 UTC
98e77284cbcd2fdb001302525db3f1dfe4af9389
8 files changed
+133
-79
database/engine/rrdengine.c
+38
-2
@@ -235,6 +235,43 @@ void read_cached_extent_cb(struct rrdengine_worker_config* wc, unsigned idx, str
235
freez(xt_io_descr);
236
}
237
238
+static void fill_page_with_nulls(void *page, uint32_t page_length, uint8_t type) {
239
+ switch(type) {
240
+ case PAGE_METRICS: {
241
+ storage_number n = pack_storage_number(NAN, SN_FLAG_NONE);
242
+ storage_number *array = (storage_number *)page;
243
+ size_t slots = page_length / sizeof(n);
244
+ for(size_t i = 0; i < slots ; i++)
245
+ array[i] = n;
246
+ }
247
+ break;
248
+
249
+ case PAGE_TIER: {
250
+ storage_number_tier1_t n = {
251
+ .min_value = NAN,
252
+ .max_value = NAN,
253
+ .sum_value = NAN,
254
+ .count = 1,
255
+ .anomaly_count = 0,
256
+ };
257
+ storage_number_tier1_t *array = (storage_number_tier1_t *)page;
258
+ size_t slots = page_length / sizeof(n);
259
+ for(size_t i = 0; i < slots ; i++)
260
+ array[i] = n;
261
+ }
262
+ break;
263
+
264
+ default: {
265
+ static bool logged = false;
266
+ if(!logged) {
267
+ error("DBENGINE: cannot fill page with nulls on unknown page type id %d", type);
268
+ logged = true;
269
+ }
270
+ memset(page, 0, page_length);
271
+ }
272
+ }
273
+}
274
+
275
void read_extent_cb(uv_fs_t* req)
276
{
277
struct rrdengine_worker_config* wc = req->loop->data;
@@ -359,8 +396,7 @@ after_crc_check:
396
397
/* care, we don't hold the descriptor mutex */
398
if (have_read_error) {
362
- /* Applications should make sure NULL values match 0 as does SN_EMPTY_SLOT */
363
- memset(page, SN_EMPTY_SLOT, descr->page_length);
399
+ fill_page_with_nulls(page, descr->page_length, descr->type);
400
} else if (RRD_NO_COMPRESSION == header->compression_algorithm) {
401
(void) memcpy(page, xt_io_descr->buf + payload_offset + page_offset, descr->page_length);
402
} else {
database/engine/rrdengineapi.c
+35
-13
@@ -177,18 +177,38 @@ STORAGE_COLLECT_HANDLE *rrdeng_store_metric_init(STORAGE_METRIC_HANDLE *db_metri
177
/* The page must be populated and referenced */
178
static int page_has_only_empty_metrics(struct rrdeng_page_descr *descr)
179
{
180
- unsigned i;
181
- uint8_t has_only_empty_metrics = 1;
182
- storage_number *page;
180
+ switch(descr->type) {
181
+ case PAGE_METRICS: {
182
+ size_t slots = descr->page_length / PAGE_POINT_SIZE_BYTES(descr);
183
+ storage_number *array = (storage_number *)descr->pg_cache_descr->page;
184
+ for (size_t i = 0 ; i < slots; ++i) {
185
+ if(does_storage_number_exist(array[i]))
186
+ return 0;
187
+ }
188
+ }
189
+ break;
190
184
- page = descr->pg_cache_descr->page;
185
- for (i = 0 ; i < descr->page_length / PAGE_POINT_SIZE_BYTES(descr); ++i) {
186
- if (SN_EMPTY_SLOT != page[i]) {
187
- has_only_empty_metrics = 0;
188
- break;
191
+ case PAGE_TIER: {
192
+ size_t slots = descr->page_length / PAGE_POINT_SIZE_BYTES(descr);
193
+ storage_number_tier1_t *array = (storage_number_tier1_t *)descr->pg_cache_descr->page;
194
+ for (size_t i = 0 ; i < slots; ++i) {
195
+ if(fpclassify(array[i].sum_value) != FP_NAN)
196
+ return 0;
197
+ }
198
+ }
199
+ break;
200
+
201
+ default: {
202
+ static bool logged = false;
203
+ if(!logged) {
204
+ error("DBENGINE: cannot check page for nulls on unknown page type id %d", descr->type);
205
+ logged = true;
206
+ }
207
+ return 0;
208
}
209
}
191
- return has_only_empty_metrics;
210
+
211
+ return 1;
212
}
213
214
void rrdeng_store_metric_flush_current_page(STORAGE_COLLECT_HANDLE *collection_handle) {
@@ -222,7 +242,9 @@ void rrdeng_store_metric_flush_current_page(STORAGE_COLLECT_HANDLE *collection_h
242
handle->descr = NULL;
243
}
244
225
-void rrdeng_store_metric_next(STORAGE_COLLECT_HANDLE *collection_handle, usec_t point_in_time, NETDATA_DOUBLE n,
245
+void rrdeng_store_metric_next(STORAGE_COLLECT_HANDLE *collection_handle,
246
+ usec_t point_in_time,
247
+ NETDATA_DOUBLE n,
248
NETDATA_DOUBLE min_value,
249
NETDATA_DOUBLE max_value,
250
uint16_t count,
@@ -516,15 +538,15 @@ STORAGE_POINT rrdeng_load_metric_next(struct rrddim_query_handle *rrdimm_handle)
538
case PAGE_METRICS: {
539
storage_number n = handle->page[position];
540
sp.min = sp.max = sp.sum = unpack_storage_number(n);
519
- sp.flags = n & SN_ALL_FLAGS;
541
+ sp.flags = n & SN_USER_FLAGS;
542
sp.count = 1;
521
- sp.anomaly_count = (n & SN_ANOMALY_BIT) ? 0 : 1;
543
+ sp.anomaly_count = is_storage_number_anomalous(n) ? 1 : 0;
544
}
545
break;
546
547
case PAGE_TIER: {
548
tier1_value = ((storage_number_tier1_t *)handle->page)[position];
527
- sp.flags = tier1_value.anomaly_count ? 0 : SN_ANOMALY_BIT;
549
+ sp.flags = tier1_value.anomaly_count ? SN_FLAG_NONE : SN_FLAG_NOT_ANOMALOUS;
550
sp.count = tier1_value.count;
551
sp.anomaly_count = tier1_value.anomaly_count;
552
sp.min = tier1_value.min_value;
database/ram/rrddim_mem.c
+3
-3
@@ -15,7 +15,7 @@ void rrddim_metric_free(STORAGE_METRIC_HANDLE *db_metric_handle __maybe_unused)
15
16
STORAGE_COLLECT_HANDLE *rrddim_collect_init(STORAGE_METRIC_HANDLE *db_metric_handle) {
17
RRDDIM *rd = (RRDDIM *)db_metric_handle;
18
- rd->db[rd->rrdset->current_entry] = SN_EMPTY_SLOT;
18
+ rd->db[rd->rrdset->current_entry] = pack_storage_number(NAN, SN_FLAG_NONE);
19
struct mem_collect_handle *ch = calloc(1, sizeof(struct mem_collect_handle));
20
ch->rd = rd;
21
return (STORAGE_COLLECT_HANDLE *)ch;
@@ -191,8 +191,8 @@ STORAGE_POINT rrddim_query_next_metric(struct rrddim_query_handle *handle) {
191
h->slot = slot;
192
h->slot_timestamp += h->dt;
193
194
- sp.anomaly_count = (n & SN_ANOMALY_BIT) ? 0 : 1;
195
- sp.flags = (n & SN_ALL_FLAGS);
194
+ sp.anomaly_count = is_storage_number_anomalous(n) ? 1 : 0;
195
+ sp.flags = (n & SN_USER_FLAGS);
196
sp.min = sp.max = sp.sum = unpack_storage_number(n);
197
198
return sp;
database/rrd.h
+2
-2
@@ -378,7 +378,7 @@ typedef struct storage_point {
378
(x).min = (x).max = (x).sum = NAN; \
379
(x).count = 0; \
380
(x).anomaly_count = 0; \
381
- (x).flags = SN_EMPTY_SLOT; \
381
+ (x).flags = SN_FLAG_NONE; \
382
(x).start_time = 0; \
383
(x).end_time = 0; \
384
} while(0)
@@ -387,7 +387,7 @@ typedef struct storage_point {
387
(x).min = (x).max = (x).sum = NAN; \
388
(x).count = 1; \
389
(x).anomaly_count = 0; \
390
- (x).flags = SN_EMPTY_SLOT; \
390
+ (x).flags = SN_FLAG_NONE; \
391
(x).start_time = start_t; \
392
(x).end_time = end_t; \
393
} while(0)
database/rrdset.c
+9
-15
@@ -1041,8 +1041,7 @@ void store_metric_at_tier(RRDDIM *rd, struct rrddim_tier *t, STORAGE_POINT sp, u
1041
NAN,
1042
NAN,
1043
0,
1044
- 0,
1045
- SN_EMPTY_SLOT);
1044
+ 0, SN_FLAG_NONE);
1045
}
1046
1047
t->virtual_point.count = 0;
@@ -1075,7 +1074,7 @@ static void store_metric(RRDDIM *rd, usec_t point_end_time_ut, NETDATA_DOUBLE n,
1074
.max = n,
1075
.sum = n,
1076
.count = 1,
1078
- .anomaly_count = (flags & SN_ANOMALY_BIT) ? 0 : 1,
1077
+ .anomaly_count = (flags & SN_FLAG_NOT_ANOMALOUS) ? 0 : 1,
1078
.flags = flags
1079
};
1080
@@ -1110,7 +1109,7 @@ static inline size_t rrdset_done_interpolate(
1109
SN_FLAGS storage_flags = SN_DEFAULT_FLAGS;
1110
1111
if (has_reset_value)
1113
- storage_flags |= SN_EXISTS_RESET;
1112
+ storage_flags |= SN_FLAG_RESET;
1113
1114
for( ; next_store_ut <= now_collect_ut ; last_collect_ut = next_store_ut, next_store_ut += update_every_ut, iterations-- ) {
1115
@@ -1207,8 +1206,7 @@ static inline size_t rrdset_done_interpolate(
1206
1207
if(unlikely(!store_this_entry)) {
1208
(void) ml_is_anomalous(rd, 0, false);
1210
-// rd->state->collect_ops.store_metric(rd, next_store_ut, NAN, 0, 0, 1, SN_EMPTY_SLOT, 0);
1211
- store_metric(rd, next_store_ut, NAN, SN_EMPTY_SLOT);
1209
+ store_metric(rd, next_store_ut, NAN, SN_FLAG_NONE);
1210
continue;
1211
}
1212
@@ -1217,10 +1215,9 @@ static inline size_t rrdset_done_interpolate(
1215
1216
if (ml_is_anomalous(rd, new_value, true)) {
1217
// clear anomaly bit: 0 -> is anomalous, 1 -> not anomalous
1220
- dim_storage_flags &= ~ ((uint32_t) SN_ANOMALY_BIT);
1218
+ dim_storage_flags &= ~((storage_number)SN_FLAG_NOT_ANOMALOUS);
1219
}
1220
1223
-// rd->state->collect_ops.store_metric(rd, next_store_ut, new_value, 0, 0, 1, dim_storage_flags, 0);
1221
store_metric(rd, next_store_ut, new_value, dim_storage_flags);
1222
rd->last_stored_value = new_value;
1223
}
@@ -1228,19 +1225,16 @@ static inline size_t rrdset_done_interpolate(
1225
(void) ml_is_anomalous(rd, 0, false);
1226
1227
#ifdef NETDATA_INTERNAL_CHECKS
1231
- rrdset_debug(st, "%s: STORE[%ld] = NON EXISTING "
1232
- , rd->name
1233
- , current_entry
1234
- );
1228
+ rrdset_debug(st, "%s: STORE[%ld] = NON EXISTING ", rd->name, current_entry);
1229
#endif
1230
1237
-// rd->state->collect_ops.store_metric(rd, next_store_ut, NAN, 0, 0, 1, SN_EMPTY_SLOT, 0);
1238
- store_metric(rd, next_store_ut, NAN, SN_EMPTY_SLOT);
1231
+ store_metric(rd, next_store_ut, NAN, SN_FLAG_NONE);
1232
rd->last_stored_value = NAN;
1233
}
1234
1235
stored_entries++;
1236
}
1237
+
1238
// reset the storage flags for the next point, if any;
1239
storage_flags = SN_DEFAULT_FLAGS;
1240
@@ -1277,7 +1271,7 @@ static inline void rrdset_done_fill_the_gap(RRDSET *st) {
1271
long current_entry = st->current_entry;
1272
1273
for(c = 0; c < entries && next_store_ut <= now_collect_ut ; next_store_ut += update_every_ut, c++) {
1280
- rd->db[current_entry] = SN_EMPTY_SLOT;
1274
+ rd->db[current_entry] = pack_storage_number(NAN, SN_FLAG_NONE);
1275
current_entry = ((current_entry + 1) >= entries) ? 0 : current_entry + 1;
1276
1277
#ifdef NETDATA_INTERNAL_CHECKS
libnetdata/storage_number/storage_number.c
+16
-19
@@ -11,12 +11,13 @@ storage_number pack_storage_number(NETDATA_DOUBLE value, SN_FLAGS flags) {
11
// bit 25 SN_ANOMALY_BIT = 0: anomalous, 1: not anomalous
12
// bit 24 to bit 1 = the value
13
14
- storage_number r = flags & SN_ALL_FLAGS;
14
+ if(unlikely(fpclassify(value) == FP_NAN || fpclassify(value) == FP_INFINITE))
15
+ return SN_EMPTY_SLOT;
16
16
- // The isnormal() macro shall determine whether its argument value
17
- // is normal (neither zero, subnormal, infinite, nor NaN).
18
- if(unlikely(!isnormal(value)))
19
- goto RET_SN;
17
+ storage_number r = flags & SN_USER_FLAGS;
18
+
19
+ if(unlikely(fpclassify(value) == FP_ZERO || fpclassify(value) == FP_SUBNORMAL))
20
+ return r;
21
22
int m = 0;
23
NETDATA_DOUBLE n = value, factor = 10;
@@ -24,13 +25,13 @@ storage_number pack_storage_number(NETDATA_DOUBLE value, SN_FLAGS flags) {
25
// if the value is negative
26
// add the sign bit and make it positive
27
if(n < 0) {
27
- r += (1 << 31); // the sign bit 32
28
+ r += SN_FLAG_NEGATIVE; // the sign bit 32
29
n = -n;
30
}
31
32
if(n / 10000000.0 > 0x00ffffff) {
33
factor = 100;
33
- r |= SN_EXISTS_100;
34
+ r |= SN_FLAG_NOT_EXISTS_MUL100;
35
}
36
37
// make its integer part fit in 0x00ffffff
@@ -42,16 +43,16 @@ storage_number pack_storage_number(NETDATA_DOUBLE value, SN_FLAGS flags) {
43
}
44
45
if(m) {
45
- // the value was too big and we divided it
46
- // so we add a multiplier to unpack it
47
- r += (1 << 30) + (m << 27); // the multiplier m
46
+ // the value was too big, and we divided it
47
+ // so, we add a multiplier to unpack it
48
+ r += SN_FLAG_MULTIPLY + (m << 27); // the multiplier m
49
50
if(n > (NETDATA_DOUBLE)0x00ffffff) {
51
#ifdef NETDATA_INTERNAL_CHECKS
52
error("Number " NETDATA_DOUBLE_FORMAT " is too big.", value);
53
#endif
54
r += 0x00ffffff;
54
- goto RET_SN;
55
+ return r;
56
}
57
}
58
else {
@@ -65,13 +66,13 @@ storage_number pack_storage_number(NETDATA_DOUBLE value, SN_FLAGS flags) {
66
m++;
67
}
68
68
- if (unlikely(n > (NETDATA_DOUBLE) (0x00ffffff))) {
69
+ if (unlikely(n > (NETDATA_DOUBLE)0x00ffffff)) {
70
n /= 10;
71
m--;
72
}
72
- // the value was small enough and we multiplied it
73
- // so we add a divider to unpack it
74
- r += (0 << 30) + (m << 27); // the divider m
73
+ // the value was small enough, and we multiplied it
74
+ // so, we add a divider to unpack it
75
+ r += (m << 27); // the divider m
76
}
77
78
#ifdef STORAGE_WITH_MATH
@@ -82,10 +83,6 @@ storage_number pack_storage_number(NETDATA_DOUBLE value, SN_FLAGS flags) {
83
r += (storage_number)n;
84
#endif
85
85
-RET_SN:
86
- if (r == SN_EMPTY_SLOT)
87
- r = SN_ANOMALOUS_ZERO;
88
-
86
return r;
87
}
88
libnetdata/storage_number/storage_number.h
+26
-21
@@ -75,37 +75,42 @@ typedef struct storage_number_tier1 {
75
#define STORAGE_NUMBER_FORMAT "%u"
76
77
typedef enum {
78
- SN_ANOMALY_BIT = (1 << 24), // the anomaly bit of the value
79
- SN_EXISTS_RESET = (1 << 25), // the value has been overflown
80
- SN_EXISTS_100 = (1 << 26) // very large value (multiplier is 100 instead of 10)
78
+ SN_FLAG_NONE = 0,
79
+ SN_FLAG_NOT_ANOMALOUS = (1 << 24), // the anomaly bit of the value (0:anomalous, 1:not anomalous)
80
+ SN_FLAG_RESET = (1 << 25), // the value has been overflown
81
+ SN_FLAG_NOT_EXISTS_MUL100 = (1 << 26), // very large value (multiplier is 100 instead of 10)
82
+ SN_FLAG_MULTIPLY = (1 << 30), // multiply, else divide
83
+ SN_FLAG_NEGATIVE = (1 << 31), // negative, else positive
84
} SN_FLAGS;
85
83
-#define SN_ALL_FLAGS (SN_ANOMALY_BIT|SN_EXISTS_RESET|SN_EXISTS_100)
86
+#define SN_USER_FLAGS (SN_FLAG_NOT_ANOMALOUS | SN_FLAG_RESET)
87
85
-#define SN_EMPTY_SLOT 0x00000000
86
-#define SN_DEFAULT_FLAGS SN_ANOMALY_BIT
88
+// default flags for all storage numbers
89
+// anomaly bit is reversed, so we set it by default
90
+#define SN_DEFAULT_FLAGS SN_FLAG_NOT_ANOMALOUS
91
92
// When the calculated number is zero and the value is anomalous (ie. it's bit
93
// is zero) we want to return a storage_number representation that is
94
// different from the empty slot. We achieve this by mapping zero to
95
// SN_EXISTS_100. Unpacking the SN_EXISTS_100 value will return zero because
96
// its fraction field (as well as its exponent factor field) will be zero.
93
-#define SN_ANOMALOUS_ZERO SN_EXISTS_100
97
+#define SN_EMPTY_SLOT SN_FLAG_NOT_EXISTS_MUL100
98
99
// checks
96
-#define does_storage_number_exist(value) (((storage_number) (value)) != SN_EMPTY_SLOT)
97
-#define did_storage_number_reset(value) ((((storage_number) (value)) & SN_EXISTS_RESET) != 0)
100
+#define does_storage_number_exist(value) (((storage_number)(value)) != SN_EMPTY_SLOT)
101
+#define did_storage_number_reset(value) ((((storage_number)(value)) & SN_FLAG_RESET))
102
+#define is_storage_number_anomalous(value) (does_storage_number_exist(value) && !(((storage_number)(value)) & SN_FLAG_NOT_ANOMALOUS))
103
99
-storage_number pack_storage_number(NETDATA_DOUBLE value, SN_FLAGS flags);
104
+storage_number pack_storage_number(NETDATA_DOUBLE value, SN_FLAGS flags) __attribute__((const));
105
static inline NETDATA_DOUBLE unpack_storage_number(storage_number value) __attribute__((const));
106
107
int print_netdata_double(char *str, NETDATA_DOUBLE value);
108
104
-// sign div/mul <--- multiplier / divider ---> 10/100 RESET EXISTS VALUE
105
-#define STORAGE_NUMBER_POSITIVE_MAX_RAW (storage_number)( (0 << 31) | (1 << 30) | (1 << 29) | (1 << 28) | (1<<27) | (1 << 26) | (0 << 25) | (1 << 24) | 0x00ffffff )
106
-#define STORAGE_NUMBER_POSITIVE_MIN_RAW (storage_number)( (0 << 31) | (0 << 30) | (1 << 29) | (1 << 28) | (1<<27) | (0 << 26) | (0 << 25) | (1 << 24) | 0x00000001 )
107
-#define STORAGE_NUMBER_NEGATIVE_MAX_RAW (storage_number)( (1 << 31) | (0 << 30) | (1 << 29) | (1 << 28) | (1<<27) | (0 << 26) | (0 << 25) | (1 << 24) | 0x00000001 )
108
-#define STORAGE_NUMBER_NEGATIVE_MIN_RAW (storage_number)( (1 << 31) | (1 << 30) | (1 << 29) | (1 << 28) | (1<<27) | (1 << 26) | (0 << 25) | (1 << 24) | 0x00ffffff )
109
+// sign div/mul <--- multiplier / divider ---> 10/100 RESET EXISTS VALUE
110
+#define STORAGE_NUMBER_POSITIVE_MAX_RAW (storage_number)( (0 << 31) | (1 << 30) | (1 << 29) | (1 << 28) | (1 << 27) | (1 << 26) | (0 << 25) | (1 << 24) | 0x00ffffff )
111
+#define STORAGE_NUMBER_POSITIVE_MIN_RAW (storage_number)( (0 << 31) | (0 << 30) | (1 << 29) | (1 << 28) | (1 << 27) | (0 << 26) | (0 << 25) | (1 << 24) | 0x00000001 )
112
+#define STORAGE_NUMBER_NEGATIVE_MAX_RAW (storage_number)( (1 << 31) | (0 << 30) | (1 << 29) | (1 << 28) | (1 << 27) | (0 << 26) | (0 << 25) | (1 << 24) | 0x00000001 )
113
+#define STORAGE_NUMBER_NEGATIVE_MIN_RAW (storage_number)( (1 << 31) | (1 << 30) | (1 << 29) | (1 << 28) | (1 << 27) | (1 << 26) | (0 << 25) | (1 << 24) | 0x00ffffff )
114
115
// accepted accuracy loss
116
#define ACCURACY_LOSS_ACCEPTED_PERCENT 0.0001
@@ -126,19 +131,19 @@ static inline NETDATA_DOUBLE unpack_storage_number(storage_number value) {
131
int factor = 0;
132
133
// bit 32 = 0:positive, 1:negative
129
- if(unlikely(value & (1 << 31)))
134
+ if(unlikely(value & SN_FLAG_NEGATIVE))
135
sign = -1;
136
137
// bit 31 = 0:divide, 1:multiply
133
- if(unlikely(value & (1 << 30)))
138
+ if(unlikely(value & SN_FLAG_MULTIPLY))
139
exp = 1;
140
136
- // bit 27 SN_EXISTS_100
137
- if(unlikely(value & (1 << 26)))
141
+ // bit 27 SN_FLAG_NOT_EXISTS_MUL100
142
+ if(unlikely(value & SN_FLAG_NOT_EXISTS_MUL100))
143
factor = 1;
144
140
- // bit 26 SN_EXISTS_RESET
141
- // bit 25 SN_ANOMALY_BIT
145
+ // bit 26 SN_FLAG_RESET
146
+ // bit 25 SN_FLAG_NOT_ANOMALOUS
147
148
// bit 30, 29, 28 = (multiplier or divider) 0-7 (8 total)
149
int mul = (int)((value & ((1<<29)|(1<<28)|(1<<27))) >> 27);
web/api/queries/query.c
+4
-4
@@ -579,7 +579,7 @@ QUERY_POINT QUERY_POINT_EMPTY = {
579
.start_time = 0,
580
.value = NAN,
581
.anomaly = 0,
582
- .flags = SN_EMPTY_SLOT,
582
+ .flags = SN_FLAG_NONE,
583
#ifdef NETDATA_INTERNAL_CHECKS
584
.id = 0,
585
#endif
@@ -823,10 +823,10 @@ static void query_plan(QUERY_ENGINE_OPS *ops, time_t after_wanted, time_t before
823
824
#define query_add_point_to_group(r, point, ops) do { \
825
if(likely(netdata_double_isnumber((point).value))) { \
826
- if(likely((point).value != 0.0)) \
826
+ if(likely(fpclassify((point).value) != FP_ZERO)) \
827
(ops).group_points_non_zero++; \
828
\
829
- if(unlikely((point).flags & SN_EXISTS_RESET)) \
829
+ if(unlikely((point).flags & SN_FLAG_RESET)) \
830
(ops).group_value_flags |= RRDR_VALUE_RESET; \
831
\
832
(ops).grouping_add(r, (point).value); \
@@ -942,7 +942,7 @@ static inline void rrd2rrdr_do_dimension(
942
}
943
else {
944
new_point.value = NAN;
945
- new_point.flags = SN_EMPTY_SLOT;
945
+ new_point.flags = SN_FLAG_NONE;
946
}
947
}
948