| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #ifndef NETDATA_RRDCONTEXT_INTERNAL_H |
| 4 | #define NETDATA_RRDCONTEXT_INTERNAL_H 1 |
| 5 | |
| 6 | #include "rrdcontext.h" |
| 7 | #include "rrdcontext-context-registry.h" |
| 8 | #include "../sqlite/sqlite_context.h" |
| 9 | #include "../../aclk/schema-wrappers/rrdcontext-context.h" |
| 10 | #include "../../aclk/aclk_contexts_api.h" |
| 11 | #include "../../aclk/aclk.h" |
| 12 | #include "../storage-engine.h" |
| 13 | |
| 14 | #define MESSAGES_PER_BUNDLE_TO_SEND_TO_HUB_PER_HOST 5000 |
| 15 | #define FULL_RETENTION_SCAN_DELAY_AFTER_DB_ROTATION_SECS 120 |
| 16 | #define RRDCONTEXT_WORKER_THREAD_HEARTBEAT_USEC (1000 * USEC_PER_MS) |
| 17 | #define RRDCONTEXT_MINIMUM_ALLOWED_PRIORITY 10 |
| 18 | |
| 19 | #define LOG_TRANSITIONS false |
| 20 | |
| 21 | #define WORKER_JOB_HOSTS 1 |
| 22 | #define WORKER_JOB_CHECK 2 |
| 23 | #define WORKER_JOB_SEND 3 |
| 24 | #define WORKER_JOB_DEQUEUE 4 |
| 25 | #define WORKER_JOB_RETENTION 5 |
| 26 | #define WORKER_JOB_QUEUED 6 |
| 27 | #define WORKER_JOB_CLEANUP 7 |
| 28 | #define WORKER_JOB_CLEANUP_DELETE 8 |
| 29 | #define WORKER_JOB_PP_METRIC 9 // post-processing metrics |
| 30 | #define WORKER_JOB_PP_INSTANCE 10 // post-processing instances |
| 31 | #define WORKER_JOB_PP_CONTEXT 11 // post-processing contexts |
| 32 | #define WORKER_JOB_HUB_QUEUE_SIZE 12 |
| 33 | #define WORKER_JOB_PP_QUEUE_SIZE 13 |
| 34 | |
| 35 | |
| 36 | typedef enum __attribute__ ((__packed__)) { |
| 37 | RRD_FLAG_NONE = 0, |
| 38 | RRD_FLAG_DELETED = (1 << 0), // this is a deleted object (metrics, instances, contexts) |
| 39 | RRD_FLAG_COLLECTED = (1 << 1), // this object is currently being collected |
| 40 | RRD_FLAG_UPDATED = (1 << 2), // this object has updates to propagate |
| 41 | RRD_FLAG_ARCHIVED = (1 << 3), // this object is not currently being collected |
| 42 | RRD_FLAG_OWN_LABELS = (1 << 4), // this instance has its own labels - not linked to an RRDSET |
| 43 | RRD_FLAG_DEMAND_LABELS = (1 << 5), // this instance should load labels on demand |
| 44 | RRD_FLAG_LIVE_RETENTION = (1 << 6), // we have got live retention from the database |
| 45 | RRD_FLAG_QUEUED_FOR_HUB = (1 << 7), // this context is currently queued to be dispatched to hub |
| 46 | RRD_FLAG_QUEUED_FOR_PP = (1 << 8), // this context is currently queued to be post-processed |
| 47 | RRD_FLAG_HIDDEN = (1 << 9), // don't expose this to the hub or the API |
| 48 | |
| 49 | RRD_FLAG_UPDATE_REASON_TRIGGERED = (1 << 10), // the update was triggered by the child object |
| 50 | RRD_FLAG_UPDATE_REASON_LOAD_SQL = (1 << 11), // this object has just been loaded from SQL |
| 51 | RRD_FLAG_UPDATE_REASON_NEW_OBJECT = (1 << 12), // this object has just been created |
| 52 | RRD_FLAG_UPDATE_REASON_UPDATED_OBJECT = (1 << 13), // we received an update on this object |
| 53 | RRD_FLAG_UPDATE_REASON_CHANGED_LINKING = (1 << 14), // an instance or a metric switched RRDSET or RRDDIM |
| 54 | RRD_FLAG_UPDATE_REASON_CHANGED_METADATA = (1 << 15), // this context or instance changed uuid, name, units, title, family, chart type, priority, update every, rrd changed flags |
| 55 | RRD_FLAG_UPDATE_REASON_ZERO_RETENTION = (1 << 16), // this object has no retention |
| 56 | RRD_FLAG_UPDATE_REASON_CHANGED_FIRST_TIME_T = (1 << 17), // this object changed its oldest time in the db |
| 57 | RRD_FLAG_UPDATE_REASON_CHANGED_LAST_TIME_T = (1 << 18), // this object change its latest time in the db |
| 58 | RRD_FLAG_UPDATE_REASON_STOPPED_BEING_COLLECTED = (1 << 19), // this object has stopped being collected |
| 59 | RRD_FLAG_UPDATE_REASON_STARTED_BEING_COLLECTED = (1 << 20), // this object has started being collected |
| 60 | RRD_FLAG_UPDATE_REASON_DISCONNECTED_CHILD = (1 << 21), // this context belongs to a host that just disconnected |
| 61 | RRD_FLAG_UPDATE_REASON_UNUSED = (1 << 22), // this context is not used anymore |
| 62 | RRD_FLAG_UPDATE_REASON_DB_ROTATION = (1 << 23), // this context changed because of a db rotation |
| 63 | |
| 64 | RRD_FLAG_NO_TIER0_RETENTION = (1 << 28), |
| 65 | RRD_FLAG_MERGED_COLLECTED_RI_TO_RC = (1 << 29), |
| 66 | |
| 67 | // action to perform on an object |
| 68 | RRD_FLAG_UPDATE_REASON_UPDATE_RETENTION = (1 << 30), // this object has to update its retention from the db |
| 69 | } RRD_FLAGS; |
| 70 | |
| 71 | struct rrdcontext_reason { |
| 72 | RRD_FLAGS flag; |
| 73 | const char *name; |
| 74 | usec_t delay_ut; |
| 75 | }; |
| 76 | |
| 77 | extern struct rrdcontext_reason rrdcontext_reasons[]; |
| 78 | |
| 79 | #define RRD_FLAG_ALL_UPDATE_REASONS ( \ |
| 80 | RRD_FLAG_UPDATE_REASON_TRIGGERED \ |
| 81 | |RRD_FLAG_UPDATE_REASON_LOAD_SQL \ |
| 82 | |RRD_FLAG_UPDATE_REASON_NEW_OBJECT \ |
| 83 | |RRD_FLAG_UPDATE_REASON_UPDATED_OBJECT \ |
| 84 | |RRD_FLAG_UPDATE_REASON_CHANGED_LINKING \ |
| 85 | |RRD_FLAG_UPDATE_REASON_CHANGED_METADATA \ |
| 86 | |RRD_FLAG_UPDATE_REASON_ZERO_RETENTION \ |
| 87 | |RRD_FLAG_UPDATE_REASON_CHANGED_FIRST_TIME_T \ |
| 88 | |RRD_FLAG_UPDATE_REASON_CHANGED_LAST_TIME_T \ |
| 89 | |RRD_FLAG_UPDATE_REASON_STOPPED_BEING_COLLECTED \ |
| 90 | |RRD_FLAG_UPDATE_REASON_STARTED_BEING_COLLECTED \ |
| 91 | |RRD_FLAG_UPDATE_REASON_DISCONNECTED_CHILD \ |
| 92 | |RRD_FLAG_UPDATE_REASON_DB_ROTATION \ |
| 93 | |RRD_FLAG_UPDATE_REASON_UNUSED \ |
| 94 | ) |
| 95 | |
| 96 | #define RRD_FLAGS_ALLOWED_EXTERNALLY_ON_NEW_OBJECTS ( \ |
| 97 | RRD_FLAG_ARCHIVED \ |
| 98 | |RRD_FLAG_HIDDEN \ |
| 99 | |RRD_FLAG_ALL_UPDATE_REASONS \ |
| 100 | ) |
| 101 | |
| 102 | #define RRD_FLAGS_REQUIRED_FOR_DELETIONS ( \ |
| 103 | RRD_FLAG_DELETED \ |
| 104 | |RRD_FLAG_LIVE_RETENTION \ |
| 105 | ) |
| 106 | |
| 107 | #define RRD_FLAGS_PREVENTING_DELETIONS ( \ |
| 108 | RRD_FLAG_QUEUED_FOR_HUB \ |
| 109 | |RRD_FLAG_COLLECTED \ |
| 110 | |RRD_FLAG_QUEUED_FOR_PP \ |
| 111 | ) |
| 112 | |
| 113 | // get all the flags of an object |
| 114 | #define rrd_flags_get(obj) __atomic_load_n(&((obj)->flags), __ATOMIC_SEQ_CST) |
| 115 | |
| 116 | // check if ANY of the given flags (bits) is set |
| 117 | #define rrd_flag_check(obj, flag) (rrd_flags_get(obj) & (flag)) |
| 118 | |
| 119 | // check if ALL the given flags (bits) are set |
| 120 | #define rrd_flag_check_all(obj, flag) (rrd_flag_check(obj, flag) == (flag)) |
| 121 | |
| 122 | // set one or more flags (bits) |
| 123 | // NEVER alter RRD_FLAG_COLLECTED, RRD_FLAG_ARCHIVED, RRD_FLAG_DELETED with this |
| 124 | #define rrd_flag_set(obj, flag) __atomic_or_fetch(&((obj)->flags), flag, __ATOMIC_SEQ_CST) |
| 125 | |
| 126 | // clear one or more flags (bits) |
| 127 | // NEVER alter RRD_FLAG_COLLECTED, RRD_FLAG_ARCHIVED, RRD_FLAG_DELETED with this |
| 128 | #define rrd_flag_clear(obj, flag) __atomic_and_fetch(&((obj)->flags), ~(flag), __ATOMIC_SEQ_CST) |
| 129 | |
| 130 | static ALWAYS_INLINE RRD_FLAGS |
| 131 | rrd_flag_add_remove_atomic(RRD_FLAGS *flags, RRD_FLAGS check, RRD_FLAGS conditionally_add, RRD_FLAGS always_remove) { |
| 132 | RRD_FLAGS expected, desired; |
| 133 | |
| 134 | do { |
| 135 | expected = *flags; |
| 136 | |
| 137 | desired = expected; |
| 138 | desired &= ~(always_remove); |
| 139 | |
| 140 | if(!(expected & check)) |
| 141 | desired |= (check | conditionally_add); |
| 142 | |
| 143 | } while(!__atomic_compare_exchange_n(flags, &expected, desired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)); |
| 144 | |
| 145 | return expected; |
| 146 | } |
| 147 | |
| 148 | static ALWAYS_INLINE RRD_FLAGS |
| 149 | rrd_flags_replace_atomic(RRD_FLAGS *flags, RRD_FLAGS desired) { |
| 150 | RRD_FLAGS expected; |
| 151 | |
| 152 | do { |
| 153 | expected = *flags; |
| 154 | } while(!__atomic_compare_exchange_n(flags, &expected, desired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)); |
| 155 | |
| 156 | return expected; |
| 157 | } |
| 158 | |
| 159 | #define rrd_flag_set_collected(obj) \ |
| 160 | rrd_flag_add_remove_atomic(&((obj)->flags) \ |
| 161 | /* check this flag */ \ |
| 162 | , RRD_FLAG_COLLECTED \ |
| 163 | \ |
| 164 | /* add these flags together with the above, if the above is not already set */ \ |
| 165 | , RRD_FLAG_UPDATE_REASON_STARTED_BEING_COLLECTED | RRD_FLAG_UPDATED \ |
| 166 | \ |
| 167 | /* always remove these flags */ \ |
| 168 | , RRD_FLAG_ARCHIVED \ |
| 169 | | RRD_FLAG_DELETED \ |
| 170 | | RRD_FLAG_UPDATE_REASON_STOPPED_BEING_COLLECTED \ |
| 171 | | RRD_FLAG_UPDATE_REASON_ZERO_RETENTION \ |
| 172 | | RRD_FLAG_UPDATE_REASON_DISCONNECTED_CHILD \ |
| 173 | ) |
| 174 | |
| 175 | #define rrd_flag_set_archived(obj) \ |
| 176 | rrd_flag_add_remove_atomic(&((obj)->flags) \ |
| 177 | /* check this flag */ \ |
| 178 | , RRD_FLAG_ARCHIVED \ |
| 179 | \ |
| 180 | /* add these flags together with the above, if the above is not already set */ \ |
| 181 | , RRD_FLAG_UPDATE_REASON_STOPPED_BEING_COLLECTED | RRD_FLAG_UPDATED \ |
| 182 | \ |
| 183 | /* always remove these flags */ \ |
| 184 | , RRD_FLAG_COLLECTED \ |
| 185 | | RRD_FLAG_DELETED \ |
| 186 | | RRD_FLAG_UPDATE_REASON_STARTED_BEING_COLLECTED \ |
| 187 | | RRD_FLAG_UPDATE_REASON_ZERO_RETENTION \ |
| 188 | ) |
| 189 | |
| 190 | #define rrd_flag_set_deleted(obj, reason) \ |
| 191 | rrd_flag_add_remove_atomic(&((obj)->flags) \ |
| 192 | /* check this flag */ \ |
| 193 | , RRD_FLAG_DELETED \ |
| 194 | \ |
| 195 | /* add these flags together with the above, if the above is not already set */ \ |
| 196 | , RRD_FLAG_UPDATE_REASON_ZERO_RETENTION | RRD_FLAG_UPDATED | (reason) \ |
| 197 | \ |
| 198 | /* always remove these flags */ \ |
| 199 | , RRD_FLAG_ARCHIVED \ |
| 200 | | RRD_FLAG_COLLECTED \ |
| 201 | ) |
| 202 | |
| 203 | #define rrd_flag_is_collected(obj) rrd_flag_check(obj, RRD_FLAG_COLLECTED) |
| 204 | #define rrd_flag_is_archived(obj) rrd_flag_check(obj, RRD_FLAG_ARCHIVED) |
| 205 | #define rrd_flag_is_deleted(obj) rrd_flag_check(obj, RRD_FLAG_DELETED) |
| 206 | #define rrd_flag_is_updated(obj) rrd_flag_check(obj, RRD_FLAG_UPDATED) |
| 207 | |
| 208 | // mark an object as updated, providing reasons (additional bits) |
| 209 | #define rrd_flag_set_updated(obj, reason) rrd_flag_set(obj, RRD_FLAG_UPDATED | (reason)) |
| 210 | |
| 211 | // clear an object as being updated, clearing also all the reasons |
| 212 | #define rrd_flag_unset_updated(obj) rrd_flag_clear(obj, RRD_FLAG_UPDATED | RRD_FLAG_ALL_UPDATE_REASONS) |
| 213 | |
| 214 | |
| 215 | typedef struct rrdmetric { |
| 216 | UUIDMAP_ID uuid; |
| 217 | RRD_FLAGS flags; |
| 218 | |
| 219 | STRING *id; |
| 220 | STRING *name; |
| 221 | |
| 222 | RRDDIM *rrddim; |
| 223 | RRD_ALGORITHM algorithm; // atomic load/store; survives RRDDIM archive so query paths don't need a live rrddim |
| 224 | |
| 225 | time_t first_time_s; |
| 226 | time_t last_time_s; |
| 227 | |
| 228 | struct rrdinstance *ri; |
| 229 | } RRDMETRIC; |
| 230 | |
| 231 | static ALWAYS_INLINE RRDDIM *rrdmetric_rrddim_atomic_load(RRDMETRIC *rm) { |
| 232 | return __atomic_load_n(&rm->rrddim, __ATOMIC_ACQUIRE); |
| 233 | } |
| 234 | |
| 235 | static ALWAYS_INLINE void rrdmetric_rrddim_atomic_store(RRDMETRIC *rm, RRDDIM *rd) { |
| 236 | __atomic_store_n(&rm->rrddim, rd, __ATOMIC_RELEASE); |
| 237 | } |
| 238 | |
| 239 | static ALWAYS_INLINE RRD_ALGORITHM rrdmetric_algorithm_atomic_load(RRDMETRIC *rm) { |
| 240 | return __atomic_load_n(&rm->algorithm, __ATOMIC_ACQUIRE); |
| 241 | } |
| 242 | |
| 243 | static ALWAYS_INLINE void rrdmetric_algorithm_atomic_store(RRDMETRIC *rm, RRD_ALGORITHM algorithm) { |
| 244 | __atomic_store_n(&rm->algorithm, algorithm, __ATOMIC_RELEASE); |
| 245 | } |
| 246 | |
| 247 | static ALWAYS_INLINE RRDDIM *rrdmetric_rrddim_get_and_lock(RRDMETRIC *rm) { |
| 248 | for(size_t retries = 0; retries < 5; retries++) { |
| 249 | RRDDIM *rd = rrdmetric_rrddim_atomic_load(rm); |
| 250 | if(unlikely(!rd)) |
| 251 | return NULL; |
| 252 | |
| 253 | if(unlikely(!spinlock_trylock(&rd->destroy_lock))) { |
| 254 | if(retries + 1 < 5) |
| 255 | microsleep(1 * USEC_PER_MS); |
| 256 | continue; |
| 257 | } |
| 258 | |
| 259 | if(unlikely(rrdmetric_rrddim_atomic_load(rm) != rd)) { |
| 260 | spinlock_unlock(&rd->destroy_lock); |
| 261 | continue; |
| 262 | } |
| 263 | |
| 264 | return rd; |
| 265 | } |
| 266 | |
| 267 | return NULL; |
| 268 | } |
| 269 | |
| 270 | static ALWAYS_INLINE void rrdmetric_rrddim_unlock(RRDDIM *rd) { |
| 271 | if(likely(rd)) |
| 272 | spinlock_unlock(&rd->destroy_lock); |
| 273 | } |
| 274 | |
| 275 | typedef struct rrdinstance { |
| 276 | UUIDMAP_ID uuid; |
| 277 | int update_every_s; // data collection frequency |
| 278 | |
| 279 | RRD_FLAGS flags; // flags related to this instance |
| 280 | uint32_t priority:24; |
| 281 | RRDSET_TYPE chart_type; |
| 282 | |
| 283 | STRING *id; |
| 284 | STRING *name; |
| 285 | STRING *title; |
| 286 | STRING *units; |
| 287 | STRING *family; |
| 288 | |
| 289 | time_t first_time_s; |
| 290 | time_t last_time_s; |
| 291 | |
| 292 | RRDSET *rrdset; // pointer to RRDSET when collected, or NULL |
| 293 | |
| 294 | RRDLABELS *rrdlabels; // linked to RRDSET->chart_labels or own version |
| 295 | |
| 296 | struct rrdcontext *rc; |
| 297 | DICTIONARY *rrdmetrics; |
| 298 | |
| 299 | struct { |
| 300 | uint32_t collected_metrics_count; // a temporary variable to detect BEGIN/END without SET |
| 301 | // don't use it for other purposes |
| 302 | // it goes up and then resets to zero, on every iteration |
| 303 | } internal; |
| 304 | } RRDINSTANCE; |
| 305 | |
| 306 | typedef struct rrdcontext { |
| 307 | uint64_t version; |
| 308 | |
| 309 | STRING *id; |
| 310 | STRING *title; |
| 311 | STRING *units; |
| 312 | STRING *family; |
| 313 | uint32_t priority; |
| 314 | RRDSET_TYPE chart_type; |
| 315 | |
| 316 | SPINLOCK spinlock; |
| 317 | |
| 318 | RRD_FLAGS flags; |
| 319 | time_t first_time_s; |
| 320 | time_t last_time_s; |
| 321 | |
| 322 | VERSIONED_CONTEXT_DATA hub; |
| 323 | |
| 324 | DICTIONARY *rrdinstances; |
| 325 | RRDHOST *rrdhost; |
| 326 | |
| 327 | struct { |
| 328 | Word_t idx; |
| 329 | RRD_FLAGS queued_flags; // the last flags that triggered the post-processing |
| 330 | size_t executions; // how many times this context has been processed |
| 331 | usec_t queued_ut; // the last time this was queued |
| 332 | usec_t dequeued_ut; // the last time we sent (or deduplicated) this context |
| 333 | } pp; |
| 334 | |
| 335 | struct { |
| 336 | Word_t idx; |
| 337 | RRD_FLAGS queued_flags; // the last flags that triggered the queueing |
| 338 | size_t dispatches; // the number of times this has been dispatched to hub |
| 339 | usec_t queued_ut; // the last time this was queued |
| 340 | usec_t delay_calc_ut; // the last time we calculated the scheduled_dispatched_ut |
| 341 | usec_t scheduled_dispatch_ut; // the time it was/is scheduled to be sent |
| 342 | usec_t dequeued_ut; // the last time we sent (or deduplicated) this context |
| 343 | } queue; |
| 344 | } RRDCONTEXT; |
| 345 | |
| 346 | void rrdcontext_add_to_pp_queue(RRDCONTEXT *rc); |
| 347 | void rrdcontext_add_to_hub_queue(RRDCONTEXT *rc); |
| 348 | void rrdcontext_del_from_hub_queue(RRDCONTEXT *rc, bool having_lock); |
| 349 | void rrdcontext_del_from_pp_queue(RRDCONTEXT *rc, bool having_lock); |
| 350 | |
| 351 | // ---------------------------------------------------------------------------- |
| 352 | // helpers for counting collected metrics, instances and contexts |
| 353 | |
| 354 | static ALWAYS_INLINE void rrdmetric_set_collected(RRDMETRIC *rm) { |
| 355 | RRD_FLAGS old = rrd_flag_set_collected(rm); |
| 356 | if(!(old & RRD_FLAG_COLLECTED)) |
| 357 | __atomic_add_fetch(&rm->ri->rc->rrdhost->collected.metrics_count, 1, __ATOMIC_RELAXED); |
| 358 | |
| 359 | RRDDIM *rd = rrdmetric_rrddim_atomic_load(rm); |
| 360 | if(likely(rd)) |
| 361 | rd->rrdcontexts.collected = true; |
| 362 | } |
| 363 | |
| 364 | static ALWAYS_INLINE void rrdmetric_set_archived(RRDMETRIC *rm) { |
| 365 | RRD_FLAGS old = rrd_flag_set_archived(rm); |
| 366 | if(old & RRD_FLAG_COLLECTED) |
| 367 | __atomic_sub_fetch(&rm->ri->rc->rrdhost->collected.metrics_count, 1, __ATOMIC_RELAXED); |
| 368 | } |
| 369 | |
| 370 | static ALWAYS_INLINE void rrdmetric_set_deleted(RRDMETRIC *rm, RRD_FLAGS reason) { |
| 371 | RRD_FLAGS old = rrd_flag_set_deleted(rm, reason); |
| 372 | if(old & RRD_FLAG_COLLECTED) |
| 373 | __atomic_sub_fetch(&rm->ri->rc->rrdhost->collected.metrics_count, 1, __ATOMIC_RELAXED); |
| 374 | } |
| 375 | |
| 376 | static ALWAYS_INLINE void rrdmetric_set_deleted_overwrite(RRDMETRIC *rm, RRD_FLAGS replacement) { |
| 377 | replacement &= ~(RRD_FLAG_COLLECTED|RRD_FLAG_ARCHIVED|RRD_FLAG_DELETED); |
| 378 | replacement |= RRD_FLAG_DELETED; |
| 379 | RRD_FLAGS old = rrd_flags_replace_atomic(&rm->flags, replacement); |
| 380 | if(old & RRD_FLAG_COLLECTED) |
| 381 | __atomic_sub_fetch(&rm->ri->rc->rrdhost->collected.metrics_count, 1, __ATOMIC_RELAXED); |
| 382 | } |
| 383 | |
| 384 | static ALWAYS_INLINE void rrdinstance_set_collected(RRDINSTANCE *ri) { |
| 385 | RRD_FLAGS old = rrd_flag_set_collected(ri); |
| 386 | if(!(old & RRD_FLAG_COLLECTED)) |
| 387 | __atomic_add_fetch(&ri->rc->rrdhost->collected.instances_count, 1, __ATOMIC_RELAXED); |
| 388 | } |
| 389 | |
| 390 | static ALWAYS_INLINE void rrdinstance_set_archived(RRDINSTANCE *ri) { |
| 391 | RRD_FLAGS old = rrd_flag_set_archived(ri); |
| 392 | if(old & RRD_FLAG_COLLECTED) |
| 393 | __atomic_sub_fetch(&ri->rc->rrdhost->collected.instances_count, 1, __ATOMIC_RELAXED); |
| 394 | } |
| 395 | |
| 396 | static ALWAYS_INLINE void rrdinstance_set_deleted(RRDINSTANCE *ri, RRD_FLAGS reason) { |
| 397 | RRD_FLAGS old = rrd_flag_set_deleted(ri, reason); |
| 398 | if(old & RRD_FLAG_COLLECTED) |
| 399 | __atomic_sub_fetch(&ri->rc->rrdhost->collected.instances_count, 1, __ATOMIC_RELAXED); |
| 400 | } |
| 401 | |
| 402 | static ALWAYS_INLINE void rrdinstance_set_deleted_overwrite(RRDINSTANCE *ri, RRD_FLAGS replacement) { |
| 403 | replacement &= ~(RRD_FLAG_COLLECTED|RRD_FLAG_ARCHIVED|RRD_FLAG_DELETED); |
| 404 | replacement |= RRD_FLAG_DELETED; |
| 405 | RRD_FLAGS old = rrd_flags_replace_atomic(&ri->flags, replacement); |
| 406 | if(old & RRD_FLAG_COLLECTED) |
| 407 | __atomic_sub_fetch(&ri->rc->rrdhost->collected.instances_count, 1, __ATOMIC_RELAXED); |
| 408 | } |
| 409 | |
| 410 | static ALWAYS_INLINE void rrdcontext_set_collected(RRDCONTEXT *rc) { |
| 411 | RRD_FLAGS old = rrd_flag_set_collected(rc); |
| 412 | if(!(old & RRD_FLAG_COLLECTED)) |
| 413 | __atomic_add_fetch(&rc->rrdhost->collected.contexts_count, 1, __ATOMIC_RELAXED); |
| 414 | } |
| 415 | |
| 416 | static ALWAYS_INLINE void rrdcontext_set_archived(RRDCONTEXT *rc) { |
| 417 | RRD_FLAGS old = rrd_flag_set_archived(rc); |
| 418 | if(old & RRD_FLAG_COLLECTED) |
| 419 | __atomic_sub_fetch(&rc->rrdhost->collected.contexts_count, 1, __ATOMIC_RELAXED); |
| 420 | } |
| 421 | |
| 422 | static ALWAYS_INLINE void rrdcontext_set_deleted(RRDCONTEXT *rc, RRD_FLAGS reason) { |
| 423 | RRD_FLAGS old = rrd_flag_set_deleted(rc, reason); |
| 424 | if(old & RRD_FLAG_COLLECTED) |
| 425 | __atomic_sub_fetch(&rc->rrdhost->collected.contexts_count, 1, __ATOMIC_RELAXED); |
| 426 | } |
| 427 | |
| 428 | // ---------------------------------------------------------------------------- |
| 429 | // helper one-liners for RRDMETRIC |
| 430 | |
| 431 | bool rrdmetric_update_retention(RRDMETRIC *rm); |
| 432 | |
| 433 | static ALWAYS_INLINE RRDMETRIC *rrdmetric_acquired_value(RRDMETRIC_ACQUIRED *rma) { |
| 434 | return dictionary_acquired_item_value((DICTIONARY_ITEM *)rma); |
| 435 | } |
| 436 | |
| 437 | static ALWAYS_INLINE RRDMETRIC_ACQUIRED *rrdmetric_acquired_dup(RRDMETRIC_ACQUIRED *rma) { |
| 438 | RRDMETRIC *rm = rrdmetric_acquired_value(rma); |
| 439 | return (RRDMETRIC_ACQUIRED *)dictionary_acquired_item_dup(rm->ri->rrdmetrics, (DICTIONARY_ITEM *)rma); |
| 440 | } |
| 441 | |
| 442 | static ALWAYS_INLINE void rrdmetric_release(RRDMETRIC_ACQUIRED *rma) { |
| 443 | RRDMETRIC *rm = rrdmetric_acquired_value(rma); |
| 444 | dictionary_acquired_item_release(rm->ri->rrdmetrics, (DICTIONARY_ITEM *)rma); |
| 445 | } |
| 446 | |
| 447 | void rrdmetric_rrddim_is_freed(RRDDIM *rd); |
| 448 | void rrdmetric_updated_rrddim_flags(RRDDIM *rd); |
| 449 | void rrdmetric_updated_rrddim_algorithm(RRDDIM *rd); |
| 450 | void rrdmetric_collected_rrddim(RRDDIM *rd); |
| 451 | void rrdmetric_not_collected_rrddim(RRDDIM *rd); |
| 452 | |
| 453 | // ---------------------------------------------------------------------------- |
| 454 | // helper one-liners for RRDINSTANCE |
| 455 | |
| 456 | static ALWAYS_INLINE RRDINSTANCE *rrdinstance_acquired_value(RRDINSTANCE_ACQUIRED *ria) { |
| 457 | return dictionary_acquired_item_value((DICTIONARY_ITEM *)ria); |
| 458 | } |
| 459 | |
| 460 | static ALWAYS_INLINE RRDINSTANCE_ACQUIRED *rrdinstance_acquired_dup(RRDINSTANCE_ACQUIRED *ria) { |
| 461 | RRDINSTANCE *ri = rrdinstance_acquired_value(ria); |
| 462 | return (RRDINSTANCE_ACQUIRED *)dictionary_acquired_item_dup(ri->rc->rrdinstances, (DICTIONARY_ITEM *)ria); |
| 463 | } |
| 464 | |
| 465 | static ALWAYS_INLINE void rrdinstance_release(RRDINSTANCE_ACQUIRED *ria) { |
| 466 | RRDINSTANCE *ri = rrdinstance_acquired_value(ria); |
| 467 | dictionary_acquired_item_release(ri->rc->rrdinstances, (DICTIONARY_ITEM *)ria); |
| 468 | } |
| 469 | |
| 470 | void rrdinstance_from_rrdset(RRDSET *st); |
| 471 | void rrdinstance_rrdset_is_freed(RRDSET *st); |
| 472 | void rrdinstance_rrdset_has_updated_retention(RRDSET *st); |
| 473 | void rrdinstance_updated_rrdset_name(RRDSET *st); |
| 474 | void rrdinstance_updated_rrdset_flags_no_action(RRDINSTANCE *ri, RRDSET *st); |
| 475 | void rrdinstance_updated_rrdset_flags(RRDSET *st); |
| 476 | void rrdinstance_collected_rrdset(RRDSET *st); |
| 477 | void rrdinstance_rrdset_not_collected(RRDSET *st); |
| 478 | |
| 479 | void rrdcontext_queue_for_post_processing(RRDCONTEXT *rc, const char *function, RRD_FLAGS flags); |
| 480 | |
| 481 | // ---------------------------------------------------------------------------- |
| 482 | // helper one-liners for RRDCONTEXT |
| 483 | |
| 484 | static ALWAYS_INLINE RRDCONTEXT *rrdcontext_acquired_value(RRDCONTEXT_ACQUIRED *rca) { |
| 485 | return dictionary_acquired_item_value((DICTIONARY_ITEM *)rca); |
| 486 | } |
| 487 | |
| 488 | static ALWAYS_INLINE RRDCONTEXT_ACQUIRED *rrdcontext_acquired_dup(RRDCONTEXT_ACQUIRED *rca) { |
| 489 | RRDCONTEXT *rc = rrdcontext_acquired_value(rca); |
| 490 | return (RRDCONTEXT_ACQUIRED *)dictionary_acquired_item_dup(rc->rrdhost->rrdctx.contexts, (DICTIONARY_ITEM *)rca); |
| 491 | } |
| 492 | |
| 493 | static ALWAYS_INLINE void rrdcontext_release(RRDCONTEXT_ACQUIRED *rca) { |
| 494 | RRDCONTEXT *rc = rrdcontext_acquired_value(rca); |
| 495 | dictionary_acquired_item_release(rc->rrdhost->rrdctx.contexts, (DICTIONARY_ITEM *)rca); |
| 496 | } |
| 497 | |
| 498 | // ---------------------------------------------------------------------------- |
| 499 | // Forward definitions |
| 500 | void load_instance_labels_on_demand(nd_uuid_t *uuid, void *data); |
| 501 | |
| 502 | void rrdcontext_recalculate_context_retention(RRDCONTEXT *rc, RRD_FLAGS reason, bool worker_jobs); |
| 503 | void rrdcontext_recalculate_host_retention(RRDHOST *host, RRD_FLAGS reason, bool worker_jobs); |
| 504 | |
| 505 | #define rrdcontext_lock(rc) spinlock_lock(&((rc)->spinlock)) |
| 506 | #define rrdcontext_unlock(rc) spinlock_unlock(&((rc)->spinlock)) |
| 507 | |
| 508 | void rrdmetric_trigger_updates(RRDMETRIC *rm, const char *function); |
| 509 | void rrdinstance_trigger_updates(RRDINSTANCE *ri, const char *function); |
| 510 | void rrdcontext_trigger_updates(RRDCONTEXT *rc, const char *function); |
| 511 | |
| 512 | void rrdinstances_create_in_rrdcontext(RRDCONTEXT *rc); |
| 513 | void rrdinstances_destroy_from_rrdcontext(RRDCONTEXT *rc); |
| 514 | |
| 515 | void rrdmetrics_destroy_from_rrdinstance(RRDINSTANCE *ri); |
| 516 | void rrdmetrics_create_in_rrdinstance(RRDINSTANCE *ri); |
| 517 | |
| 518 | void rrdmetric_from_rrddim(RRDDIM *rd); |
| 519 | |
| 520 | void rrd_reasons_to_buffer_json_array_items(RRD_FLAGS flags, BUFFER *wb); |
| 521 | |
| 522 | #define rrdcontext_version_hash(host) rrdcontext_version_hash_with_callback(host, NULL, false, NULL) |
| 523 | uint64_t rrdcontext_version_hash_with_callback( |
| 524 | RRDHOST *host, |
| 525 | void (*callback)(RRDCONTEXT *, bool, void *), |
| 526 | bool snapshot, |
| 527 | void *bundle); |
| 528 | |
| 529 | void rrdcontext_message_send_unsafe(RRDCONTEXT *rc, bool snapshot __maybe_unused, void *bundle __maybe_unused); |
| 530 | |
| 531 | void rrdcontext_update_from_collected_rrdinstance(RRDINSTANCE *ri); |
| 532 | |
| 533 | void rrdcontext_garbage_collect_single_host(RRDHOST *host, bool worker_jobs); |
| 534 | |
| 535 | void get_metric_retention_by_id(RRDHOST *host, UUIDMAP_ID id, time_t *min_first_time_t, time_t *max_last_time_t, bool *tier0_retention); |
| 536 | |
| 537 | void rrdcontext_delete_after_loading(RRDHOST *host, RRDCONTEXT *rc); |
| 538 | void rrdcontext_initial_processing_after_loading(RRDCONTEXT *rc); |
| 539 | |
| 540 | RRDLABELS *rrdinstance_labels(RRDINSTANCE *ri); |
| 541 | |
| 542 | // Bump the dbengine-rotations counter that gates extreme-cardinality |
| 543 | // protection. Called from rrdcontext_db_rotation(); the chart-cleanup |
| 544 | // trigger (rrdcontext_request_full_gc) deliberately does NOT bump it, |
| 545 | // so the guard activates only on real dbengine rotations as before. |
| 546 | void rrdcontext_count_db_rotation(void); |
| 547 | |
| 548 | bool rrdcontext_post_process_updates(RRDCONTEXT *rc, bool force, RRD_FLAGS reason, bool worker_jobs); |
| 549 | void rrdcontext_post_process_queued_contexts(RRDHOST *host); |
| 550 | void rrdcontext_dispatch_queued_contexts_to_hub(RRDHOST *host, usec_t now_ut); |
| 551 | usec_t rrdcontext_calculate_queued_dispatch_time_ut(RRDCONTEXT *rc, usec_t now_ut); |
| 552 | bool check_if_cloud_version_changed_unsafe(RRDCONTEXT *rc, bool sending); |
| 553 | bool rrdcontext_should_be_deleted(RRDCONTEXT *rc); |
| 554 | void rrdcontext_delete_from_sql_unsafe(RRDCONTEXT *rc); |
| 555 | static inline void rrdcontext_dequeue_from_post_processing(RRDCONTEXT *rc) { |
| 556 | rrdcontext_del_from_pp_queue(rc, false); |
| 557 | } |
| 558 | |
| 559 | #endif //NETDATA_RRDCONTEXT_INTERNAL_H |