| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #include "rrdcontext-internal.h" |
| 4 | |
| 5 | ssize_t query_scope_foreach_host(SIMPLE_PATTERN *scope_hosts_sp, SIMPLE_PATTERN *hosts_sp, |
| 6 | foreach_host_cb_t cb, void *data, |
| 7 | struct query_versions *versions, |
| 8 | char *host_node_id_str) { |
| 9 | char uuid[UUID_STR_LEN]; |
| 10 | if(!host_node_id_str) host_node_id_str = uuid; |
| 11 | host_node_id_str[0] = '\0'; |
| 12 | |
| 13 | RRDHOST *host; |
| 14 | ssize_t added = 0; |
| 15 | uint64_t v_hash = 0; |
| 16 | uint64_t h_hash = 0; |
| 17 | uint64_t a_hash = 0; |
| 18 | uint64_t t_hash = 0; |
| 19 | |
| 20 | dfe_start_read(rrdhost_root_index, host) { |
| 21 | if(!UUIDiszero(host->node_id)) |
| 22 | uuid_unparse_lower(host->node_id.uuid, host_node_id_str); |
| 23 | else |
| 24 | host_node_id_str[0] = '\0'; |
| 25 | |
| 26 | SIMPLE_PATTERN_RESULT match = SP_MATCHED_POSITIVE; |
| 27 | if(scope_hosts_sp) { |
| 28 | match = simple_pattern_matches_string_extract(scope_hosts_sp, host->hostname, NULL, 0); |
| 29 | if(match == SP_NOT_MATCHED) { |
| 30 | match = simple_pattern_matches_extract(scope_hosts_sp, host->machine_guid, NULL, 0); |
| 31 | if(match == SP_NOT_MATCHED && *host_node_id_str) |
| 32 | match = simple_pattern_matches_extract(scope_hosts_sp, host_node_id_str, NULL, 0); |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | if(match != SP_MATCHED_POSITIVE) |
| 37 | continue; |
| 38 | |
| 39 | dfe_unlock(host); |
| 40 | |
| 41 | if(hosts_sp) { |
| 42 | match = simple_pattern_matches_string_extract(hosts_sp, host->hostname, NULL, 0); |
| 43 | if(match == SP_NOT_MATCHED) { |
| 44 | match = simple_pattern_matches_extract(hosts_sp, host->machine_guid, NULL, 0); |
| 45 | if(match == SP_NOT_MATCHED && *host_node_id_str) |
| 46 | match = simple_pattern_matches_extract(hosts_sp, host_node_id_str, NULL, 0); |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | bool queryable_host = (match == SP_MATCHED_POSITIVE); |
| 51 | |
| 52 | v_hash += dictionary_version(host->rrdctx.contexts); |
| 53 | h_hash += rrdcontext_queue_version(&host->rrdctx.hub_queue); |
| 54 | a_hash += dictionary_version(host->rrdcalc_root_index); |
| 55 | t_hash += __atomic_load_n(&host->health_transitions, __ATOMIC_RELAXED); |
| 56 | ssize_t ret = cb(data, host, queryable_host); |
| 57 | if(ret < 0) { |
| 58 | added = ret; |
| 59 | break; |
| 60 | } |
| 61 | added += ret; |
| 62 | } |
| 63 | dfe_done(host); |
| 64 | |
| 65 | if(versions) { |
| 66 | versions->contexts_hard_hash = v_hash; |
| 67 | versions->contexts_soft_hash = h_hash; |
| 68 | versions->alerts_hard_hash = a_hash; |
| 69 | versions->alerts_soft_hash = t_hash; |
| 70 | } |
| 71 | |
| 72 | return added; |
| 73 | } |
| 74 | |
| 75 | ssize_t query_scope_foreach_context(RRDHOST *host, const char *scope_contexts, SIMPLE_PATTERN *scope_contexts_sp, |
| 76 | SIMPLE_PATTERN *contexts_sp, foreach_context_cb_t cb, bool queryable_host, void *data) { |
| 77 | if(unlikely(!host->rrdctx.contexts)) |
| 78 | return 0; |
| 79 | |
| 80 | ssize_t added = 0; |
| 81 | |
| 82 | RRDCONTEXT_ACQUIRED *rca = NULL; |
| 83 | |
| 84 | if(scope_contexts) |
| 85 | rca = (RRDCONTEXT_ACQUIRED *)dictionary_get_and_acquire_item(host->rrdctx.contexts, scope_contexts); |
| 86 | |
| 87 | if(likely(rca)) { |
| 88 | // we found it! |
| 89 | |
| 90 | bool queryable_context = queryable_host; |
| 91 | RRDCONTEXT *rc = rrdcontext_acquired_value(rca); |
| 92 | if(queryable_context && contexts_sp && !simple_pattern_matches_string(contexts_sp, rc->id)) |
| 93 | queryable_context = false; |
| 94 | |
| 95 | added = cb(data, rca, queryable_context); |
| 96 | |
| 97 | rrdcontext_release(rca); |
| 98 | } |
| 99 | else { |
| 100 | // Probably it is a pattern, we need to search for it... |
| 101 | RRDCONTEXT *rc; |
| 102 | dfe_start_read(host->rrdctx.contexts, rc) { |
| 103 | if(scope_contexts_sp && !simple_pattern_matches_string(scope_contexts_sp, rc->id)) |
| 104 | continue; |
| 105 | |
| 106 | dfe_unlock(rc); |
| 107 | |
| 108 | bool queryable_context = queryable_host; |
| 109 | if(queryable_context && contexts_sp && !simple_pattern_matches_string(contexts_sp, rc->id)) |
| 110 | queryable_context = false; |
| 111 | |
| 112 | ssize_t ret = cb(data, (RRDCONTEXT_ACQUIRED *)rc_dfe.item, queryable_context); |
| 113 | |
| 114 | if(ret < 0) { |
| 115 | added = ret; |
| 116 | break; |
| 117 | } |
| 118 | |
| 119 | added += ret; |
| 120 | } |
| 121 | dfe_done(rc); |
| 122 | } |
| 123 | |
| 124 | return added; |
| 125 | } |
| 126 |