instance.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "internal.h"
  3. // ----------------------------------------------------------------------------
  4. // helper one-liners for RRDINSTANCE
  5. bool rrdinstance_acquired_id_and_name_are_same(RRDINSTANCE_ACQUIRED *ria) {
  6. RRDINSTANCE *ri = rrdinstance_acquired_value(ria);
  7. return ri->id == ri->name;
  8. }
  9. inline const char *rrdinstance_acquired_id(RRDINSTANCE_ACQUIRED *ria) {
  10. RRDINSTANCE *ri = rrdinstance_acquired_value(ria);
  11. return string2str(ri->id);
  12. }
  13. inline const char *rrdinstance_acquired_name(RRDINSTANCE_ACQUIRED *ria) {
  14. RRDINSTANCE *ri = rrdinstance_acquired_value(ria);
  15. return string2str(ri->name);
  16. }
  17. inline bool rrdinstance_acquired_has_name(RRDINSTANCE_ACQUIRED *ria) {
  18. RRDINSTANCE *ri = rrdinstance_acquired_value(ria);
  19. return (ri->name && ri->name != ri->id);
  20. }
  21. inline const char *rrdinstance_acquired_units(RRDINSTANCE_ACQUIRED *ria) {
  22. RRDINSTANCE *ri = rrdinstance_acquired_value(ria);
  23. return string2str(ri->units);
  24. }
  25. inline STRING *rrdinstance_acquired_units_dup(RRDINSTANCE_ACQUIRED *ria) {
  26. RRDINSTANCE *ri = rrdinstance_acquired_value(ria);
  27. return string_dup(ri->units);
  28. }
  29. inline RRDLABELS *rrdinstance_acquired_labels(RRDINSTANCE_ACQUIRED *ria) {
  30. RRDINSTANCE *ri = rrdinstance_acquired_value(ria);
  31. return ri->rrdlabels;
  32. }
  33. inline DICTIONARY *rrdinstance_acquired_functions(RRDINSTANCE_ACQUIRED *ria) {
  34. RRDINSTANCE *ri = rrdinstance_acquired_value(ria);
  35. if(!ri->rrdset) return NULL;
  36. return ri->rrdset->functions_view;
  37. }
  38. inline RRDHOST *rrdinstance_acquired_rrdhost(RRDINSTANCE_ACQUIRED *ria) {
  39. RRDINSTANCE *ri = rrdinstance_acquired_value(ria);
  40. return ri->rc->rrdhost;
  41. }
  42. inline bool rrdinstance_acquired_belongs_to_context(RRDINSTANCE_ACQUIRED *ria, RRDCONTEXT_ACQUIRED *rca) {
  43. RRDINSTANCE *ri = rrdinstance_acquired_value(ria);
  44. RRDCONTEXT *rc = rrdcontext_acquired_value(rca);
  45. return ri->rc == rc;
  46. }
  47. inline time_t rrdinstance_acquired_update_every(RRDINSTANCE_ACQUIRED *ria) {
  48. RRDINSTANCE *ri = rrdinstance_acquired_value(ria);
  49. return ri->update_every_s;
  50. }
  51. // ----------------------------------------------------------------------------
  52. // RRDINSTANCE
  53. static void rrdinstance_free(RRDINSTANCE *ri) {
  54. if(rrd_flag_check(ri, RRD_FLAG_OWN_LABELS))
  55. rrdlabels_destroy(ri->rrdlabels);
  56. rrdmetrics_destroy_from_rrdinstance(ri);
  57. string_freez(ri->id);
  58. string_freez(ri->name);
  59. string_freez(ri->title);
  60. string_freez(ri->units);
  61. string_freez(ri->family);
  62. ri->id = NULL;
  63. ri->name = NULL;
  64. ri->title = NULL;
  65. ri->units = NULL;
  66. ri->family = NULL;
  67. ri->rc = NULL;
  68. ri->rrdlabels = NULL;
  69. ri->rrdmetrics = NULL;
  70. ri->rrdset = NULL;
  71. }
  72. static void rrdinstance_insert_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *rrdcontext) {
  73. RRDINSTANCE *ri = value;
  74. // link it to its parent
  75. ri->rc = rrdcontext;
  76. ri->flags = ri->flags & RRD_FLAGS_ALLOWED_EXTERNALLY_ON_NEW_OBJECTS; // no need for atomics
  77. if(!ri->name)
  78. ri->name = string_dup(ri->id);
  79. if(ri->rrdset) {
  80. ri->rrdlabels = ri->rrdset->rrdlabels;
  81. ri->flags &= ~RRD_FLAG_OWN_LABELS; // no need of atomics at the constructor
  82. }
  83. else {
  84. ri->rrdlabels = rrdlabels_create();
  85. ri->flags |= RRD_FLAG_OWN_LABELS; // no need of atomics at the constructor
  86. }
  87. if(ri->rrdset) {
  88. if(unlikely(rrdset_flag_check(ri->rrdset, RRDSET_FLAG_HIDDEN)))
  89. ri->flags |= RRD_FLAG_HIDDEN; // no need of atomics at the constructor
  90. else
  91. ri->flags &= ~RRD_FLAG_HIDDEN; // no need of atomics at the constructor
  92. }
  93. rrdmetrics_create_in_rrdinstance(ri);
  94. // signal the react callback to do the job
  95. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_NEW_OBJECT);
  96. }
  97. static void rrdinstance_delete_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *rrdcontext __maybe_unused) {
  98. RRDINSTANCE *ri = (RRDINSTANCE *)value;
  99. internal_error(ri->rrdset, "RRDINSTANCE: '%s' is freed but there is a RRDSET linked to it.", string2str(ri->id));
  100. rrdinstance_free(ri);
  101. }
  102. static bool rrdinstance_conflict_callback(const DICTIONARY_ITEM *item __maybe_unused, void *old_value, void *new_value, void *rrdcontext __maybe_unused) {
  103. RRDINSTANCE *ri = (RRDINSTANCE *)old_value;
  104. RRDINSTANCE *ri_new = (RRDINSTANCE *)new_value;
  105. internal_error(ri->id != ri_new->id,
  106. "RRDINSTANCE: '%s' cannot change id to '%s'",
  107. string2str(ri->id), string2str(ri_new->id));
  108. if(uuid_memcmp(&ri->uuid, &ri_new->uuid) != 0) {
  109. #ifdef NETDATA_INTERNAL_CHECKS
  110. char uuid1[UUID_STR_LEN], uuid2[UUID_STR_LEN];
  111. uuid_unparse(ri->uuid, uuid1);
  112. uuid_unparse(ri_new->uuid, uuid2);
  113. internal_error(true, "RRDINSTANCE: '%s' of host '%s' changed UUID from '%s' to '%s'",
  114. string2str(ri->id), rrdhost_hostname(ri->rc->rrdhost), uuid1, uuid2);
  115. #endif
  116. uuid_copy(ri->uuid, ri_new->uuid);
  117. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_CHANGED_METADATA);
  118. }
  119. if(ri->rrdset && ri_new->rrdset && ri->rrdset != ri_new->rrdset) {
  120. ri->rrdset = ri_new->rrdset;
  121. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_CHANGED_LINKING);
  122. }
  123. #ifdef NETDATA_INTERNAL_CHECKS
  124. if(ri->rrdset && uuid_memcmp(&ri->uuid, &ri->rrdset->chart_uuid) != 0) {
  125. char uuid1[UUID_STR_LEN], uuid2[UUID_STR_LEN];
  126. uuid_unparse(ri->uuid, uuid1);
  127. uuid_unparse(ri->rrdset->chart_uuid, uuid2);
  128. internal_error(true, "RRDINSTANCE: '%s' is linked to RRDSET '%s' but they have different UUIDs. RRDINSTANCE has '%s', RRDSET has '%s'", string2str(ri->id), rrdset_id(ri->rrdset), uuid1, uuid2);
  129. }
  130. #endif
  131. if(ri->name != ri_new->name) {
  132. STRING *old = ri->name;
  133. ri->name = string_dup(ri_new->name);
  134. string_freez(old);
  135. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_CHANGED_METADATA);
  136. }
  137. if(ri->title != ri_new->title) {
  138. STRING *old = ri->title;
  139. ri->title = string_dup(ri_new->title);
  140. string_freez(old);
  141. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_CHANGED_METADATA);
  142. }
  143. if(ri->units != ri_new->units) {
  144. STRING *old = ri->units;
  145. ri->units = string_dup(ri_new->units);
  146. string_freez(old);
  147. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_CHANGED_METADATA);
  148. }
  149. if(ri->family != ri_new->family) {
  150. STRING *old = ri->family;
  151. ri->family = string_dup(ri_new->family);
  152. string_freez(old);
  153. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_CHANGED_METADATA);
  154. }
  155. if(ri->chart_type != ri_new->chart_type) {
  156. ri->chart_type = ri_new->chart_type;
  157. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_CHANGED_METADATA);
  158. }
  159. if(ri->priority != ri_new->priority) {
  160. ri->priority = ri_new->priority;
  161. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_CHANGED_METADATA);
  162. }
  163. if(ri->update_every_s != ri_new->update_every_s) {
  164. ri->update_every_s = ri_new->update_every_s;
  165. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_CHANGED_METADATA);
  166. }
  167. if(ri->rrdset != ri_new->rrdset) {
  168. ri->rrdset = ri_new->rrdset;
  169. if(ri->rrdset && rrd_flag_check(ri, RRD_FLAG_OWN_LABELS)) {
  170. RRDLABELS *old = ri->rrdlabels;
  171. ri->rrdlabels = ri->rrdset->rrdlabels;
  172. rrd_flag_clear(ri, RRD_FLAG_OWN_LABELS);
  173. rrdlabels_destroy(old);
  174. }
  175. else if(!ri->rrdset && !rrd_flag_check(ri, RRD_FLAG_OWN_LABELS)) {
  176. ri->rrdlabels = rrdlabels_create();
  177. rrd_flag_set(ri, RRD_FLAG_OWN_LABELS);
  178. }
  179. }
  180. if(ri->rrdset) {
  181. if(unlikely(rrdset_flag_check(ri->rrdset, RRDSET_FLAG_HIDDEN)))
  182. rrd_flag_set(ri, RRD_FLAG_HIDDEN);
  183. else
  184. rrd_flag_clear(ri, RRD_FLAG_HIDDEN);
  185. }
  186. rrd_flag_set(ri, ri_new->flags & RRD_FLAGS_ALLOWED_EXTERNALLY_ON_NEW_OBJECTS); // no need for atomics on ri_new
  187. if(rrd_flag_is_collected(ri) && rrd_flag_is_archived(ri))
  188. rrd_flag_set_collected(ri);
  189. if(rrd_flag_is_updated(ri))
  190. rrd_flag_set(ri, RRD_FLAG_UPDATE_REASON_UPDATED_OBJECT);
  191. // free the new one
  192. rrdinstance_free(ri_new);
  193. // the react callback will continue from here
  194. return rrd_flag_is_updated(ri);
  195. }
  196. static void rrdinstance_react_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *rrdcontext __maybe_unused) {
  197. RRDINSTANCE *ri = value;
  198. rrdinstance_trigger_updates(ri, __FUNCTION__ );
  199. }
  200. void rrdinstances_create_in_rrdcontext(RRDCONTEXT *rc) {
  201. if(unlikely(!rc || rc->rrdinstances)) return;
  202. rc->rrdinstances = dictionary_create_advanced(DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE,
  203. &dictionary_stats_category_rrdcontext, sizeof(RRDINSTANCE));
  204. dictionary_register_insert_callback(rc->rrdinstances, rrdinstance_insert_callback, rc);
  205. dictionary_register_delete_callback(rc->rrdinstances, rrdinstance_delete_callback, rc);
  206. dictionary_register_conflict_callback(rc->rrdinstances, rrdinstance_conflict_callback, rc);
  207. dictionary_register_react_callback(rc->rrdinstances, rrdinstance_react_callback, rc);
  208. }
  209. void rrdinstances_destroy_from_rrdcontext(RRDCONTEXT *rc) {
  210. if(unlikely(!rc || !rc->rrdinstances)) return;
  211. dictionary_destroy(rc->rrdinstances);
  212. rc->rrdinstances = NULL;
  213. }
  214. void rrdinstance_trigger_updates(RRDINSTANCE *ri, const char *function) {
  215. RRDSET *st = ri->rrdset;
  216. if(likely(st)) {
  217. if(unlikely((unsigned int) st->priority != ri->priority)) {
  218. ri->priority = st->priority;
  219. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_CHANGED_METADATA);
  220. }
  221. if(unlikely(st->update_every != ri->update_every_s)) {
  222. ri->update_every_s = st->update_every;
  223. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_CHANGED_METADATA);
  224. }
  225. }
  226. else if(unlikely(rrd_flag_is_collected(ri))) {
  227. // there is no rrdset, but we have it as collected!
  228. rrd_flag_set_archived(ri);
  229. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_CHANGED_LINKING);
  230. }
  231. if(rrd_flag_is_updated(ri) || !rrd_flag_check(ri, RRD_FLAG_LIVE_RETENTION)) {
  232. rrd_flag_set_updated(ri->rc, RRD_FLAG_UPDATE_REASON_TRIGGERED);
  233. rrdcontext_queue_for_post_processing(ri->rc, function, ri->flags);
  234. }
  235. }
  236. // ----------------------------------------------------------------------------
  237. // RRDINSTANCE HOOKS ON RRDSET
  238. inline void rrdinstance_from_rrdset(RRDSET *st) {
  239. RRDCONTEXT trc = {
  240. .id = string_dup(st->context),
  241. .title = string_dup(st->title),
  242. .units = string_dup(st->units),
  243. .family = string_dup(st->family),
  244. .priority = st->priority,
  245. .chart_type = st->chart_type,
  246. .flags = RRD_FLAG_NONE, // no need for atomics
  247. .rrdhost = st->rrdhost,
  248. };
  249. RRDCONTEXT_ACQUIRED *rca = (RRDCONTEXT_ACQUIRED *)dictionary_set_and_acquire_item(st->rrdhost->rrdctx.contexts, string2str(trc.id), &trc, sizeof(trc));
  250. RRDCONTEXT *rc = rrdcontext_acquired_value(rca);
  251. RRDINSTANCE tri = {
  252. .id = string_dup(st->id),
  253. .name = string_dup(st->name),
  254. .units = string_dup(st->units),
  255. .family = string_dup(st->family),
  256. .title = string_dup(st->title),
  257. .chart_type = st->chart_type,
  258. .priority = st->priority,
  259. .update_every_s = st->update_every,
  260. .flags = RRD_FLAG_NONE, // no need for atomics
  261. .rrdset = st,
  262. };
  263. uuid_copy(tri.uuid, st->chart_uuid);
  264. RRDINSTANCE_ACQUIRED *ria = (RRDINSTANCE_ACQUIRED *)dictionary_set_and_acquire_item(rc->rrdinstances, string2str(tri.id), &tri, sizeof(tri));
  265. RRDCONTEXT_ACQUIRED *rca_old = st->rrdcontexts.rrdcontext;
  266. RRDINSTANCE_ACQUIRED *ria_old = st->rrdcontexts.rrdinstance;
  267. st->rrdcontexts.rrdcontext = rca;
  268. st->rrdcontexts.rrdinstance = ria;
  269. if(rca == rca_old) {
  270. rrdcontext_release(rca_old);
  271. rca_old = NULL;
  272. }
  273. if(ria == ria_old) {
  274. rrdinstance_release(ria_old);
  275. ria_old = NULL;
  276. }
  277. if(rca_old && ria_old) {
  278. // Oops! The chart changed context!
  279. // RRDCONTEXT *rc_old = rrdcontext_acquired_value(rca_old);
  280. RRDINSTANCE *ri_old = rrdinstance_acquired_value(ria_old);
  281. // migrate all dimensions to the new metrics
  282. RRDDIM *rd;
  283. rrddim_foreach_read(rd, st) {
  284. if (!rd->rrdcontexts.rrdmetric) continue;
  285. RRDMETRIC *rm_old = rrdmetric_acquired_value(rd->rrdcontexts.rrdmetric);
  286. rrd_flags_replace(rm_old, RRD_FLAG_DELETED|RRD_FLAG_UPDATED|RRD_FLAG_LIVE_RETENTION|RRD_FLAG_UPDATE_REASON_UNUSED|RRD_FLAG_UPDATE_REASON_ZERO_RETENTION);
  287. rm_old->rrddim = NULL;
  288. rm_old->first_time_s = 0;
  289. rm_old->last_time_s = 0;
  290. rrdmetric_release(rd->rrdcontexts.rrdmetric);
  291. rd->rrdcontexts.rrdmetric = NULL;
  292. rrdmetric_from_rrddim(rd);
  293. }
  294. rrddim_foreach_done(rd);
  295. // mark the old instance, ready to be deleted
  296. if(!rrd_flag_check(ri_old, RRD_FLAG_OWN_LABELS))
  297. ri_old->rrdlabels = rrdlabels_create();
  298. rrd_flags_replace(ri_old, RRD_FLAG_OWN_LABELS|RRD_FLAG_DELETED|RRD_FLAG_UPDATED|RRD_FLAG_LIVE_RETENTION|RRD_FLAG_UPDATE_REASON_UNUSED|RRD_FLAG_UPDATE_REASON_ZERO_RETENTION);
  299. ri_old->rrdset = NULL;
  300. ri_old->first_time_s = 0;
  301. ri_old->last_time_s = 0;
  302. rrdinstance_trigger_updates(ri_old, __FUNCTION__ );
  303. rrdinstance_release(ria_old);
  304. /*
  305. // trigger updates on the old context
  306. if(!dictionary_entries(rc_old->rrdinstances) && !dictionary_stats_referenced_items(rc_old->rrdinstances)) {
  307. rrdcontext_lock(rc_old);
  308. rc_old->flags = ((rc_old->flags & RRD_FLAG_QUEUED)?RRD_FLAG_QUEUED:RRD_FLAG_NONE)|RRD_FLAG_DELETED|RRD_FLAG_UPDATED|RRD_FLAG_LIVE_RETENTION|RRD_FLAG_UPDATE_REASON_UNUSED|RRD_FLAG_UPDATE_REASON_ZERO_RETENTION;
  309. rc_old->first_time_s = 0;
  310. rc_old->last_time_s = 0;
  311. rrdcontext_unlock(rc_old);
  312. rrdcontext_trigger_updates(rc_old, __FUNCTION__ );
  313. }
  314. else
  315. rrdcontext_trigger_updates(rc_old, __FUNCTION__ );
  316. */
  317. rrdcontext_release(rca_old);
  318. rca_old = NULL;
  319. ria_old = NULL;
  320. }
  321. if(rca_old || ria_old)
  322. fatal("RRDCONTEXT: cannot switch rrdcontext without switching rrdinstance too");
  323. }
  324. #define rrdset_get_rrdinstance(st) rrdset_get_rrdinstance_with_trace(st, __FUNCTION__)
  325. static inline RRDINSTANCE *rrdset_get_rrdinstance_with_trace(RRDSET *st, const char *function) {
  326. if(unlikely(!st->rrdcontexts.rrdinstance)) {
  327. netdata_log_error("RRDINSTANCE: RRDSET '%s' is not linked to an RRDINSTANCE at %s()", rrdset_id(st), function);
  328. return NULL;
  329. }
  330. RRDINSTANCE *ri = rrdinstance_acquired_value(st->rrdcontexts.rrdinstance);
  331. if(unlikely(!ri)) {
  332. netdata_log_error("RRDINSTANCE: RRDSET '%s' lost its link to an RRDINSTANCE at %s()", rrdset_id(st), function);
  333. return NULL;
  334. }
  335. if(unlikely(ri->rrdset != st))
  336. fatal("RRDINSTANCE: '%s' is not linked to RRDSET '%s' at %s()", string2str(ri->id), rrdset_id(st), function);
  337. return ri;
  338. }
  339. inline void rrdinstance_rrdset_is_freed(RRDSET *st) {
  340. RRDINSTANCE *ri = rrdset_get_rrdinstance(st);
  341. if(unlikely(!ri)) return;
  342. rrd_flag_set_archived(ri);
  343. if(!rrd_flag_check(ri, RRD_FLAG_OWN_LABELS)) {
  344. ri->rrdlabels = rrdlabels_create();
  345. rrdlabels_copy(ri->rrdlabels, st->rrdlabels);
  346. rrd_flag_set(ri, RRD_FLAG_OWN_LABELS);
  347. }
  348. ri->rrdset = NULL;
  349. rrdinstance_trigger_updates(ri, __FUNCTION__ );
  350. rrdinstance_release(st->rrdcontexts.rrdinstance);
  351. st->rrdcontexts.rrdinstance = NULL;
  352. rrdcontext_release(st->rrdcontexts.rrdcontext);
  353. st->rrdcontexts.rrdcontext = NULL;
  354. st->rrdcontexts.collected = false;
  355. }
  356. inline void rrdinstance_rrdset_has_updated_retention(RRDSET *st) {
  357. st->rrdcontexts.collected = false;
  358. RRDINSTANCE *ri = rrdset_get_rrdinstance(st);
  359. if(unlikely(!ri)) return;
  360. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_UPDATE_RETENTION);
  361. rrdinstance_trigger_updates(ri, __FUNCTION__ );
  362. }
  363. inline void rrdinstance_updated_rrdset_name(RRDSET *st) {
  364. st->rrdcontexts.collected = false;
  365. // the chart may not be initialized when this is called
  366. if(unlikely(!st->rrdcontexts.rrdinstance)) return;
  367. RRDINSTANCE *ri = rrdset_get_rrdinstance(st);
  368. if(unlikely(!ri)) return;
  369. if(st->name != ri->name) {
  370. STRING *old = ri->name;
  371. ri->name = string_dup(st->name);
  372. string_freez(old);
  373. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_CHANGED_METADATA);
  374. rrdinstance_trigger_updates(ri, __FUNCTION__ );
  375. }
  376. }
  377. inline void rrdinstance_updated_rrdset_flags_no_action(RRDINSTANCE *ri, RRDSET *st) {
  378. if(unlikely(ri->rrdset != st))
  379. fatal("RRDCONTEXT: instance '%s' is not linked to chart '%s' on host '%s'",
  380. string2str(ri->id), rrdset_id(st), rrdhost_hostname(st->rrdhost));
  381. bool st_is_hidden = rrdset_flag_check(st, RRDSET_FLAG_HIDDEN);
  382. bool ri_is_hidden = rrd_flag_check(ri, RRD_FLAG_HIDDEN);
  383. if(unlikely(st_is_hidden != ri_is_hidden)) {
  384. if (unlikely(st_is_hidden && !ri_is_hidden))
  385. rrd_flag_set_updated(ri, RRD_FLAG_HIDDEN | RRD_FLAG_UPDATE_REASON_CHANGED_METADATA);
  386. else if (unlikely(!st_is_hidden && ri_is_hidden)) {
  387. rrd_flag_clear(ri, RRD_FLAG_HIDDEN);
  388. rrd_flag_set_updated(ri, RRD_FLAG_UPDATE_REASON_CHANGED_METADATA);
  389. }
  390. }
  391. }
  392. inline void rrdinstance_updated_rrdset_flags(RRDSET *st) {
  393. st->rrdcontexts.collected = false;
  394. RRDINSTANCE *ri = rrdset_get_rrdinstance(st);
  395. if(unlikely(!ri)) return;
  396. if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)))
  397. rrd_flag_set_archived(ri);
  398. rrdinstance_updated_rrdset_flags_no_action(ri, st);
  399. rrdinstance_trigger_updates(ri, __FUNCTION__ );
  400. }
  401. inline void rrdinstance_collected_rrdset(RRDSET *st) {
  402. if(st->rrdcontexts.collected)
  403. return;
  404. st->rrdcontexts.collected = true;
  405. RRDINSTANCE *ri = rrdset_get_rrdinstance(st);
  406. if(unlikely(!ri)) {
  407. rrdcontext_updated_rrdset(st);
  408. ri = rrdset_get_rrdinstance(st);
  409. if(unlikely(!ri))
  410. return;
  411. }
  412. rrdinstance_updated_rrdset_flags_no_action(ri, st);
  413. if(unlikely(ri->internal.collected_metrics_count && !rrd_flag_is_collected(ri)))
  414. rrd_flag_set_collected(ri);
  415. // we use this variable to detect BEGIN/END without SET
  416. ri->internal.collected_metrics_count = 0;
  417. rrdinstance_trigger_updates(ri, __FUNCTION__ );
  418. }