master
c 221 lines 7.56 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "rrdset.h"
4 #include "storage-engine.h"
5
6 void rrdset_metadata_updated(RRDSET *st) {
7 __atomic_add_fetch(&st->version, 1, __ATOMIC_RELAXED);
8 rrdcontext_updated_rrdset(st);
9 }
10
11 // ----------------------------------------------------------------------------
12
13 // get the timestamp of the last entry in the round-robin database
14 time_t rrdset_last_entry_s(RRDSET *st) {
15 RRDDIM *rd;
16 time_t last_entry_s = 0;
17
18 rrddim_foreach_read(rd, st) {
19 time_t t = rrddim_last_entry_s(rd);
20 if(t > last_entry_s) last_entry_s = t;
21 }
22 rrddim_foreach_done(rd);
23
24 return last_entry_s;
25 }
26
27 time_t rrdset_last_entry_s_of_tier(RRDSET *st, size_t tier) {
28 RRDDIM *rd;
29 time_t last_entry_s = 0;
30
31 rrddim_foreach_read(rd, st) {
32 time_t t = rrddim_last_entry_s_of_tier(rd, tier);
33 if(t > last_entry_s) last_entry_s = t;
34 }
35 rrddim_foreach_done(rd);
36
37 return last_entry_s;
38 }
39
40 // get the timestamp of first entry in the round-robin database
41 time_t rrdset_first_entry_s(RRDSET *st) {
42 RRDDIM *rd;
43 time_t first_entry_s = LONG_MAX;
44
45 rrddim_foreach_read(rd, st) {
46 time_t t = rrddim_first_entry_s(rd);
47 if(t < first_entry_s)
48 first_entry_s = t;
49 }
50 rrddim_foreach_done(rd);
51
52 if (unlikely(LONG_MAX == first_entry_s)) return 0;
53 return first_entry_s;
54 }
55
56 time_t rrdset_first_entry_s_of_tier(RRDSET *st, size_t tier) {
57 if(unlikely(tier >= nd_profile.storage_tiers))
58 return 0;
59
60 RRDDIM *rd;
61 time_t first_entry_s = LONG_MAX;
62
63 rrddim_foreach_read(rd, st) {
64 time_t t = rrddim_first_entry_s_of_tier(rd, tier);
65 if(t && t < first_entry_s)
66 first_entry_s = t;
67 }
68 rrddim_foreach_done(rd);
69
70 if (unlikely(LONG_MAX == first_entry_s)) return 0;
71 return first_entry_s;
72 }
73
74 void rrdset_get_retention_of_tier_for_collected_chart(RRDSET *st, time_t *first_time_s, time_t *last_time_s, time_t now_s, size_t tier) {
75 if(!now_s)
76 now_s = now_realtime_sec();
77
78 time_t db_first_entry_s = rrdset_first_entry_s_of_tier(st, tier);
79 time_t db_last_entry_s = st->last_updated.tv_sec; // we assume this is a collected RRDSET
80
81 if(unlikely(!db_last_entry_s)) {
82 db_last_entry_s = rrdset_last_entry_s_of_tier(st, tier);
83
84 if (unlikely(!db_last_entry_s)) {
85 // we assume this is a collected RRDSET
86 db_first_entry_s = 0;
87 db_last_entry_s = 0;
88 }
89 }
90
91 if(unlikely(db_last_entry_s > now_s)) {
92 internal_error(db_last_entry_s > now_s + 1,
93 "RRDSET: 'host:%s/chart:%s' latest db time %ld is in the future, adjusting it to now %ld",
94 rrdhost_hostname(st->rrdhost), rrdset_id(st),
95 db_last_entry_s, now_s);
96 db_last_entry_s = now_s;
97 }
98
99 if(unlikely(db_first_entry_s && db_last_entry_s && db_first_entry_s >= db_last_entry_s)) {
100 internal_error(db_first_entry_s > db_last_entry_s,
101 "RRDSET: 'host:%s/chart:%s' oldest db time %ld is bigger than latest db time %ld, adjusting it to (latest time %ld - update every %ld)",
102 rrdhost_hostname(st->rrdhost), rrdset_id(st),
103 db_first_entry_s, db_last_entry_s,
104 db_last_entry_s, (time_t)st->update_every);
105 db_first_entry_s = db_last_entry_s - st->update_every;
106 }
107
108 if(unlikely(!db_first_entry_s && db_last_entry_s))
109 // this can be the case on the first data collection of a chart
110 db_first_entry_s = db_last_entry_s - st->update_every;
111
112 *first_time_s = db_first_entry_s;
113 *last_time_s = db_last_entry_s;
114 }
115
116 void rrdset_is_obsolete___safe_from_collector_thread(RRDSET *st) {
117 if(!st) return;
118
119 rrdset_pluginsd_receive_unslot(st);
120
121 if(unlikely(!(rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)))) {
122 // netdata_log_info("Setting obsolete flag on chart 'host:%s/chart:%s'",
123 // rrdhost_hostname(st->rrdhost), rrdset_id(st));
124
125 rrdset_flag_set(st, RRDSET_FLAG_OBSOLETE);
126 rrdhost_flag_set(st->rrdhost, RRDHOST_FLAG_PENDING_OBSOLETE_CHARTS);
127
128 st->last_accessed_time_s = now_realtime_sec();
129
130 // The parent skips replication for obsolete charts, so the natural
131 // "replication finished" decrement at stream-replication-sender.c will
132 // never fire for this chart. Release any pending replication slot now,
133 // otherwise rrdhost_sender_replicating_charts pins above zero and
134 // observability (SND_REPLICATING vs SND_RUNNING) stays stuck on the
135 // wrong state. Mirror the natural-finalize path's pulse-status flip on
136 // the 0/1 boundary so SND_REPLICATING -> SND_RUNNING is observed.
137 RRDSET_FLAGS old_repl = rrdset_flag_set_and_clear(
138 st,
139 RRDSET_FLAG_SENDER_REPLICATION_FINISHED,
140 RRDSET_FLAG_SENDER_REPLICATION_IN_PROGRESS);
141 if(old_repl & RRDSET_FLAG_SENDER_REPLICATION_IN_PROGRESS) {
142 if(rrdhost_sender_replicating_charts_minus_one(st->rrdhost) == 0)
143 pulse_host_status(st->rrdhost, PULSE_HOST_STATUS_SND_RUNNING, 0);
144 }
145
146 rrdset_metadata_updated(st);
147
148 // the chart will not get more updates (data collection)
149 // so, we have to push its definition now
150 stream_sender_send_rrdset_definition_now(st);
151 rrdcontext_updated_rrdset_flags(st);
152 }
153 }
154
155 void rrdset_isnot_obsolete___safe_from_collector_thread(RRDSET *st) {
156 if(unlikely((rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)))) {
157
158 // netdata_log_info("Clearing obsolete flag on chart 'host:%s/chart:%s'",
159 // rrdhost_hostname(st->rrdhost), rrdset_id(st));
160
161 rrdset_flag_clear(st, RRDSET_FLAG_OBSOLETE);
162 st->last_accessed_time_s = now_realtime_sec();
163
164 rrdset_metadata_updated(st);
165
166 // the chart will be pushed upstream automatically
167 // due to data collection
168 rrdcontext_updated_rrdset_flags(st);
169 }
170 }
171
172 void rrdset_update_heterogeneous_flag(RRDSET *st) {
173 RRDHOST *host = st->rrdhost;
174 (void)host;
175
176 RRDDIM *rd;
177
178 rrdset_flag_clear(st, RRDSET_FLAG_HOMOGENEOUS_CHECK);
179
180 bool init = false, is_heterogeneous = false;
181 RRD_ALGORITHM algorithm;
182 int32_t multiplier;
183 int32_t divisor;
184
185 rrddim_foreach_read(rd, st) {
186 if(!init) {
187 algorithm = rd->algorithm;
188 multiplier = rd->multiplier;
189 divisor = ABS(rd->divisor);
190 init = true;
191 continue;
192 }
193
194 if(algorithm != rd->algorithm || multiplier != ABS(rd->multiplier) || divisor != ABS(rd->divisor)) {
195 if(!rrdset_flag_check(st, RRDSET_FLAG_HETEROGENEOUS)) {
196 #ifdef NETDATA_INTERNAL_CHECKS
197 netdata_log_info("Dimension '%s' added on chart '%s' of host '%s' is not homogeneous to other dimensions already present "
198 "(algorithm is '%s' vs '%s', multiplier is %d vs %d, "
199 "divisor is %d vs %d).",
200 rrddim_name(rd),
201 rrdset_name(st),
202 rrdhost_hostname(host),
203 rrd_algorithm_name(rd->algorithm), rrd_algorithm_name(algorithm),
204 rd->multiplier, multiplier,
205 rd->divisor, divisor
206 );
207 #endif
208 rrdset_flag_set(st, RRDSET_FLAG_HETEROGENEOUS);
209 }
210
211 is_heterogeneous = true;
212 break;
213 }
214 }
215 rrddim_foreach_done(rd);
216
217 if(!is_heterogeneous) {
218 rrdset_flag_clear(st, RRDSET_FLAG_HETEROGENEOUS);
219 rrdcontext_updated_rrdset_flags(st);
220 }
221 }