Contexts Loading (#19336)
* do not load instances and dimensions for unknown contexts - instead of creating contexts and adding instances and dimensions * node updates to NC * unify all liveness calls * prevent wanted cache size from getting negative
Costa Tsaousis committed
Jan 7, 2025 at 21:24 UTC
84ddf0d48c0c42a07c104e9e1a6caabc2241d2f2
14 files changed
+92
-67
src/aclk/aclk.c
+29
-6
@@ -833,6 +833,29 @@ exit:
833
return NULL;
834
}
835
836
+bool aclk_host_state_update_auto(RRDHOST *host) {
837
+ int live;
838
+ switch(rrdhost_ingestion_status(host)) {
839
+ case RRDHOST_INGEST_STATUS_ARCHIVED:
840
+ case RRDHOST_INGEST_STATUS_INITIALIZING:
841
+ case RRDHOST_INGEST_STATUS_OFFLINE:
842
+ live = 0;
843
+ break;
844
+
845
+ case RRDHOST_INGEST_STATUS_REPLICATING:
846
+ // receiving replication
847
+ // no need to send this to NC
848
+ return false;
849
+
850
+ case RRDHOST_INGEST_STATUS_ONLINE:
851
+ // currently collecting data
852
+ live = 1;
853
+ break;
854
+ }
855
+ aclk_host_state_update(host, live, 1);
856
+ return true;
857
+}
858
+
859
void aclk_host_state_update(RRDHOST *host, int cmd, int queryable)
860
{
861
ND_UUID node_id;
@@ -858,7 +881,7 @@ void aclk_host_state_update(RRDHOST *host, int cmd, int queryable)
881
882
node_instance_creation_t node_instance_creation = {
883
.claim_id = claim_id_is_set(claim_id) ? claim_id.str : NULL,
861
- .hops = rrdhost_system_info_hops(host->system_info),
884
+ .hops = rrdhost_ingestion_hops(host),
885
.hostname = rrdhost_hostname(host),
886
.machine_guid = host->machine_guid};
887
@@ -869,7 +892,7 @@ void aclk_host_state_update(RRDHOST *host, int cmd, int queryable)
892
create_query->data.bin_payload.msg_name = "CreateNodeInstance";
893
nd_log(NDLS_DAEMON, NDLP_DEBUG,
894
"Registering host=%s, hops=%d", host->machine_guid,
872
- rrdhost_system_info_hops(host->system_info));
895
+ rrdhost_ingestion_hops(host));
896
897
aclk_execute_query(create_query);
898
return;
@@ -878,7 +901,7 @@ void aclk_host_state_update(RRDHOST *host, int cmd, int queryable)
901
902
aclk_query_t query = aclk_query_new(NODE_STATE_UPDATE);
903
node_instance_connection_t node_state_update = {
881
- .hops = rrdhost_system_info_hops(host->system_info),
904
+ .hops = rrdhost_ingestion_hops(host),
905
.live = cmd,
906
.queryable = queryable,
907
.session_id = aclk_session_newarch
@@ -895,7 +918,7 @@ void aclk_host_state_update(RRDHOST *host, int cmd, int queryable)
918
nd_log(NDLS_DAEMON, NDLP_DEBUG,
919
"Queuing status update for node=%s, live=%d, hops=%d, queryable=%d",
920
(char*)node_state_update.node_id, cmd,
898
- rrdhost_system_info_hops(host->system_info), queryable);
921
+ rrdhost_ingestion_hops(host), queryable);
922
923
freez((void*)node_state_update.node_id);
924
query->data.bin_payload.msg_name = "UpdateNodeInstanceConnection";
@@ -1067,7 +1090,7 @@ char *aclk_state(void)
1090
}
1091
1092
buffer_sprintf(wb, "\tStreaming Hops: %d\n\tRelationship: %s",
1070
- rrdhost_system_info_hops(host->system_info),
1093
+ rrdhost_ingestion_hops(host),
1094
host == localhost ? "self" : "child");
1095
1096
if (host != localhost)
@@ -1202,7 +1225,7 @@ char *aclk_state_json(void)
1225
json_object_object_add(nodeinstance, "node-id", tmp);
1226
}
1227
1205
- tmp = json_object_new_int(rrdhost_system_info_hops(host->system_info));
1228
+ tmp = json_object_new_int(rrdhost_ingestion_hops(host));
1229
json_object_object_add(nodeinstance, "streaming-hops", tmp);
1230
1231
tmp = json_object_new_string(host == localhost ? "self" : "child");
src/aclk/aclk.h
+2
@@ -83,6 +83,8 @@ extern struct aclk_shared_state {
83
} aclk_shared_state;
84
85
void aclk_host_state_update(RRDHOST *host, int cmd, int queryable);
86
+bool aclk_host_state_update_auto(RRDHOST *host);
87
+
88
void aclk_send_node_instances(void);
89
90
void aclk_send_bin_msg(char *msg, size_t msg_len, enum aclk_topics subtopic, const char *msgname);
src/aclk/aclk_rx_msgs.c
+3
-7
@@ -281,14 +281,10 @@ int create_node_instance_result(const char *msg, size_t msg_len)
281
282
RRDHOST *host = rrdhost_find_by_guid(res.machine_guid);
283
if (likely(host)) {
284
- if (host == localhost) {
285
- node_state_update.live = 1;
286
- node_state_update.hops = 0;
287
- } else {
288
- node_state_update.live = (!rrdhost_flag_check(host, RRDHOST_FLAG_ORPHAN));
289
- node_state_update.hops = rrdhost_system_info_hops(host->system_info);
290
- }
284
+ node_state_update.live = rrdhost_is_local(host) ? 1 : 0;
285
+ node_state_update.hops = rrdhost_ingestion_hops(host);
286
node_state_update.capabilities = aclk_get_node_instance_capas(host);
287
+ schedule_node_state_update(host, 5000);
288
}
289
290
CLAIM_ID claim_id = claim_id_get();
src/database/contexts/worker.c
+9
-14
@@ -33,7 +33,7 @@ static void rrdinstance_load_dimension_callback(SQL_DIMENSION_DATA *sd, void *da
33
RRDCONTEXT_ACQUIRED *rca = (RRDCONTEXT_ACQUIRED *)dictionary_get_and_acquire_item(host->rrdctx.contexts, sd->context);
34
if(!rca) {
35
nd_log(NDLS_DAEMON, NDLP_ERR,
36
- "RRDCONTEXT: context '%s' is not found in host '%s'",
36
+ "RRDCONTEXT: context '%s' is not found in host '%s' - not loading dimensions",
37
sd->context, rrdhost_hostname(host));
38
return;
39
}
@@ -43,7 +43,7 @@ static void rrdinstance_load_dimension_callback(SQL_DIMENSION_DATA *sd, void *da
43
if(!ria) {
44
rrdcontext_release(rca);
45
nd_log(NDLS_DAEMON, NDLP_ERR,
46
- "RRDCONTEXT: instance '%s' of context '%s' is not found in host '%s'",
46
+ "RRDCONTEXT: instance '%s' of context '%s' is not found in host '%s' - not loading dimensions",
47
sd->chart_id, sd->context, rrdhost_hostname(host));
48
return;
49
}
@@ -67,18 +67,13 @@ static void rrdinstance_load_dimension_callback(SQL_DIMENSION_DATA *sd, void *da
67
static void rrdinstance_load_instance_callback(SQL_CHART_DATA *sc, void *data) {
68
RRDHOST *host = data;
69
70
- RRDCONTEXT tc = {
71
- .id = string_strdupz(sc->context),
72
- .title = string_strdupz(sc->title),
73
- .units = string_strdupz(sc->units),
74
- .family = string_strdupz(sc->family),
75
- .priority = sc->priority,
76
- .chart_type = sc->chart_type,
77
- .flags = RRD_FLAG_ARCHIVED | RRD_FLAG_UPDATE_REASON_LOAD_SQL, // no need for atomics
78
- .rrdhost = host,
79
- };
80
-
81
- RRDCONTEXT_ACQUIRED *rca = (RRDCONTEXT_ACQUIRED *)dictionary_set_and_acquire_item(host->rrdctx.contexts, string2str(tc.id), &tc, sizeof(tc));
70
+ RRDCONTEXT_ACQUIRED *rca = (RRDCONTEXT_ACQUIRED *)dictionary_get_and_acquire_item(host->rrdctx.contexts, sc->context);
71
+ if(!rca) {
72
+ nd_log(NDLS_DAEMON, NDLP_ERR,
73
+ "RRDCONTEXT: context '%s' is not found in host '%s' - not loadings instances",
74
+ sc->context, rrdhost_hostname(host));
75
+ return;
76
+ }
77
RRDCONTEXT *rc = rrdcontext_acquired_value(rca);
78
79
RRDINSTANCE tri = {
src/database/engine/cache.c
+5
-2
@@ -403,7 +403,7 @@ static inline size_t cache_usage_per1000(PGC *cache, size_t *size_to_evict) {
403
wanted_cache_size = referenced_size + dirty;
404
405
// if we don't have enough clean pages, there is no reason to be aggressive or critical
406
- if(wanted_cache_size < current_cache_size - clean)
406
+ if(wanted_cache_size < (current_cache_size - clean) && current_cache_size > clean)
407
wanted_cache_size = current_cache_size - clean;
408
409
if(cache->config.out_of_memory_protection_bytes) {
@@ -415,7 +415,10 @@ static inline size_t cache_usage_per1000(PGC *cache, size_t *size_to_evict) {
415
const uint64_t min_available = cache->config.out_of_memory_protection_bytes;
416
if (sm.ram_available_bytes < min_available) {
417
// we must shrink
418
- wanted_cache_size = current_cache_size - (min_available - sm.ram_available_bytes);
418
+ if(current_cache_size > (min_available - sm.ram_available_bytes))
419
+ wanted_cache_size = current_cache_size - (min_available - sm.ram_available_bytes);
420
+ else
421
+ wanted_cache_size = hot + dirty;
422
}
423
else if(cache->config.use_all_ram) {
424
// we can grow
src/database/rrd.h
+6
-2
@@ -1263,9 +1263,13 @@ extern RRDHOST *localhost;
1263
#define rrdhost_sender_replicating_charts_minus_one(host) (__atomic_sub_fetch(&((host)->stream.snd.status.replication.charts), 1, __ATOMIC_RELAXED))
1264
#define rrdhost_sender_replicating_charts_zero(host) (__atomic_store_n(&((host)->stream.snd.status.replication.charts), 0, __ATOMIC_RELAXED))
1265
1266
-#define rrdhost_is_online(host) ( \
1266
+#define rrdhost_is_local(host) ( \
1267
(host) == localhost || \
1268
- rrdhost_option_check(host, RRDHOST_OPTION_VIRTUAL_HOST) || \
1268
+ rrdhost_option_check(host, RRDHOST_OPTION_VIRTUAL_HOST) \
1269
+ )
1270
+
1271
+#define rrdhost_is_online(host) ( \
1272
+ rrdhost_is_local(host) || \
1273
(rrdhost_flag_check(host, RRDHOST_FLAG_COLLECTOR_ONLINE) && !rrdhost_flag_check(host, RRDHOST_FLAG_ORPHAN)) \
1274
)
1275
src/database/rrdfunctions.c
+1
-1
@@ -296,7 +296,7 @@ int rrd_functions_find_by_name(RRDHOST *host, BUFFER *wb, const char *name, size
296
rrd_collector_running(rdcf->collector) ? "yes" : "no",
297
host->stream.rcv.status.tid, host->stream.snd.status.tid,
298
state_id, rdcf->rrdhost_state_id,
299
- rrdhost_system_info_hops(host->system_info)
299
+ rrdhost_ingestion_hops(host)
300
);
301
302
dictionary_acquired_item_release(host->functions, *item);
src/database/sqlite/sqlite_aclk.c
+5
-11
@@ -333,11 +333,8 @@ static void node_update_timer_cb(uv_timer_t *handle)
333
struct aclk_sync_cfg_t *ahc = handle->data;
334
RRDHOST *host = ahc->host;
335
336
- rrdhost_receiver_lock(host);
337
- int live = (host == localhost || host->receiver || !(rrdhost_flag_check(host, RRDHOST_FLAG_ORPHAN))) ? 1 : 0;
338
- rrdhost_receiver_unlock(host);
339
- nd_log(NDLS_ACLK, NDLP_DEBUG,"Timer: Sending node update info for %s, LIVE = %d", rrdhost_hostname(host), live);
340
- aclk_host_state_update(host, live, 1);
336
+ if(aclk_host_state_update_auto(host))
337
+ uv_timer_stop(&ahc->timer);
338
}
339
340
static void close_callback(uv_handle_t *handle, void *data __maybe_unused)
@@ -426,19 +423,16 @@ static void aclk_synchronization(void *arg)
423
uv_timer_stop(&ahc->timer);
424
425
ahc->timer.data = ahc;
429
- int rc = uv_timer_start(&ahc->timer, node_update_timer_cb, schedule_time, 0);
426
+ int rc = uv_timer_start(&ahc->timer, node_update_timer_cb, schedule_time, 5000);
427
if (!rc)
428
break; // Timer started, exit
429
}
430
}
431
432
// This is fallback if timer fails
436
- rrdhost_receiver_lock(host);
437
- int live = (host == localhost || host->receiver || !(rrdhost_flag_check(host, RRDHOST_FLAG_ORPHAN))) ? 1 : 0;
438
- rrdhost_receiver_unlock(host);
439
- aclk_host_state_update(host, live, 1);
440
- nd_log(NDLS_ACLK, NDLP_DEBUG,"Sending node update info for %s, LIVE = %d", rrdhost_hostname(host), live);
433
+ aclk_host_state_update_auto(host);
434
break;
435
+
436
case ACLK_DATABASE_NODE_UNREGISTER:
437
sql_unregister_node(cmd.param[0]);
438
break;
src/database/sqlite/sqlite_aclk_node.c
+1
-5
@@ -135,27 +135,23 @@ void aclk_check_node_info_and_collectors(void)
135
if (!wc->node_info_send_time && !wc->node_collectors_send)
136
continue;
137
138
- bool replicating = false;
139
-
138
if (unlikely(rrdhost_receiver_replicating_charts(host))) {
139
internal_error(true, "ACLK SYNC: Host %s is still replicating in", rrdhost_hostname(host));
140
replicating_rcv++;
141
replicating_rcv_host = host->hostname;
144
- replicating = true;
142
}
143
144
if (unlikely(rrdhost_sender_replicating_charts(host))) {
145
internal_error(true, "ACLK SYNC: Host %s is still replicating out", rrdhost_hostname(host));
146
replicating_snd++;
147
replicating_snd_host = host->hostname;
151
- replicating = true;
148
}
149
150
#ifdef REPLICATION_TRACKING
151
replication_tracking_counters(host, &replay_counters);
152
#endif
153
158
- if(replicating)
154
+ if(replicating_rcv)
155
continue;
156
157
bool pp_queue_empty = !(host->rrdctx.pp_queue && dictionary_entries(host->rrdctx.pp_queue));
src/database/sqlite/sqlite_metadata.c
+3
-5
@@ -458,10 +458,8 @@ struct node_instance_list *get_node_list(void)
458
459
uuid_copy(node_list[row].host_id, *host_id);
460
node_list[row].queryable = 1;
461
- node_list[row].live =
462
- (host == localhost || host->receiver || !(rrdhost_flag_check(host, RRDHOST_FLAG_ORPHAN))) ? 1 : 0;
463
- node_list[row].hops = host->system_info ? rrdhost_system_info_hops(host->system_info) :
464
- uuid_eq(*host_id, localhost->host_id.uuid) ? 0 : 1;
461
+ node_list[row].live = rrdhost_ingestion_status(host) == RRDHOST_INGEST_STATUS_ONLINE ? 1 : 0;
462
+ node_list[row].hops = rrdhost_ingestion_hops(host);
463
node_list[row].hostname =
464
sqlite3_column_bytes(res, 2) ? strdupz((char *)sqlite3_column_text(res, 2)) : NULL;
465
}
@@ -938,7 +936,7 @@ static int store_host_metadata(RRDHOST *host)
936
SQLITE_BIND_FAIL(bind_fail, bind_text_null(res, ++param, rrdhost_os(host), 1));
937
SQLITE_BIND_FAIL(bind_fail, bind_text_null(res, ++param, rrdhost_timezone(host), 1));
938
SQLITE_BIND_FAIL(bind_fail, bind_text_null(res, ++param, "", 1));
941
- SQLITE_BIND_FAIL(bind_fail, sqlite3_bind_int(res, ++param, host->system_info ? rrdhost_system_info_hops(host->system_info) : 0));
939
+ SQLITE_BIND_FAIL(bind_fail, sqlite3_bind_int(res, ++param, rrdhost_ingestion_hops(host)));
940
SQLITE_BIND_FAIL(bind_fail, sqlite3_bind_int(res, ++param, host->rrd_memory_mode));
941
SQLITE_BIND_FAIL(bind_fail, bind_text_null(res, ++param, rrdhost_abbrev_timezone(host), 1));
942
SQLITE_BIND_FAIL(bind_fail, sqlite3_bind_int(res, ++param, host->utc_offset));
src/streaming/rrdhost-status.c
+19
-7
@@ -96,6 +96,18 @@ static NETDATA_DOUBLE rrdhost_sender_replication_completion_unsafe(RRDHOST *host
96
return completion;
97
}
98
99
+RRDHOST_INGEST_STATUS rrdhost_ingestion_status(RRDHOST *host) {
100
+ RRDHOST_STATUS status;
101
+ rrdhost_status(host, now_realtime_sec(), &status);
102
+ return status.ingest.status;
103
+}
104
+
105
+int16_t rrdhost_ingestion_hops(RRDHOST *host) {
106
+ if(rrdhost_is_local(host)) return 0;
107
+ if(!host->system_info) return 1;
108
+ return rrdhost_system_info_hops(host->system_info);
109
+}
110
+
111
void rrdhost_status(RRDHOST *host, time_t now, RRDHOST_STATUS *s) {
112
memset(s, 0, sizeof(*s));
113
@@ -130,7 +142,7 @@ void rrdhost_status(RRDHOST *host, time_t now, RRDHOST_STATUS *s) {
142
s->ingest.reason = (online) ? STREAM_HANDSHAKE_NEVER : host->stream.rcv.status.exit_reason;
143
144
rrdhost_receiver_lock(host);
133
- s->ingest.hops = (int16_t)(host->system_info ? rrdhost_system_info_hops(host->system_info) : (host == localhost) ? 0 : 1);
145
+ s->ingest.hops = rrdhost_ingestion_hops(host);
146
bool has_receiver = false;
147
if (host->receiver && rrdhost_flag_check(host, RRDHOST_FLAG_COLLECTOR_ONLINE)) {
148
has_receiver = true;
@@ -144,16 +156,20 @@ void rrdhost_status(RRDHOST *host, time_t now, RRDHOST_STATUS *s) {
156
}
157
rrdhost_receiver_unlock(host);
158
159
+ s->ingest.collected.metrics = __atomic_load_n(&host->collected.metrics_count, __ATOMIC_RELAXED);
160
+ s->ingest.collected.instances = __atomic_load_n(&host->collected.instances_count, __ATOMIC_RELAXED);
161
+ s->ingest.collected.contexts = __atomic_load_n(&host->collected.contexts_count, __ATOMIC_RELAXED);
162
+
163
if (online) {
164
if(s->db.status == RRDHOST_DB_STATUS_INITIALIZING)
165
s->ingest.status = RRDHOST_INGEST_STATUS_INITIALIZING;
166
151
- else if (host == localhost || rrdhost_option_check(host, RRDHOST_OPTION_VIRTUAL_HOST)) {
167
+ else if (rrdhost_is_local(host)) {
168
s->ingest.status = RRDHOST_INGEST_STATUS_ONLINE;
169
s->ingest.since = netdata_start_time;
170
}
171
156
- else if (s->ingest.replication.in_progress)
172
+ else if (s->ingest.replication.in_progress || !s->ingest.collected.metrics)
173
s->ingest.status = RRDHOST_INGEST_STATUS_REPLICATING;
174
175
else
@@ -169,10 +185,6 @@ void rrdhost_status(RRDHOST *host, time_t now, RRDHOST_STATUS *s) {
185
s->ingest.status = RRDHOST_INGEST_STATUS_OFFLINE;
186
}
187
172
- s->ingest.collected.metrics = __atomic_load_n(&host->collected.metrics_count, __ATOMIC_RELAXED);
173
- s->ingest.collected.instances = __atomic_load_n(&host->collected.instances_count, __ATOMIC_RELAXED);
174
- s->ingest.collected.contexts = __atomic_load_n(&host->collected.contexts_count, __ATOMIC_RELAXED);
175
-
188
if(host == localhost)
189
s->ingest.type = RRDHOST_INGEST_TYPE_LOCALHOST;
190
else if(has_receiver)
src/streaming/rrdhost-status.h
+7
-5
@@ -16,11 +16,11 @@ typedef enum __attribute__((packed)) {
16
} RRDHOST_DB_LIVENESS;
17
18
typedef enum __attribute__((packed)) {
19
- RRDHOST_INGEST_STATUS_ARCHIVED = 0,
20
- RRDHOST_INGEST_STATUS_INITIALIZING,
21
- RRDHOST_INGEST_STATUS_REPLICATING,
22
- RRDHOST_INGEST_STATUS_ONLINE,
23
- RRDHOST_INGEST_STATUS_OFFLINE,
19
+ RRDHOST_INGEST_STATUS_ARCHIVED = 0, // an old host in the database (never connected during this session)
20
+ RRDHOST_INGEST_STATUS_INITIALIZING, // contexts are still loading
21
+ RRDHOST_INGEST_STATUS_REPLICATING, // receiving replication
22
+ RRDHOST_INGEST_STATUS_ONLINE, // currently collecting data
23
+ RRDHOST_INGEST_STATUS_OFFLINE, // a disconnected node
24
} RRDHOST_INGEST_STATUS;
25
26
typedef enum __attribute__((packed)) {
@@ -166,5 +166,7 @@ typedef struct rrdhost_status_t {
166
} RRDHOST_STATUS;
167
168
void rrdhost_status(RRDHOST *host, time_t now, RRDHOST_STATUS *s);
169
+RRDHOST_INGEST_STATUS rrdhost_ingestion_status(RRDHOST *host);
170
+int16_t rrdhost_ingestion_hops(RRDHOST *host);
171
172
#endif //NETDATA_RRDHOST_STATUS_H
src/streaming/stream-connector.c
+1
-1
@@ -274,7 +274,7 @@ bool stream_connect(struct sender_state *s, uint16_t default_port, time_t timeou
274
// make sure the socket is closed
275
nd_sock_close(&s->sock);
276
277
- s->hops = (int16_t)(rrdhost_system_info_hops(host->system_info) + 1);
277
+ s->hops = (int16_t)(rrdhost_ingestion_hops(s->host) + 1);
278
279
// reset this to make sure we have its current value
280
s->sock.verify_certificate = netdata_ssl_validate_certificate_sender;
src/web/api/v1/api_v1_info.c
+1
-1
@@ -38,7 +38,7 @@ static inline void web_client_api_request_v1_info_mirrored_hosts_status(BUFFER *
38
buffer_json_add_array_item_object(wb);
39
40
buffer_json_member_add_string(wb, "hostname", rrdhost_hostname(host));
41
- buffer_json_member_add_uint64(wb, "hops", host->system_info ? rrdhost_system_info_hops(host->system_info) : (host == localhost) ? 0 : 1);
41
+ buffer_json_member_add_int64(wb, "hops", rrdhost_ingestion_hops(host));
42
buffer_json_member_add_boolean(wb, "reachable", (host == localhost || !rrdhost_flag_check(host, RRDHOST_FLAG_ORPHAN)));
43
44
buffer_json_member_add_string(wb, "guid", host->machine_guid);