master
h 153 lines 4.04 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #ifndef NETDATA_API_QUERY_COUNTIF_H
4 #define NETDATA_API_QUERY_COUNTIF_H
5
6 #include "../query.h"
7 #include "../rrdr.h"
8
9 enum tg_countif_cmp {
10 TG_COUNTIF_EQUAL,
11 TG_COUNTIF_NOTEQUAL,
12 TG_COUNTIF_LESS,
13 TG_COUNTIF_LESSEQUAL,
14 TG_COUNTIF_GREATER,
15 TG_COUNTIF_GREATEREQUAL,
16 };
17
18 struct tg_countif {
19 enum tg_countif_cmp comparison;
20 NETDATA_DOUBLE target;
21 size_t count;
22 size_t matched;
23 };
24
25 static inline void tg_countif_create(RRDR *r, const char *options __maybe_unused) {
26 struct tg_countif *g = onewayalloc_callocz(r->internal.owa, 1, sizeof(struct tg_countif));
27 r->time_grouping.data = g;
28
29 if(options && *options) {
30 // skip any leading spaces
31 while(isspace((uint8_t)*options)) options++;
32
33 // find the comparison function
34 switch(*options) {
35 case '!':
36 options++;
37 if(*options != '=' && *options != ':')
38 options--;
39 g->comparison = TG_COUNTIF_NOTEQUAL;
40 break;
41
42 case '>':
43 options++;
44 if(*options == '=' || *options == ':') {
45 g->comparison = TG_COUNTIF_GREATEREQUAL;
46 }
47 else {
48 options--;
49 g->comparison = TG_COUNTIF_GREATER;
50 }
51 break;
52
53 case '<':
54 options++;
55 if(*options == '>') {
56 g->comparison = TG_COUNTIF_NOTEQUAL;
57 }
58 else if(*options == '=' || *options == ':') {
59 g->comparison = TG_COUNTIF_LESSEQUAL;
60 }
61 else {
62 options--;
63 g->comparison = TG_COUNTIF_LESS;
64 }
65 break;
66
67 case '=':
68 if(options[1] == '=')
69 options++; // support ==, skip to second '='
70 g->comparison = TG_COUNTIF_EQUAL;
71 break;
72
73 default:
74 case ':':
75 g->comparison = TG_COUNTIF_EQUAL;
76 break;
77 }
78 if(*options) options++;
79
80 // skip everything up to the first digit
81 while(isspace((uint8_t)*options)) options++;
82
83 g->target = str2ndd(options, NULL);
84 }
85 else {
86 g->target = 0.0;
87 g->comparison = TG_COUNTIF_EQUAL;
88 }
89 }
90
91 // resets when switches dimensions
92 // so, clear everything to restart
93 static inline void tg_countif_reset(RRDR *r) {
94 struct tg_countif *g = (struct tg_countif *)r->time_grouping.data;
95 g->matched = 0;
96 g->count = 0;
97 }
98
99 static inline void tg_countif_free(RRDR *r) {
100 onewayalloc_freez(r->internal.owa, r->time_grouping.data);
101 r->time_grouping.data = NULL;
102 }
103
104 static inline void tg_countif_add(RRDR *r, NETDATA_DOUBLE value) {
105 struct tg_countif *g = (struct tg_countif *)r->time_grouping.data;
106 switch(g->comparison) {
107 case TG_COUNTIF_GREATER:
108 if(value > g->target) g->matched++;
109 break;
110
111 case TG_COUNTIF_GREATEREQUAL:
112 if(value >= g->target) g->matched++;
113 break;
114
115 case TG_COUNTIF_LESS:
116 if(value < g->target) g->matched++;
117 break;
118
119 case TG_COUNTIF_LESSEQUAL:
120 if(value <= g->target) g->matched++;
121 break;
122
123 case TG_COUNTIF_EQUAL:
124 if(value == g->target) g->matched++;
125 break;
126
127 case TG_COUNTIF_NOTEQUAL:
128 if(value != g->target) g->matched++;
129 break;
130 }
131 g->count++;
132 }
133
134 static inline NETDATA_DOUBLE tg_countif_flush(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) {
135 struct tg_countif *g = (struct tg_countif *)r->time_grouping.data;
136
137 NETDATA_DOUBLE value;
138
139 if(unlikely(!g->count)) {
140 value = 0.0;
141 *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY;
142 }
143 else {
144 value = (NETDATA_DOUBLE)g->matched * 100 / (NETDATA_DOUBLE)g->count;
145 }
146
147 g->matched = 0;
148 g->count = 0;
149
150 return value;
151 }
152
153 #endif //NETDATA_API_QUERY_COUNTIF_H