master
c 232 lines 7.75 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "rrdcontext-internal.h"
4
5 static __thread size_t th_ignored_metrics = 0, th_ignored_instances = 0, th_zero_retention_metrics = 0;
6
7 static void rrdinstance_load_clabel(SQL_CLABEL_DATA *sld, void *data) {
8 RRDINSTANCE *ri = data;
9 rrdlabels_add(ri->rrdlabels, sld->label_key, sld->label_value, sld->label_source);
10 }
11
12 void load_instance_labels_on_demand(nd_uuid_t *uuid, void *data) {
13 ctx_get_label_list(uuid, rrdinstance_load_clabel, data);
14 }
15
16 static void rrdinstance_load_dimension_callback(SQL_DIMENSION_DATA *sd, void *data) {
17 RRDHOST *host = data;
18
19 UUIDMAP_ID id = uuidmap_create(sd->dim_id);
20 time_t min_first_time_t = LONG_MAX, max_last_time_t = 0;
21 get_metric_retention_by_id(host, id, &min_first_time_t, &max_last_time_t, NULL);
22 if((!min_first_time_t || min_first_time_t == LONG_MAX) && !max_last_time_t) {
23 uuidmap_free(id);
24 th_zero_retention_metrics++;
25 return;
26 }
27
28 RRDCONTEXT_ACQUIRED *rca = (RRDCONTEXT_ACQUIRED *)dictionary_get_and_acquire_item(host->rrdctx.contexts, sd->context);
29 if(!rca) {
30 th_ignored_metrics++;
31 uuidmap_free(id);
32 return;
33 }
34 RRDCONTEXT *rc = rrdcontext_acquired_value(rca);
35 if(!rc) {
36 th_ignored_metrics++;
37 dictionary_acquired_item_release(host->rrdctx.contexts, (DICTIONARY_ITEM *)rca);
38 uuidmap_free(id);
39 return;
40 }
41
42 RRDINSTANCE_ACQUIRED *ria = (RRDINSTANCE_ACQUIRED *)dictionary_get_and_acquire_item(rc->rrdinstances, sd->chart_id);
43 if(!ria) {
44 th_ignored_metrics++;
45 rrdcontext_release(rca);
46 uuidmap_free(id);
47 return;
48 }
49 RRDINSTANCE *ri = rrdinstance_acquired_value(ria);
50 if(!ri) {
51 th_ignored_metrics++;
52 dictionary_acquired_item_release(rc->rrdinstances, (DICTIONARY_ITEM *)ria);
53 rrdcontext_release(rca);
54 uuidmap_free(id);
55 return;
56 }
57
58 RRDMETRIC trm = {
59 .uuid = id,
60 .id = string_strdupz(sd->id),
61 .name = string_strdupz(sd->name),
62 .flags = RRD_FLAG_ARCHIVED | RRD_FLAG_UPDATE_REASON_LOAD_SQL, // no need for atomic
63 .algorithm = (RRD_ALGORITHM)sd->algorithm,
64 };
65 if(sd->hidden) trm.flags |= RRD_FLAG_HIDDEN;
66
67 dictionary_set(ri->rrdmetrics, string2str(trm.id), &trm, sizeof(trm));
68
69 rrdinstance_release(ria);
70 rrdcontext_release(rca);
71 }
72
73 static void rrdinstance_load_instance_callback(SQL_CHART_DATA *sc, void *data) {
74 RRDHOST *host = data;
75
76 RRDCONTEXT tc = {
77 .id = string_strdupz(sc->context),
78 .title = string_strdupz(sc->title),
79 .units = string_strdupz(sc->units),
80 .family = string_strdupz(sc->family),
81 .priority = sc->priority,
82 .chart_type = sc->chart_type,
83 .flags = RRD_FLAG_ARCHIVED | RRD_FLAG_UPDATE_REASON_LOAD_SQL, // no need for atomics
84 .rrdhost = host,
85 };
86
87 RRDCONTEXT_ACQUIRED *rca = (RRDCONTEXT_ACQUIRED *)dictionary_set_and_acquire_item(host->rrdctx.contexts, string2str(tc.id), &tc, sizeof(tc));
88 if(!rca) {
89 th_ignored_instances++;
90 string_freez(tc.id);
91 string_freez(tc.title);
92 string_freez(tc.units);
93 string_freez(tc.family);
94 return;
95 }
96
97 RRDCONTEXT *rc = rrdcontext_acquired_value(rca);
98 if(!rc) {
99 th_ignored_instances++;
100 rrdcontext_release(rca);
101 return;
102 }
103
104 RRDINSTANCE tri = {
105 .uuid = uuidmap_create(sc->chart_id),
106 .id = string_strdupz(sc->id),
107 .name = string_strdupz(sc->name),
108 .title = string_strdupz(sc->title),
109 .units = string_strdupz(sc->units),
110 .family = string_strdupz(sc->family),
111 .chart_type = sc->chart_type,
112 .priority = sc->priority,
113 .update_every_s = sc->update_every,
114 .flags = RRD_FLAG_ARCHIVED | RRD_FLAG_UPDATE_REASON_LOAD_SQL, // no need for atomics
115 };
116
117 RRDINSTANCE_ACQUIRED *ria = (RRDINSTANCE_ACQUIRED *)dictionary_set_and_acquire_item(rc->rrdinstances, sc->id, &tri, sizeof(tri));
118 if(!ria) {
119 th_ignored_instances++;
120 uuidmap_free(tri.uuid);
121 string_freez(tri.id);
122 string_freez(tri.name);
123 string_freez(tri.title);
124 string_freez(tri.units);
125 string_freez(tri.family);
126 rrdcontext_release(rca);
127 return;
128 }
129
130 rrdinstance_release(ria);
131 rrdcontext_release(rca);
132 }
133
134 static void rrdcontext_load_context_callback(VERSIONED_CONTEXT_DATA *ctx_data, void *data) {
135 RRDHOST *host = data;
136 (void)host;
137
138 RRDCONTEXT trc = {
139 .id = string_strdupz(ctx_data->id),
140 .flags = RRD_FLAG_ARCHIVED | RRD_FLAG_UPDATE_REASON_LOAD_SQL, // no need for atomics
141
142 // no need to set more data here
143 // we only need the hub data
144
145 .hub = *ctx_data,
146 };
147 dictionary_set(host->rrdctx.contexts, string2str(trc.id), &trc, sizeof(trc));
148 }
149
150 void rrdhost_load_rrdcontext_data(RRDHOST *host) {
151 if(host->rrdctx.contexts) return;
152
153 rrdhost_create_rrdcontexts(host);
154 if (host->rrd_memory_mode != RRD_DB_MODE_DBENGINE)
155 return;
156
157 th_ignored_metrics = th_ignored_instances = th_zero_retention_metrics = 0;
158
159 ctx_get_context_list(&host->host_id.uuid, rrdcontext_load_context_callback, host);
160 if (unlikely(exit_initiated_get()))
161 return;
162
163 ctx_get_chart_list(&host->host_id.uuid, rrdinstance_load_instance_callback, host);
164 if (unlikely(exit_initiated_get()))
165 return;
166
167 ctx_get_dimension_list(&host->host_id.uuid, rrdinstance_load_dimension_callback, host);
168 if (unlikely(exit_initiated_get()))
169 return;
170
171 size_t ignored_metrics = th_ignored_metrics, ignored_instances = th_ignored_instances, zero_retention_metrics = th_zero_retention_metrics;
172 size_t loaded_metrics = 0, loaded_instances = 0, loaded_contexts = 0;
173 size_t loaded_and_deleted_instances = 0, loaded_and_deleted_contexts = 0;
174
175 RRDCONTEXT *rc;
176 dfe_start_read(host->rrdctx.contexts, rc) {
177 if (unlikely(exit_initiated_get()))
178 break;
179
180 size_t instances = 0;
181
182 RRDINSTANCE *ri;
183 dfe_start_write(rc->rrdinstances, ri) {
184 size_t metrics = 0;
185
186 RRDMETRIC *rm;
187 dfe_start_read(ri->rrdmetrics, rm) {
188 rrdmetric_trigger_updates(rm, __FUNCTION__ );
189 loaded_metrics++;
190 metrics++;
191 }
192 dfe_done(rm);
193 dictionary_garbage_collect(ri->rrdmetrics);
194
195 if(!metrics) {
196 dictionary_del(rc->rrdinstances, ri_dfe.name);
197 loaded_and_deleted_instances++;
198 }
199 else {
200 rrdinstance_trigger_updates(ri, __FUNCTION__);
201 loaded_instances++;
202 instances++;
203 }
204 }
205 dfe_done(ri);
206 dictionary_garbage_collect(rc->rrdinstances);
207
208 if(!instances) {
209 metadata_queue_ctx_host_cleanup(&host->host_id.uuid, rc_dfe.name);
210 rrdcontext_delete_after_loading(host, rc);
211 loaded_and_deleted_contexts++;
212 }
213 else {
214 rrdcontext_trigger_updates(rc, __FUNCTION__);
215 rrdcontext_initial_processing_after_loading(rc);
216 loaded_contexts++;
217 }
218 }
219 dfe_done(rc);
220 dictionary_garbage_collect(host->rrdctx.contexts);
221 rrdcontext_garbage_collect_single_host(host, false);
222
223 nd_log(NDLS_DAEMON, ignored_metrics || ignored_instances ? NDLP_WARNING : NDLP_NOTICE,
224 "RRDCONTEXT: metadata for node '%s': "
225 "contexts %zu (deleted %zu), "
226 "instances %zu (deleted %zu, ignored %zu), and "
227 "metrics %zu (ignored %zu, zero retention %zu)",
228 rrdhost_hostname(host),
229 loaded_contexts, loaded_and_deleted_contexts,
230 loaded_instances, loaded_and_deleted_instances, ignored_instances,
231 loaded_metrics, ignored_metrics, zero_retention_metrics);
232 }