@cryptotaxi247 / netdata-1 / commits / 98c7260d9

Prepare the main cleanup function for the exporting engine (#9099)

Vladimir Kobal committed May 20, 2020 at 09:30 UTC 98c7260d929a2f6ad2aabb4b27f0d77d49f6cae8
5 files changed +101 -25
exporting/clean_connectors.c
+19 -18
@@ -3,35 +3,36 @@
3 #include "exporting_engine.h"
4
5 /**
6 - * Clean the instance config.
7 - * @param ptr
6 + * Clean the instance config
7 + *
8 + * @param config an instance config structure.
9 */
9 -static void clean_instance_config(struct instance_config *ptr)
10 +static void clean_instance_config(struct instance_config *config)
11 {
11 - if (ptr->name)
12 - freez((void *)ptr->name);
12 + if (config->name)
13 + freez((void *)config->name);
14
14 - if (ptr->destination)
15 - freez((void *)ptr->destination);
15 + if (config->destination)
16 + freez((void *)config->destination);
17
17 - if (ptr->charts_pattern)
18 - simple_pattern_free(ptr->charts_pattern);
18 + if (config->charts_pattern)
19 + simple_pattern_free(config->charts_pattern);
20
20 - if (ptr->hosts_pattern)
21 - simple_pattern_free(ptr->hosts_pattern);
21 + if (config->hosts_pattern)
22 + simple_pattern_free(config->hosts_pattern);
23 }
24
25 /**
26 * Clean the allocated variables
27 *
27 - * @param ptr a pointer to the structure with variables to clean.
28 + * @param instance an instance data structure.
29 */
29 -void clean_instance(struct instance *ptr)
30 +void clean_instance(struct instance *instance)
31 {
31 - clean_instance_config(&ptr->config);
32 - if (ptr->labels)
33 - buffer_free(ptr->labels);
32 + clean_instance_config(&instance->config);
33 + if (instance->labels)
34 + buffer_free(instance->labels);
35
35 - uv_mutex_destroy(&ptr->mutex);
36 - uv_cond_destroy(&ptr->cond_var);
36 + uv_cond_destroy(&instance->cond_var);
37 + // uv_mutex_destroy(&instance->mutex);
38 }
exporting/exporting_engine.c
+54 -3
@@ -2,12 +2,63 @@
2
3 #include "exporting_engine.h"
4
5 -static void exporting_main_cleanup(void *ptr) {
5 +static struct engine *engine = NULL;
6 +
7 +/**
8 + * Clean up the main exporting thread and all connector workers on Netdata exit
9 + *
10 + * @param ptr thread data.
11 + */
12 +static void exporting_main_cleanup(void *ptr)
13 +{
14 struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
15 static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
16
17 info("cleaning up...");
18
19 + if (!engine) {
20 + static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
21 + return;
22 + }
23 +
24 + engine->exit = 1;
25 +
26 + int found = 0;
27 + usec_t max = 2 * USEC_PER_SEC, step = 50000;
28 +
29 + for (struct instance *instance = engine->instance_root; instance; instance = instance->next) {
30 + if (!instance->exited) {
31 + found++;
32 + info("stopping worker for instance %s", instance->config.name);
33 + uv_cond_signal(&instance->cond_var);
34 + } else
35 + info("found stopped worker for instance %s", instance->config.name);
36 + }
37 +
38 + while (found && max > 0) {
39 + max -= step;
40 + info("Waiting %d exporting connectors to finish...", found);
41 + sleep_usec(step);
42 + found = 0;
43 +
44 + for (struct instance *instance = engine->instance_root; instance; instance = instance->next) {
45 + if (!instance->exited)
46 + found++;
47 + }
48 + }
49 +
50 + for (struct instance *instance = engine->instance_root; instance;) {
51 + struct instance *current_instance = instance;
52 + instance = instance->next;
53 + clean_instance(current_instance);
54 + }
55 +
56 + if (engine->config.prefix)
57 + freez((void *)engine->config.prefix);
58 + if (engine->config.hostname)
59 + freez((void *)engine->config.hostname);
60 + freez(engine);
61 +
62 static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
63 }
64
@@ -24,7 +75,7 @@ void *exporting_main(void *ptr)
75 {
76 netdata_thread_cleanup_push(exporting_main_cleanup, ptr);
77
27 - struct engine *engine = read_exporting_config();
78 + engine = read_exporting_config();
79 if (!engine) {
80 info("EXPORTING: no exporting connectors configured");
81 goto cleanup;
@@ -54,7 +105,7 @@ void *exporting_main(void *ptr)
105 send_main_rusage(st_main_rusage, rd_main_user, rd_main_system);
106
107 #ifdef UNIT_TESTING
57 - break;
108 + return NULL;
109 #endif
110 }
111
exporting/exporting_engine.h
+4
@@ -180,6 +180,8 @@ struct instance {
180 size_t index;
181 struct instance *next;
182 struct engine *engine;
183 +
184 + volatile sig_atomic_t exited;
185 };
186
187 struct engine {
@@ -192,6 +194,8 @@ struct engine {
194 int mongoc_initialized;
195
196 struct instance *instance_root;
197 +
198 + volatile sig_atomic_t exit;
199 };
200
201 extern struct instance *prometheus_exporter_instance;
exporting/send_data.c
+21 -2
@@ -140,6 +140,21 @@ void simple_connector_send_buffer(int *sock, int *failures, struct instance *ins
140 }
141 }
142
143 +/**
144 + * Clean up a simple connector instance on Netdata exit
145 + *
146 + * @param instance an instance data structure.
147 + */
148 +void simple_connector_cleanup(struct instance *instance)
149 +{
150 + info("EXPORTING: cleaning up instance %s ...", instance->config.name);
151 +
152 + // TODO free allocated resources
153 +
154 + info("EXPORTING: instance %s exited", instance->config.name);
155 + instance->exited = 1;
156 +}
157 +
158 /**
159 * Simple connector worker
160 *
@@ -159,7 +174,7 @@ void simple_connector_worker(void *instance_p)
174 .tv_usec = (instance->config.timeoutms * 1000) % 1000000};
175 int failures = 0;
176
162 - while(!netdata_exit) {
177 + while(!instance->engine->exit) {
178
179 // reset the monitoring chart counters
180 stats->received_bytes =
@@ -195,7 +210,7 @@ void simple_connector_worker(void *instance_p)
210 stats->reconnects += reconnects;
211 }
212
198 - if(unlikely(netdata_exit)) break;
213 + if(unlikely(instance->engine->exit)) break;
214
215 // ------------------------------------------------------------------------
216 // if we are connected, send our buffer to the data collecting server
@@ -203,6 +218,8 @@ void simple_connector_worker(void *instance_p)
218 uv_mutex_lock(&instance->mutex);
219 uv_cond_wait(&instance->cond_var, &instance->mutex);
220
221 + if(unlikely(instance->engine->exit)) break;
222 +
223 if (likely(sock != -1)) {
224 simple_connector_send_buffer(&sock, &failures, instance);
225 } else {
@@ -238,4 +255,6 @@ void simple_connector_worker(void *instance_p)
255 break;
256 #endif
257 }
258 +
259 + simple_connector_cleanup(instance);
260 }
exporting/tests/test_exporting_engine.c
+3 -2
@@ -65,8 +65,6 @@ static void test_exporting_engine(void **state)
65 expect_value(__wrap_send_main_rusage, rd_user, NULL);
66 expect_value(__wrap_send_main_rusage, rd_system, NULL);
67
68 - expect_function_call(__wrap_info_int);
69 -
68 void *ptr = malloc(sizeof(struct netdata_static_thread));
69 assert_ptr_equal(exporting_main(ptr), NULL);
70 assert_int_equal(engine->now, 2);
@@ -668,6 +666,9 @@ static void test_simple_connector_worker(void **state)
666 expect_value(__wrap_send_internal_metrics, instance, instance);
667 will_return(__wrap_send_internal_metrics, 0);
668
669 + expect_function_call(__wrap_info_int);
670 + expect_function_call(__wrap_info_int);
671 +
672 simple_connector_worker(instance);
673
674 assert_int_equal(stats->buffered_metrics, 0);