@cryptotaxi247 / netdata-1 / commits / 5ecd4b4a3

Clean sqlite prepared statements on thread shutdown (#13193)

* Clean sqlite prepared statements on thread shutdown * Add note for pending statements to finalize

Stelios Fragkakis committed Jun 22, 2022 at 23:38 UTC 5ecd4b4a311e0a83dcd900f8e11f6f355a562b1e
1 file changed +41 -4
database/sqlite/sqlite_functions.c
+41 -4
@@ -68,6 +68,9 @@ const char *database_cleanup[] = {
68
69 sqlite3 *db_meta = NULL;
70
71 +#define MAX_PREPARED_STATEMENTS (32)
72 +pthread_key_t key_pool[MAX_PREPARED_STATEMENTS];
73 +
74 static uv_mutex_t sqlite_transaction_lock;
75
76 int execute_insert(sqlite3_stmt *res)
@@ -96,6 +99,10 @@ static void add_stmt_to_list(sqlite3_stmt *res)
99 static sqlite3_stmt *statements[MAX_OPEN_STATEMENTS];
100
101 if (unlikely(!res)) {
102 + if (idx)
103 + info("Finilizing %d statements", idx);
104 + else
105 + info("No statements pending to finalize");
106 while (idx > 0) {
107 int rc;
108 rc = sqlite3_finalize(statements[--idx]);
@@ -107,13 +114,39 @@ static void add_stmt_to_list(sqlite3_stmt *res)
114
115 if (unlikely(idx == MAX_OPEN_STATEMENTS))
116 return;
110 - statements[idx++] = res;
117 }
118
113 -int prepare_statement(sqlite3 *database, char *query, sqlite3_stmt **statement) {
119 +static void release_statement(void *statement)
120 +{
121 + int rc;
122 +#ifdef NETDATA_INTERNAL_CHECKS
123 + info("Thread %d: Cleaning prepared statement on %p", gettid(), statement);
124 +#endif
125 + if (unlikely(rc = sqlite3_finalize((sqlite3_stmt *) statement) != SQLITE_OK))
126 + error_report("Failed to finalize statement, rc = %d", rc);
127 +}
128 +
129 +int prepare_statement(sqlite3 *database, char *query, sqlite3_stmt **statement)
130 +{
131 + static __thread uint32_t keys_used = 0;
132 +
133 + pthread_key_t *key = NULL;
134 + int ret = 1;
135 +
136 + if (likely(keys_used < MAX_PREPARED_STATEMENTS))
137 + key = &key_pool[keys_used++];
138 +
139 int rc = sqlite3_prepare_v2(database, query, -1, statement, 0);
115 - if (likely(rc == SQLITE_OK))
116 - add_stmt_to_list(*statement);
140 + if (likely(rc == SQLITE_OK)) {
141 + if (likely(key)) {
142 + ret = pthread_setspecific(*key, *statement);
143 +#ifdef NETDATA_INTERNAL_CHECKS
144 + info("Thread %d: Using key %u on statement %p", gettid(), keys_used, *statement);
145 +#endif
146 + }
147 + if (ret)
148 + add_stmt_to_list(*statement);
149 + }
150 return rc;
151 }
152
@@ -448,6 +481,10 @@ int sql_init_database(db_check_action_type_t rebuild, int memory)
481
482 fatal_assert(0 == uv_mutex_init(&sqlite_transaction_lock));
483 info("SQLite database initialization completed");
484 +
485 + for (int i = 0; i < MAX_PREPARED_STATEMENTS; i++)
486 + (void)pthread_key_create(&key_pool[i], release_statement);
487 +
488 return 0;
489 }
490