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;