@cryptotaxi247 / netdata-1 / commits / c2b8b9a80

Rrddim acquire on replay set (#13932)

* prevent RRDDIM from vanishing while replay is working with it * set chart last access time * set chart last access time everytime someone finds it * do not replay dimensions that are archived * remove the obsolete flag from dimensions that replayed; do not process archived dimensions * cleanup db_metric_handle refcount of hidden dimensions * more information in page alignment fatal * do not fatal() of page alignment reset when the caller is the only writer

Costa Tsaousis committed Nov 1, 2022 at 20:32 UTC c2b8b9a8073b28ac780a949f847ef14d74296fee
6 files changed +85 -42
collectors/plugins.d/pluginsd_parser.c
+28 -12
@@ -56,14 +56,15 @@ PARSER_RC pluginsd_set(char **words, size_t num_words, void *user, PLUGINSD_ACTI
56 debug(D_PLUGINSD, "is setting dimension '%s'/'%s' to '%s'", rrdset_id(st), dimension, value ? value : "<nothing>");
57
58 if (value) {
59 - RRDDIM *rd = rrddim_find(st, dimension);
59 + RRDDIM_ACQUIRED *rda = rrddim_find_and_acquire(st, dimension);
60 + RRDDIM *rd = rrddim_acquired_to_rrddim(rda);
61 if (unlikely(!rd)) {
61 - error(
62 - "requested a SET to dimension with id '%s' on stats '%s' (%s) on host '%s', which does not exist. Disabling it.",
63 - dimension, rrdset_name(st), rrdset_id(st), rrdhost_hostname(st->rrdhost));
62 + error( "requested a SET to dimension with id '%s' on stats '%s' (%s) on host '%s', which does not exist. Disabling it.",
63 + dimension, rrdset_name(st), rrdset_id(st), rrdhost_hostname(st->rrdhost));
64 goto disable;
65 - } else
66 - rrddim_set_by_pointer(st, rd, strtoll(value, NULL, 0));
65 + }
66 + rrddim_set_by_pointer(st, rd, strtoll(value, NULL, 0));
67 + rrddim_acquired_release(rda);
68 }
69 return PARSER_RC_OK;
70
@@ -1024,19 +1025,28 @@ PARSER_RC pluginsd_replay_set(char **words, size_t num_words, void *user, PLUGIN
1025 debug(D_PLUGINSD, "REPLAY: is replaying dimension '%s'/'%s' to '%s'", rrdset_id(st), dimension, value_str);
1026
1027 if (likely(value_str)) {
1027 - RRDDIM *rd = rrddim_find(st, dimension);
1028 + RRDDIM_ACQUIRED *rda = rrddim_find_and_acquire(st, dimension);
1029 + RRDDIM *rd = rrddim_acquired_to_rrddim(rda);
1030 if(unlikely(!rd)) {
1031 error("REPLAY: requested a " PLUGINSD_KEYWORD_REPLAY_SET " to dimension with id '%s' on chart '%s' ('%s') on host '%s', which does not exist. Disabling it.",
1032 dimension, rrdset_name(st), rrdset_id(st), rrdhost_hostname(st->rrdhost));
1033 goto disable;
1034 }
1033 - else {
1035 +
1036 + RRDDIM_FLAGS rd_flags = rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE | RRDDIM_FLAG_ARCHIVED);
1037 +
1038 + if(unlikely(rd_flags & RRDDIM_FLAG_OBSOLETE)) {
1039 + error("Dimension %s in chart '%s' has the OBSOLETE flag set, but it is collected.", rrddim_name(rd), rrdset_id(st));
1040 + rrddim_isnot_obsolete(st, rd);
1041 + }
1042 +
1043 + if(!(rd_flags & RRDDIM_FLAG_ARCHIVED)) {
1044 NETDATA_DOUBLE value = strtondd(value_str, NULL);
1045 SN_FLAGS flags = SN_FLAG_NONE;
1046
1047 char c;
1038 - while((c = *flags_str++)) {
1039 - switch(c) {
1048 + while ((c = *flags_str++)) {
1049 + switch (c) {
1050 case 'R':
1051 flags |= SN_FLAG_RESET;
1052 break;
@@ -1052,7 +1062,7 @@ PARSER_RC pluginsd_replay_set(char **words, size_t num_words, void *user, PLUGIN
1062 }
1063 }
1064
1055 - if(!netdata_double_isnumber(value)) {
1065 + if (!netdata_double_isnumber(value)) {
1066 value = NAN;
1067 flags = SN_EMPTY_SLOT;
1068 }
@@ -1062,6 +1072,10 @@ PARSER_RC pluginsd_replay_set(char **words, size_t num_words, void *user, PLUGIN
1072 rd->last_collected_time.tv_usec = 0;
1073 rd->collections_counter++;
1074 }
1075 + else
1076 + error("Dimension %s in chart '%s' has the ARCHIVED flag set, but it is collected. Ignoring data.", rrddim_name(rd), rrdset_id(st));
1077 +
1078 + rrddim_acquired_release(rda);
1079 }
1080 return PARSER_RC_OK;
1081
@@ -1093,7 +1107,8 @@ PARSER_RC pluginsd_replay_rrddim_collection_state(char **words, size_t num_words
1107 goto disable;
1108 }
1109
1096 - RRDDIM *rd = rrddim_find(st, dimension);
1110 + RRDDIM_ACQUIRED *rda = rrddim_find_and_acquire(st, dimension);
1111 + RRDDIM *rd = rrddim_acquired_to_rrddim(rda);
1112 if(unlikely(!rd)) {
1113 error("REPLAY: requested a " PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE " to dimension with id '%s' on chart '%s' ('%s') on host '%s', which does not exist. Disabling it.",
1114 dimension, rrdset_name(st), rrdset_id(st), rrdhost_hostname(st->rrdhost));
@@ -1110,6 +1125,7 @@ PARSER_RC pluginsd_replay_rrddim_collection_state(char **words, size_t num_words
1125 rd->last_collected_value = last_collected_value_str ? str2ll(last_collected_value_str, NULL) : 0;
1126 rd->last_calculated_value = last_calculated_value_str ? str2ndd(last_calculated_value_str, NULL) : 0;
1127 rd->last_stored_value = last_stored_value_str ? str2ndd(last_stored_value_str, NULL) : 0.0;
1128 + rrddim_acquired_release(rda);
1129 return PARSER_RC_OK;
1130
1131 disable:
database/engine/rrdengineapi.c
+5 -6
@@ -134,13 +134,12 @@ STORAGE_METRIC_HANDLE *rrdeng_metric_get(STORAGE_INSTANCE *db_instance, uuid_t *
134 __atomic_add_fetch(&page_index->refcount, 1, __ATOMIC_SEQ_CST);
135
136 if(pa) {
137 - if(page_index->alignment && page_index->alignment != pa)
138 - fatal("DBENGINE: page_index has a different alignment.");
137 + if(page_index->alignment && page_index->alignment != pa && page_index->writers > 0)
138 + fatal("DBENGINE: page_index has a different alignment (page_index refcount is %u, writers is %u).",
139 + page_index->refcount, page_index->writers);
140
140 - if(!page_index->alignment) {
141 - page_index->alignment = pa;
142 - __atomic_add_fetch(&pa->refcount, 1, __ATOMIC_SEQ_CST);
143 - }
141 + page_index->alignment = pa;
142 + __atomic_add_fetch(&pa->refcount, 1, __ATOMIC_SEQ_CST);
143 }
144 }
145
database/rrd.h
+3
@@ -1280,6 +1280,9 @@ int rrddim_set_multiplier(RRDSET *st, RRDDIM *rd, collected_number multiplier);
1280 int rrddim_set_divisor(RRDSET *st, RRDDIM *rd, collected_number divisor);
1281
1282 RRDDIM *rrddim_find(RRDSET *st, const char *id);
1283 +RRDDIM_ACQUIRED *rrddim_find_and_acquire(RRDSET *st, const char *id);
1284 +RRDDIM *rrddim_acquired_to_rrddim(RRDDIM_ACQUIRED *rda);
1285 +void rrddim_acquired_release(RRDDIM_ACQUIRED *rda);
1286 RRDDIM *rrddim_find_active(RRDSET *st, const char *id);
1287
1288 int rrddim_hide(RRDSET *st, const char *id);
database/rrdcontext.c
+5 -2
@@ -2406,7 +2406,7 @@ static void query_target_add_metric(QUERY_TARGET_LOCALS *qtl, RRDMETRIC_ACQUIRED
2406 tier_retention[tier].eng = eng;
2407 tier_retention[tier].db_update_every = (time_t) (qtl->host->db[tier].tier_grouping * ri->update_every);
2408
2409 - if(rm->rrddim && rm->rrddim->tiers[tier]->db_metric_handle)
2409 + if(rm->rrddim && rm->rrddim->tiers[tier] && rm->rrddim->tiers[tier]->db_metric_handle)
2410 tier_retention[tier].db_metric_handle = eng->api.metric_dup(rm->rrddim->tiers[tier]->db_metric_handle);
2411 else
2412 tier_retention[tier].db_metric_handle = eng->api.metric_get(qtl->host->db[tier].instance, &rm->uuid, NULL);
@@ -2439,6 +2439,7 @@ static void query_target_add_metric(QUERY_TARGET_LOCALS *qtl, RRDMETRIC_ACQUIRED
2439 }
2440 }
2441
2442 + bool release_retention = true;
2443 bool timeframe_matches =
2444 (tiers_added
2445 && (common_first_time_t - common_update_every * 2) <= qt->window.before
@@ -2521,11 +2522,13 @@ static void query_target_add_metric(QUERY_TARGET_LOCALS *qtl, RRDMETRIC_ACQUIRED
2522 qm->tiers[tier].db_last_time_t = tier_retention[tier].db_last_time_t;
2523 qm->tiers[tier].db_update_every = tier_retention[tier].db_update_every;
2524 }
2525 + release_retention = false;
2526 }
2527 }
2526 - else {
2528 + else
2529 qtl->metrics_skipped_due_to_not_matching_timeframe++;
2530
2531 + if(release_retention) {
2532 // cleanup anything we allocated to the retention we will not use
2533 for(size_t tier = 0; tier < storage_tiers ;tier++) {
2534 if (tier_retention[tier].db_metric_handle)
database/rrddim.c
+38 -22
@@ -180,24 +180,21 @@ static void rrddim_delete_callback(const DICTIONARY_ITEM *item __maybe_unused, v
180
181 debug(D_RRD_CALLS, "rrddim_free() %s.%s", rrdset_name(st), rrddim_name(rd));
182
183 - if (!rrddim_flag_check(rd, RRDDIM_FLAG_ARCHIVED)) {
184 -
185 - size_t tiers_available = 0, tiers_said_yes = 0;
186 - for(size_t tier = 0; tier < storage_tiers ;tier++) {
187 - if(rd->tiers[tier]) {
188 - tiers_available++;
183 + size_t tiers_available = 0, tiers_said_yes = 0;
184 + for(size_t tier = 0; tier < storage_tiers ;tier++) {
185 + if(rd->tiers[tier] && rd->tiers[tier]->db_collection_handle) {
186 + tiers_available++;
187
190 - if(rd->tiers[tier]->collect_ops->finalize(rd->tiers[tier]->db_collection_handle))
191 - tiers_said_yes++;
188 + if(rd->tiers[tier]->collect_ops->finalize(rd->tiers[tier]->db_collection_handle))
189 + tiers_said_yes++;
190
193 - rd->tiers[tier]->db_collection_handle = NULL;
194 - }
191 + rd->tiers[tier]->db_collection_handle = NULL;
192 }
193 + }
194
197 - if (tiers_available == tiers_said_yes && tiers_said_yes && rd->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) {
198 - /* This metric has no data and no references */
199 - metaqueue_delete_dimension_uuid(&rd->metric_uuid);
200 - }
195 + if (tiers_available == tiers_said_yes && tiers_said_yes && rd->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) {
196 + /* This metric has no data and no references */
197 + metaqueue_delete_dimension_uuid(&rd->metric_uuid);
198 }
199
200 rrddimvar_delete_all(rd);
@@ -246,16 +243,14 @@ static bool rrddim_conflict_callback(const DICTIONARY_ITEM *item __maybe_unused,
243 rc += rrddim_set_multiplier(st, rd, ctr->multiplier);
244 rc += rrddim_set_divisor(st, rd, ctr->divisor);
245
249 - if(rrddim_flag_check(rd, RRDDIM_FLAG_ARCHIVED)) {
250 -
251 - for(size_t tier = 0; tier < storage_tiers ;tier++) {
252 - if (rd->tiers[tier])
253 - rd->tiers[tier]->db_collection_handle =
254 - rd->tiers[tier]->collect_ops->init(rd->tiers[tier]->db_metric_handle, st->rrdhost->db[tier].tier_grouping * st->update_every);
255 - }
246 + for(size_t tier = 0; tier < storage_tiers ;tier++) {
247 + if (rd->tiers[tier] && !rd->tiers[tier]->db_collection_handle)
248 + rd->tiers[tier]->db_collection_handle =
249 + rd->tiers[tier]->collect_ops->init(rd->tiers[tier]->db_metric_handle, st->rrdhost->db[tier].tier_grouping * st->update_every);
250 + }
251
252 + if(rrddim_flag_check(rd, RRDDIM_FLAG_ARCHIVED)) {
253 rrddim_flag_clear(rd, RRDDIM_FLAG_ARCHIVED);
258 -
254 if(!rrdset_is_ar_chart(st)) {
255 rrddim_flag_set(rd, RRDDIM_FLAG_PENDING_HEALTH_INITIALIZATION);
256 rrdset_flag_set(rd->rrdset, RRDSET_FLAG_PENDING_HEALTH_INITIALIZATION);
@@ -318,6 +313,27 @@ inline RRDDIM *rrddim_find(RRDSET *st, const char *id) {
313 return rrddim_index_find(st, id);
314 }
315
316 +inline RRDDIM_ACQUIRED *rrddim_find_and_acquire(RRDSET *st, const char *id) {
317 + debug(D_RRD_CALLS, "rrddim_find() for chart %s, dimension %s", rrdset_name(st), id);
318 +
319 + return (RRDDIM_ACQUIRED *)dictionary_get_and_acquire_item(st->rrddim_root_index, id);
320 +}
321 +
322 +RRDDIM *rrddim_acquired_to_rrddim(RRDDIM_ACQUIRED *rda) {
323 + if(unlikely(!rda))
324 + return NULL;
325 +
326 + return (RRDDIM *) dictionary_acquired_item_value((const DICTIONARY_ITEM *)rda);
327 +}
328 +
329 +void rrddim_acquired_release(RRDDIM_ACQUIRED *rda) {
330 + if(unlikely(!rda))
331 + return;
332 +
333 + RRDDIM *rd = rrddim_acquired_to_rrddim(rda);
334 + dictionary_acquired_item_release(rd->rrdset->rrddim_root_index, (const DICTIONARY_ITEM *)rda);
335 +}
336 +
337 // This will not return dimensions that are archived
338 RRDDIM *rrddim_find_active(RRDSET *st, const char *id) {
339 RRDDIM *rd = rrddim_find(st, id);
database/rrdset.c
+6
@@ -353,6 +353,8 @@ static void rrdset_react_callback(const DICTIONARY_ITEM *item __maybe_unused, vo
353 RRDSET *st = rrdset;
354 RRDHOST *host = st->rrdhost;
355
356 + st->last_accessed_time = now_realtime_sec();
357 +
358 if((host->health_enabled && (ctr->react_action & (RRDSET_REACT_NEW | RRDSET_REACT_CHART_ACTIVATED))) && !rrdset_is_ar_chart(st)) {
359 rrdset_flag_set(st, RRDSET_FLAG_PENDING_HEALTH_INITIALIZATION);
360 rrdhost_flag_set(st->rrdhost, RRDHOST_FLAG_PENDING_HEALTH_INITIALIZATION);
@@ -420,6 +422,10 @@ static RRDSET *rrdset_index_find(RRDHOST *host, const char *id) {
422 inline RRDSET *rrdset_find(RRDHOST *host, const char *id) {
423 debug(D_RRD_CALLS, "rrdset_find() for chart '%s' in host '%s'", id, rrdhost_hostname(host));
424 RRDSET *st = rrdset_index_find(host, id);
425 +
426 + if(st)
427 + st->last_accessed_time = now_realtime_sec();
428 +
429 return(st);
430 }
431