@cryptotaxi247 / netdata-1 / commits / 6f1655ab9

Alert prototypes: use r/w spinlock instead of spinlock (#19410)

use r/w spinlock instead of spinlock

Costa Tsaousis committed Jan 15, 2025 at 18:30 UTC 6f1655ab9dc113b00ad4353ba2085bf9bfe54726
8 files changed +38 -21
src/database/sqlite/sqlite_functions.c
+5 -2
@@ -14,12 +14,16 @@ SQLITE_API int sqlite3_exec_monitored(
14 void *data, /* 1st argument to callback */
15 char **errmsg /* Error msg written here */
16 ) {
17 + internal_fatal(!nd_thread_runs_sql(), "THIS THREAD CANNOT RUN SQL");
18 +
19 int rc = sqlite3_exec(db, sql, callback, data, errmsg);
20 pulse_sqlite3_query_completed(rc == SQLITE_OK, rc == SQLITE_BUSY, rc == SQLITE_LOCKED);
21 return rc;
22 }
23
24 SQLITE_API int sqlite3_step_monitored(sqlite3_stmt *stmt) {
25 + internal_fatal(!nd_thread_runs_sql(), "THIS THREAD CANNOT RUN SQL");
26 +
27 int rc;
28 int cnt = 0;
29
@@ -66,8 +70,7 @@ static bool mark_database_to_recover(sqlite3_stmt *res, sqlite3 *database, int r
70 return false;
71 }
72
69 -int execute_insert(sqlite3_stmt *res)
70 -{
73 +int execute_insert(sqlite3_stmt *res) {
74 int rc;
75 rc = sqlite3_step_monitored(res);
76 if (rc == SQLITE_CORRUPT) {
src/health/health_dyncfg.c
+2 -2
@@ -659,11 +659,11 @@ static int dyncfg_health_prototype_job_action(BUFFER *result, DYNCFG_CMDS cmd, B
659 code = dyncfg_default_response(result, HTTP_RESP_OK, "already enabled");
660 else {
661 size_t matches_enabled = 0;
662 - spinlock_lock(&ap->_internal.spinlock);
662 + rw_spinlock_write_lock(&ap->_internal.rw_spinlock);
663 for(RRD_ALERT_PROTOTYPE *t = ap; t ;t = t->_internal.next)
664 if(t->match.enabled)
665 matches_enabled++;
666 - spinlock_unlock(&ap->_internal.spinlock);
666 + rw_spinlock_write_unlock(&ap->_internal.rw_spinlock);
667
668 if(!matches_enabled) {
669 code = dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, "all rules in this alert are disabled, so enabling the alert has no effect");
src/health/health_internals.h
+1 -2
@@ -53,10 +53,9 @@ typedef struct rrd_alert_prototype {
53 struct rrd_alert_config config;
54
55 struct {
56 - uint32_t uses;
56 bool enabled;
57 bool is_on_disk;
59 - SPINLOCK spinlock;
58 + RW_SPINLOCK rw_spinlock;
59 struct rrd_alert_prototype *prev, *next;
60 } _internal;
61 } RRD_ALERT_PROTOTYPE;
src/health/health_prototypes.c
+13 -15
@@ -206,7 +206,7 @@ static void health_prototype_cleanup_one_unsafe(RRD_ALERT_PROTOTYPE *ap) {
206 }
207
208 void health_prototype_cleanup(RRD_ALERT_PROTOTYPE *ap) {
209 - spinlock_lock(&ap->_internal.spinlock);
209 + rw_spinlock_write_lock(&ap->_internal.rw_spinlock);
210
211 while(ap->_internal.next) {
212 RRD_ALERT_PROTOTYPE *t = ap->_internal.next;
@@ -215,7 +215,7 @@ void health_prototype_cleanup(RRD_ALERT_PROTOTYPE *ap) {
215 freez(t);
216 }
217
218 - spinlock_unlock(&ap->_internal.spinlock);
218 + rw_spinlock_write_unlock(&ap->_internal.rw_spinlock);
219
220 health_prototype_cleanup_one_unsafe(ap);
221 }
@@ -228,7 +228,7 @@ void health_prototype_free(RRD_ALERT_PROTOTYPE *ap) {
228
229 void health_prototype_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
230 RRD_ALERT_PROTOTYPE *ap = value;
231 - spinlock_init(&ap->_internal.spinlock);
231 + rw_spinlock_init(&ap->_internal.rw_spinlock);
232 if(ap->config.source_type != DYNCFG_SOURCE_TYPE_DYNCFG)
233 ap->_internal.is_on_disk = true;
234 }
@@ -253,9 +253,9 @@ bool health_prototype_conflict_cb(const DICTIONARY_ITEM *item __maybe_unused, vo
253 nap = callocz(1, sizeof(*nap));
254 memcpy(nap, new_value, sizeof(*nap));
255
256 - spinlock_lock(&ap->_internal.spinlock);
256 + rw_spinlock_write_lock(&ap->_internal.rw_spinlock);
257 DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(ap->_internal.next, nap, _internal.prev, _internal.next);
258 - spinlock_unlock(&ap->_internal.spinlock);
258 + rw_spinlock_write_unlock(&ap->_internal.rw_spinlock);
259
260 if(nap->_internal.enabled)
261 ap->_internal.enabled = true;
@@ -263,14 +263,13 @@ bool health_prototype_conflict_cb(const DICTIONARY_ITEM *item __maybe_unused, vo
263 }
264 else {
265 // alerts with the same name replace the existing one
266 - spinlock_init(&nap->_internal.spinlock);
267 - nap->_internal.uses = ap->_internal.uses;
266 + rw_spinlock_init(&nap->_internal.rw_spinlock);
267
269 - spinlock_lock(&nap->_internal.spinlock);
270 - spinlock_lock(&ap->_internal.spinlock);
268 + rw_spinlock_write_lock(&nap->_internal.rw_spinlock);
269 + rw_spinlock_write_lock(&ap->_internal.rw_spinlock);
270 SWAP(*ap, *nap);
272 - spinlock_unlock(&ap->_internal.spinlock);
273 - spinlock_unlock(&nap->_internal.spinlock);
271 + rw_spinlock_write_unlock(&ap->_internal.rw_spinlock);
272 + rw_spinlock_write_unlock(&nap->_internal.rw_spinlock);
273
274 health_prototype_cleanup(nap);
275 memset(nap, 0, sizeof(*nap));
@@ -598,7 +597,7 @@ static void health_prototype_apply_to_rrdset(RRDSET *st, RRD_ALERT_PROTOTYPE *ap
597 if(!ap->_internal.enabled)
598 return;
599
601 - spinlock_lock(&ap->_internal.spinlock);
600 + rw_spinlock_read_lock(&ap->_internal.rw_spinlock);
601 for(size_t template = 0; template < 2; template++) {
602 bool want_template = template ? true : false;
603
@@ -617,11 +616,10 @@ static void health_prototype_apply_to_rrdset(RRDSET *st, RRD_ALERT_PROTOTYPE *ap
616 if (!prototype_matches_rrdset(st, t))
617 continue;
618
620 - if (rrdcalc_add_from_prototype(st->rrdhost, st, t))
621 - ap->_internal.uses++;
619 + rrdcalc_add_from_prototype(st->rrdhost, st, t);
620 }
621 }
624 - spinlock_unlock(&ap->_internal.spinlock);
622 + rw_spinlock_read_unlock(&ap->_internal.rw_spinlock);
623 }
624
625 void health_prototype_alerts_for_rrdset_incrementally(RRDSET *st) {
src/libnetdata/threads/threads.c
+10
@@ -64,6 +64,16 @@ static struct {
64
65 static __thread ND_THREAD *_nd_thread_info = NULL;
66 static __thread char _nd_thread_os_name[ND_THREAD_TAG_MAX + 1] = "";
67 +static __thread bool _nd_thread_can_run_sql = true;
68 +
69 +void nd_thread_can_run_sql(bool run_sql) {
70 + _nd_thread_can_run_sql = run_sql;
71 +}
72 +
73 +bool nd_thread_runs_sql(void) {
74 + return _nd_thread_can_run_sql;
75 +}
76 +
77
78 // --------------------------------------------------------------------------------------------------------------------
79 // O/S abstraction
src/libnetdata/threads/threads.h
+3
@@ -114,4 +114,7 @@ void nd_thread_rwspinlock_write_unlocked(void);
114 #define nd_thread_rwspinlock_write_unlocked() debug_dummy()
115 #endif
116
117 +void nd_thread_can_run_sql(bool exclude);
118 +bool nd_thread_runs_sql(void);
119 +
120 #endif //NETDATA_THREADS_H
src/streaming/stream-connector.c
+2
@@ -511,6 +511,8 @@ static void *stream_connector_thread(void *ptr) {
511 struct connector *sc = ptr;
512 sc->tid = gettid_cached();
513
514 + nd_thread_can_run_sql(false);
515 +
516 worker_register("STREAMCNT");
517 worker_register_job_name(WORKER_SENDER_CONNECTOR_JOB_CONNECTING, "connect");
518 worker_register_job_name(WORKER_SENDER_CONNECTOR_JOB_CONNECTED, "connected");
src/streaming/stream-thread.c
+2
@@ -381,6 +381,8 @@ static bool stream_thread_process_poll_slot(struct stream_thread *sth, nd_poll_r
381 void *stream_thread(void *ptr) {
382 struct stream_thread *sth = ptr;
383
384 + nd_thread_can_run_sql(false);
385 +
386 worker_register("STREAM");
387
388 // stream thread main event loop