@cryptotaxi247 / netdata-1 / commits / 596615647

Fix contexts stay not-live when children reconnect (#19536)

* fixed bug where contexts stay not-live, although they are collected * small optimization

Costa Tsaousis committed Jan 30, 2025 at 17:51 UTC 596615647d9d5fcf99623250906085baab82dc55
4 files changed +67 -51
src/database/contexts/instance.c
+9 -3
@@ -420,8 +420,14 @@ static inline RRDINSTANCE *rrdset_get_rrdinstance_with_trace(RRDSET *st, const c
420 return ri;
421 }
422
423 -static inline void rrdinstance_rrdset_not_collected(RRDSET *st) {
423 +ALWAYS_INLINE void rrdinstance_rrdset_not_collected(RRDSET *st) {
424 st->rrdcontexts.collected = false;
425 +
426 + RRDDIM *rd;
427 + rrddim_foreach_read(rd, st) {
428 + rrdmetric_not_collected_rrddim(rd);
429 + }
430 + rrddim_foreach_done(rd);
431 }
432
433 inline void rrdinstance_rrdset_is_freed(RRDSET *st) {
@@ -450,8 +456,8 @@ inline void rrdinstance_rrdset_is_freed(RRDSET *st) {
456 st->rrdcontexts.rrdcontext = NULL;
457 }
458
453 -inline void rrdinstance_rrdset_has_updated_retention(RRDSET *st) {
454 - rrdinstance_rrdset_not_collected(st);
459 +ALWAYS_INLINE void rrdinstance_rrdset_has_updated_retention(RRDSET *st) {
460 + // rrdinstance_rrdset_not_collected(st);
461
462 RRDINSTANCE *ri = rrdset_get_rrdinstance(st);
463 if(unlikely(!ri)) return;
src/database/contexts/internal.h
+26 -22
@@ -125,7 +125,7 @@ extern struct rrdcontext_reason rrdcontext_reasons[];
125 // NEVER alter RRD_FLAG_COLLECTED, RRD_FLAG_ARCHIVED, RRD_FLAG_DELETED with this
126 #define rrd_flag_clear(obj, flag) __atomic_and_fetch(&((obj)->flags), ~(flag), __ATOMIC_SEQ_CST)
127
128 -static inline RRD_FLAGS
128 +static ALWAYS_INLINE RRD_FLAGS
129 rrd_flag_add_remove_atomic(RRD_FLAGS *flags, RRD_FLAGS check, RRD_FLAGS conditionally_add, RRD_FLAGS always_remove) {
130 RRD_FLAGS expected, desired;
131
@@ -143,7 +143,7 @@ rrd_flag_add_remove_atomic(RRD_FLAGS *flags, RRD_FLAGS check, RRD_FLAGS conditio
143 return expected;
144 }
145
146 -static inline RRD_FLAGS
146 +static ALWAYS_INLINE RRD_FLAGS
147 rrd_flags_replace_atomic(RRD_FLAGS *flags, RRD_FLAGS desired) {
148 RRD_FLAGS expected;
149
@@ -297,25 +297,27 @@ typedef struct rrdcontext {
297 // ----------------------------------------------------------------------------
298 // helpers for counting collected metrics, instances and contexts
299
300 -static inline void rrdmetric_set_collected(RRDMETRIC *rm) {
300 +static ALWAYS_INLINE void rrdmetric_set_collected(RRDMETRIC *rm) {
301 RRD_FLAGS old = rrd_flag_set_collected(rm);
302 if(!(old & RRD_FLAG_COLLECTED))
303 __atomic_add_fetch(&rm->ri->rc->rrdhost->collected.metrics_count, 1, __ATOMIC_RELAXED);
304 +
305 + rm->rrddim->rrdcontexts.collected = true;
306 }
307
306 -static inline void rrdmetric_set_archived(RRDMETRIC *rm) {
308 +static ALWAYS_INLINE void rrdmetric_set_archived(RRDMETRIC *rm) {
309 RRD_FLAGS old = rrd_flag_set_archived(rm);
310 if(old & RRD_FLAG_COLLECTED)
311 __atomic_sub_fetch(&rm->ri->rc->rrdhost->collected.metrics_count, 1, __ATOMIC_RELAXED);
312 }
313
312 -static inline void rrdmetric_set_deleted(RRDMETRIC *rm, RRD_FLAGS reason) {
314 +static ALWAYS_INLINE void rrdmetric_set_deleted(RRDMETRIC *rm, RRD_FLAGS reason) {
315 RRD_FLAGS old = rrd_flag_set_deleted(rm, reason);
316 if(old & RRD_FLAG_COLLECTED)
317 __atomic_sub_fetch(&rm->ri->rc->rrdhost->collected.metrics_count, 1, __ATOMIC_RELAXED);
318 }
319
318 -static inline void rrdmetric_set_deleted_overwrite(RRDMETRIC *rm, RRD_FLAGS replacement) {
320 +static ALWAYS_INLINE void rrdmetric_set_deleted_overwrite(RRDMETRIC *rm, RRD_FLAGS replacement) {
321 replacement &= ~(RRD_FLAG_COLLECTED|RRD_FLAG_ARCHIVED|RRD_FLAG_DELETED);
322 replacement |= RRD_FLAG_DELETED;
323 RRD_FLAGS old = rrd_flags_replace_atomic(&rm->flags, replacement);
@@ -323,25 +325,25 @@ static inline void rrdmetric_set_deleted_overwrite(RRDMETRIC *rm, RRD_FLAGS repl
325 __atomic_sub_fetch(&rm->ri->rc->rrdhost->collected.metrics_count, 1, __ATOMIC_RELAXED);
326 }
327
326 -static inline void rrdinstance_set_collected(RRDINSTANCE *ri) {
328 +static ALWAYS_INLINE void rrdinstance_set_collected(RRDINSTANCE *ri) {
329 RRD_FLAGS old = rrd_flag_set_collected(ri);
330 if(!(old & RRD_FLAG_COLLECTED))
331 __atomic_add_fetch(&ri->rc->rrdhost->collected.instances_count, 1, __ATOMIC_RELAXED);
332 }
333
332 -static inline void rrdinstance_set_archived(RRDINSTANCE *ri) {
334 +static ALWAYS_INLINE void rrdinstance_set_archived(RRDINSTANCE *ri) {
335 RRD_FLAGS old = rrd_flag_set_archived(ri);
336 if(old & RRD_FLAG_COLLECTED)
337 __atomic_sub_fetch(&ri->rc->rrdhost->collected.instances_count, 1, __ATOMIC_RELAXED);
338 }
339
338 -static inline void rrdinstance_set_deleted(RRDINSTANCE *ri, RRD_FLAGS reason) {
340 +static ALWAYS_INLINE void rrdinstance_set_deleted(RRDINSTANCE *ri, RRD_FLAGS reason) {
341 RRD_FLAGS old = rrd_flag_set_deleted(ri, reason);
342 if(old & RRD_FLAG_COLLECTED)
343 __atomic_sub_fetch(&ri->rc->rrdhost->collected.instances_count, 1, __ATOMIC_RELAXED);
344 }
345
344 -static inline void rrdinstance_set_deleted_overwrite(RRDINSTANCE *ri, RRD_FLAGS replacement) {
346 +static ALWAYS_INLINE void rrdinstance_set_deleted_overwrite(RRDINSTANCE *ri, RRD_FLAGS replacement) {
347 replacement &= ~(RRD_FLAG_COLLECTED|RRD_FLAG_ARCHIVED|RRD_FLAG_DELETED);
348 replacement |= RRD_FLAG_DELETED;
349 RRD_FLAGS old = rrd_flags_replace_atomic(&ri->flags, replacement);
@@ -349,19 +351,19 @@ static inline void rrdinstance_set_deleted_overwrite(RRDINSTANCE *ri, RRD_FLAGS
351 __atomic_sub_fetch(&ri->rc->rrdhost->collected.instances_count, 1, __ATOMIC_RELAXED);
352 }
353
352 -static inline void rrdcontext_set_collected(RRDCONTEXT *rc) {
354 +static ALWAYS_INLINE void rrdcontext_set_collected(RRDCONTEXT *rc) {
355 RRD_FLAGS old = rrd_flag_set_collected(rc);
356 if(!(old & RRD_FLAG_COLLECTED))
357 __atomic_add_fetch(&rc->rrdhost->collected.contexts_count, 1, __ATOMIC_RELAXED);
358 }
359
358 -static inline void rrdcontext_set_archived(RRDCONTEXT *rc) {
360 +static ALWAYS_INLINE void rrdcontext_set_archived(RRDCONTEXT *rc) {
361 RRD_FLAGS old = rrd_flag_set_archived(rc);
362 if(old & RRD_FLAG_COLLECTED)
363 __atomic_sub_fetch(&rc->rrdhost->collected.contexts_count, 1, __ATOMIC_RELAXED);
364 }
365
364 -static inline void rrdcontext_set_deleted(RRDCONTEXT *rc, RRD_FLAGS reason) {
366 +static ALWAYS_INLINE void rrdcontext_set_deleted(RRDCONTEXT *rc, RRD_FLAGS reason) {
367 RRD_FLAGS old = rrd_flag_set_deleted(rc, reason);
368 if(old & RRD_FLAG_COLLECTED)
369 __atomic_sub_fetch(&rc->rrdhost->collected.contexts_count, 1, __ATOMIC_RELAXED);
@@ -372,16 +374,16 @@ static inline void rrdcontext_set_deleted(RRDCONTEXT *rc, RRD_FLAGS reason) {
374
375 bool rrdmetric_update_retention(RRDMETRIC *rm);
376
375 -static inline RRDMETRIC *rrdmetric_acquired_value(RRDMETRIC_ACQUIRED *rma) {
377 +static ALWAYS_INLINE RRDMETRIC *rrdmetric_acquired_value(RRDMETRIC_ACQUIRED *rma) {
378 return dictionary_acquired_item_value((DICTIONARY_ITEM *)rma);
379 }
380
379 -static inline RRDMETRIC_ACQUIRED *rrdmetric_acquired_dup(RRDMETRIC_ACQUIRED *rma) {
381 +static ALWAYS_INLINE RRDMETRIC_ACQUIRED *rrdmetric_acquired_dup(RRDMETRIC_ACQUIRED *rma) {
382 RRDMETRIC *rm = rrdmetric_acquired_value(rma);
383 return (RRDMETRIC_ACQUIRED *)dictionary_acquired_item_dup(rm->ri->rrdmetrics, (DICTIONARY_ITEM *)rma);
384 }
385
384 -static inline void rrdmetric_release(RRDMETRIC_ACQUIRED *rma) {
386 +static ALWAYS_INLINE void rrdmetric_release(RRDMETRIC_ACQUIRED *rma) {
387 RRDMETRIC *rm = rrdmetric_acquired_value(rma);
388 dictionary_acquired_item_release(rm->ri->rrdmetrics, (DICTIONARY_ITEM *)rma);
389 }
@@ -389,20 +391,21 @@ static inline void rrdmetric_release(RRDMETRIC_ACQUIRED *rma) {
391 void rrdmetric_rrddim_is_freed(RRDDIM *rd);
392 void rrdmetric_updated_rrddim_flags(RRDDIM *rd);
393 void rrdmetric_collected_rrddim(RRDDIM *rd);
394 +void rrdmetric_not_collected_rrddim(RRDDIM *rd);
395
396 // ----------------------------------------------------------------------------
397 // helper one-liners for RRDINSTANCE
398
396 -static inline RRDINSTANCE *rrdinstance_acquired_value(RRDINSTANCE_ACQUIRED *ria) {
399 +static ALWAYS_INLINE RRDINSTANCE *rrdinstance_acquired_value(RRDINSTANCE_ACQUIRED *ria) {
400 return dictionary_acquired_item_value((DICTIONARY_ITEM *)ria);
401 }
402
400 -static inline RRDINSTANCE_ACQUIRED *rrdinstance_acquired_dup(RRDINSTANCE_ACQUIRED *ria) {
403 +static ALWAYS_INLINE RRDINSTANCE_ACQUIRED *rrdinstance_acquired_dup(RRDINSTANCE_ACQUIRED *ria) {
404 RRDINSTANCE *ri = rrdinstance_acquired_value(ria);
405 return (RRDINSTANCE_ACQUIRED *)dictionary_acquired_item_dup(ri->rc->rrdinstances, (DICTIONARY_ITEM *)ria);
406 }
407
405 -static inline void rrdinstance_release(RRDINSTANCE_ACQUIRED *ria) {
408 +static ALWAYS_INLINE void rrdinstance_release(RRDINSTANCE_ACQUIRED *ria) {
409 RRDINSTANCE *ri = rrdinstance_acquired_value(ria);
410 dictionary_acquired_item_release(ri->rc->rrdinstances, (DICTIONARY_ITEM *)ria);
411 }
@@ -414,22 +417,23 @@ void rrdinstance_updated_rrdset_name(RRDSET *st);
417 void rrdinstance_updated_rrdset_flags_no_action(RRDINSTANCE *ri, RRDSET *st);
418 void rrdinstance_updated_rrdset_flags(RRDSET *st);
419 void rrdinstance_collected_rrdset(RRDSET *st);
420 +void rrdinstance_rrdset_not_collected(RRDSET *st);
421
422 void rrdcontext_queue_for_post_processing(RRDCONTEXT *rc, const char *function, RRD_FLAGS flags);
423
424 // ----------------------------------------------------------------------------
425 // helper one-liners for RRDCONTEXT
426
423 -static inline RRDCONTEXT *rrdcontext_acquired_value(RRDCONTEXT_ACQUIRED *rca) {
427 +static ALWAYS_INLINE RRDCONTEXT *rrdcontext_acquired_value(RRDCONTEXT_ACQUIRED *rca) {
428 return dictionary_acquired_item_value((DICTIONARY_ITEM *)rca);
429 }
430
427 -static inline RRDCONTEXT_ACQUIRED *rrdcontext_acquired_dup(RRDCONTEXT_ACQUIRED *rca) {
431 +static ALWAYS_INLINE RRDCONTEXT_ACQUIRED *rrdcontext_acquired_dup(RRDCONTEXT_ACQUIRED *rca) {
432 RRDCONTEXT *rc = rrdcontext_acquired_value(rca);
433 return (RRDCONTEXT_ACQUIRED *)dictionary_acquired_item_dup(rc->rrdhost->rrdctx.contexts, (DICTIONARY_ITEM *)rca);
434 }
435
432 -static inline void rrdcontext_release(RRDCONTEXT_ACQUIRED *rca) {
436 +static ALWAYS_INLINE void rrdcontext_release(RRDCONTEXT_ACQUIRED *rca) {
437 RRDCONTEXT *rc = rrdcontext_acquired_value(rca);
438 dictionary_acquired_item_release(rc->rrdhost->rrdctx.contexts, (DICTIONARY_ITEM *)rca);
439 }
src/database/contexts/metric.c
+9 -5
@@ -227,6 +227,10 @@ void rrdmetric_trigger_updates(RRDMETRIC *rm, const char *function) {
227 // ----------------------------------------------------------------------------
228 // RRDMETRIC HOOKS ON RRDDIM
229
230 +ALWAYS_INLINE void rrdmetric_not_collected_rrddim(RRDDIM *rd) {
231 + rd->rrdcontexts.collected = false;
232 +}
233 +
234 void rrdmetric_from_rrddim(RRDDIM *rd) {
235 if(unlikely(!rd->rrdset))
236 fatal("RRDMETRIC: rrddim '%s' does not have a rrdset.", rrddim_id(rd));
@@ -253,11 +257,11 @@ void rrdmetric_from_rrddim(RRDDIM *rd) {
257 rrdmetric_release(rd->rrdcontexts.rrdmetric);
258
259 rd->rrdcontexts.rrdmetric = rma;
256 - rd->rrdcontexts.collected = false;
260 + rrdmetric_not_collected_rrddim(rd);
261 }
262
263 #define rrddim_get_rrdmetric(rd) rrddim_get_rrdmetric_with_trace(rd, __FUNCTION__)
260 -static inline RRDMETRIC *rrddim_get_rrdmetric_with_trace(RRDDIM *rd, const char *function) {
264 +static ALWAYS_INLINE RRDMETRIC *rrddim_get_rrdmetric_with_trace(RRDDIM *rd, const char *function) {
265 if(unlikely(!rd->rrdcontexts.rrdmetric)) {
266 netdata_log_error("RRDMETRIC: RRDDIM '%s' is not linked to an RRDMETRIC at %s()", rrddim_id(rd), function);
267 return NULL;
@@ -286,11 +290,11 @@ inline void rrdmetric_rrddim_is_freed(RRDDIM *rd) {
290 rrdmetric_trigger_updates(rm, __FUNCTION__ );
291 rrdmetric_release(rd->rrdcontexts.rrdmetric);
292 rd->rrdcontexts.rrdmetric = NULL;
289 - rd->rrdcontexts.collected = false;
293 + rrdmetric_not_collected_rrddim(rd);
294 }
295
296 inline void rrdmetric_updated_rrddim_flags(RRDDIM *rd) {
293 - rd->rrdcontexts.collected = false;
297 + rrdmetric_not_collected_rrddim(rd);
298
299 RRDMETRIC *rm = rrddim_get_rrdmetric(rd);
300 if(unlikely(!rm)) return;
@@ -303,7 +307,7 @@ inline void rrdmetric_updated_rrddim_flags(RRDDIM *rd) {
307 rrdmetric_trigger_updates(rm, __FUNCTION__ );
308 }
309
306 -inline void rrdmetric_collected_rrddim(RRDDIM *rd) {
310 +ALWAYS_INLINE void rrdmetric_collected_rrddim(RRDDIM *rd) {
311 if(rd->rrdcontexts.collected)
312 return;
313
src/database/contexts/rrdcontext.c
+23 -21
@@ -40,51 +40,51 @@ void rrd_reasons_to_buffer_json_array_items(RRD_FLAGS flags, BUFFER *wb) {
40 // ----------------------------------------------------------------------------
41 // public API
42
43 -void rrdcontext_updated_rrddim(RRDDIM *rd) {
43 +ALWAYS_INLINE void rrdcontext_updated_rrddim(RRDDIM *rd) {
44 rrdmetric_from_rrddim(rd);
45 }
46
47 -void rrdcontext_removed_rrddim(RRDDIM *rd) {
47 +ALWAYS_INLINE void rrdcontext_removed_rrddim(RRDDIM *rd) {
48 rrdmetric_rrddim_is_freed(rd);
49 }
50
51 -void rrdcontext_updated_rrddim_algorithm(RRDDIM *rd) {
51 +ALWAYS_INLINE void rrdcontext_updated_rrddim_algorithm(RRDDIM *rd) {
52 rrdmetric_updated_rrddim_flags(rd);
53 }
54
55 -void rrdcontext_updated_rrddim_multiplier(RRDDIM *rd) {
55 +ALWAYS_INLINE void rrdcontext_updated_rrddim_multiplier(RRDDIM *rd) {
56 rrdmetric_updated_rrddim_flags(rd);
57 }
58
59 -void rrdcontext_updated_rrddim_divisor(RRDDIM *rd) {
59 +ALWAYS_INLINE void rrdcontext_updated_rrddim_divisor(RRDDIM *rd) {
60 rrdmetric_updated_rrddim_flags(rd);
61 }
62
63 -void rrdcontext_updated_rrddim_flags(RRDDIM *rd) {
63 +ALWAYS_INLINE void rrdcontext_updated_rrddim_flags(RRDDIM *rd) {
64 rrdmetric_updated_rrddim_flags(rd);
65 }
66
67 -void rrdcontext_collected_rrddim(RRDDIM *rd) {
67 +ALWAYS_INLINE void rrdcontext_collected_rrddim(RRDDIM *rd) {
68 rrdmetric_collected_rrddim(rd);
69 }
70
71 -void rrdcontext_updated_rrdset(RRDSET *st) {
71 +ALWAYS_INLINE void rrdcontext_updated_rrdset(RRDSET *st) {
72 rrdinstance_from_rrdset(st);
73 }
74
75 -void rrdcontext_removed_rrdset(RRDSET *st) {
75 +ALWAYS_INLINE void rrdcontext_removed_rrdset(RRDSET *st) {
76 rrdinstance_rrdset_is_freed(st);
77 }
78
79 -void rrdcontext_updated_retention_rrdset(RRDSET *st) {
79 +ALWAYS_INLINE void rrdcontext_updated_retention_rrdset(RRDSET *st) {
80 rrdinstance_rrdset_has_updated_retention(st);
81 }
82
83 -void rrdcontext_updated_rrdset_name(RRDSET *st) {
83 +ALWAYS_INLINE void rrdcontext_updated_rrdset_name(RRDSET *st) {
84 rrdinstance_updated_rrdset_name(st);
85 }
86
87 -void rrdcontext_updated_rrdset_flags(RRDSET *st) {
87 +ALWAYS_INLINE void rrdcontext_updated_rrdset_flags(RRDSET *st) {
88 rrdinstance_updated_rrdset_flags(st);
89 }
90
@@ -92,15 +92,21 @@ ALWAYS_INLINE void rrdcontext_collected_rrdset(RRDSET *st) {
92 rrdinstance_collected_rrdset(st);
93 }
94
95 -void rrdcontext_host_child_connected(RRDHOST *host) {
96 - (void)host;
95 +ALWAYS_INLINE void rrdcontext_host_child_disconnected(RRDHOST *host) {
96 + rrdcontext_recalculate_host_retention(host, RRD_FLAG_UPDATE_REASON_DISCONNECTED_CHILD, false);
97 +}
98
98 - // no need to do anything here
99 - ;
99 +ALWAYS_INLINE void rrdcontext_host_child_connected(RRDHOST *host) {
100 + // clear the rrdcontexts status cache inside RRDSET and RRDDIM
101 + RRDSET *st;
102 + rrdset_foreach_read(st, host) {
103 + rrdinstance_rrdset_not_collected(st);
104 + }
105 + rrdset_foreach_done(st);
106 }
107
108 usec_t rrdcontext_next_db_rotation_ut = 0;
103 -void rrdcontext_db_rotation(void) {
109 +ALWAYS_INLINE void rrdcontext_db_rotation(void) {
110 // called when the db rotates its database
111 rrdcontext_next_db_rotation_ut = now_realtime_usec() + FULL_RETENTION_SCAN_DELAY_AFTER_DB_ROTATION_SECS * USEC_PER_SEC;
112 }
@@ -162,10 +168,6 @@ int rrdcontext_find_chart_uuid(RRDSET *st, nd_uuid_t *store_uuid) {
168 return 0;
169 }
170
165 -void rrdcontext_host_child_disconnected(RRDHOST *host) {
166 - rrdcontext_recalculate_host_retention(host, RRD_FLAG_UPDATE_REASON_DISCONNECTED_CHILD, false);
167 -}
168 -
171 int rrdcontext_foreach_instance_with_rrdset_in_context(RRDHOST *host, const char *context, int (*callback)(RRDSET *st, void *data), void *data) {
172 if(unlikely(!host || !context || !*context || !callback))
173 return -1;