diff options
-rw-r--r-- | daemon/main.c | 1 | ||||
-rw-r--r-- | database/sqlite/sqlite_functions.c | 65 | ||||
-rw-r--r-- | web/api/formatters/json_wrapper.c | 4 | ||||
-rw-r--r-- | web/api/formatters/rrd2json.c | 54 |
4 files changed, 88 insertions, 36 deletions
diff --git a/daemon/main.c b/daemon/main.c index eab53dea6f..346486a84f 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -50,6 +50,7 @@ void netdata_cleanup_and_exit(int ret) { rrdeng_exit(&multidb_ctx); #endif } + sql_close_database(); // unlink the pid if(pidfile[0]) { diff --git a/database/sqlite/sqlite_functions.c b/database/sqlite/sqlite_functions.c index 63b0196439..694b86330a 100644 --- a/database/sqlite/sqlite_functions.c +++ b/database/sqlite/sqlite_functions.c @@ -48,6 +48,31 @@ static int execute_insert(sqlite3_stmt *res) return rc; } +#define MAX_OPEN_STATEMENTS (512) + +static void add_stmt_to_list(sqlite3_stmt *res) +{ + static int idx = 0; + static sqlite3_stmt *statements[MAX_OPEN_STATEMENTS]; + + if (unlikely(!res)) { + while (idx > 0) + sqlite3_finalize(statements[--idx]); + return; + } + + if (unlikely(idx == MAX_OPEN_STATEMENTS)) + return; + statements[idx++] = res; +} + +static int prepare_statement(sqlite3 *database, char *query, sqlite3_stmt **statement) { + int rc = sqlite3_prepare_v2(database, query, -1, statement, 0); + if (likely(rc == SQLITE_OK)) + add_stmt_to_list(*statement); + return rc; +} + /* * Store a chart or dimension UUID in chart_active or dimension_active * The statement that will be prepared determines that @@ -178,9 +203,12 @@ void sql_close_database(void) return; info("Closing SQLite database"); - rc = sqlite3_close(db_meta); + + add_stmt_to_list(NULL); + + rc = sqlite3_close_v2(db_meta); if (unlikely(rc != SQLITE_OK)) - error_report("Error %d while closing the SQLite database", rc); + error_report("Error %d while closing the SQLite database, %s", rc, sqlite3_errstr(rc)); return; } @@ -193,7 +221,7 @@ int find_uuid_type(uuid_t *uuid) int uuid_type = 3; if (unlikely(!res)) { - rc = sqlite3_prepare_v2(db_meta, FIND_UUID_TYPE, -1, &res, 0); + rc = prepare_statement(db_meta, FIND_UUID_TYPE, &res); if (rc != SQLITE_OK) { error_report("Failed to bind prepare statement to find UUID type in the database"); return 0; @@ -228,7 +256,7 @@ uuid_t *find_dimension_uuid(RRDSET *st, RRDDIM *rd) return NULL; if (unlikely(!res)) { - rc = sqlite3_prepare_v2(db_meta, SQL_FIND_DIMENSION_UUID, -1, &res, 0); + rc = prepare_statement(db_meta, SQL_FIND_DIMENSION_UUID, &res); if (rc != SQLITE_OK) { error_report("Failed to bind prepare statement to lookup dimension UUID in the database"); return NULL; @@ -308,7 +336,7 @@ void delete_dimension_uuid(uuid_t *dimension_uuid) #endif if (unlikely(!res)) { - rc = sqlite3_prepare_v2(db_meta, DELETE_DIMENSION_UUID, -1, &res, 0); + rc = prepare_statement(db_meta, DELETE_DIMENSION_UUID, &res); if (rc != SQLITE_OK) { error_report("Failed to prepare statement to delete a dimension uuid"); return; @@ -344,7 +372,7 @@ uuid_t *find_chart_uuid(RRDHOST *host, const char *type, const char *id, const c return NULL; if (unlikely(!res)) { - rc = sqlite3_prepare_v2(db_meta, SQL_FIND_CHART_UUID, -1, &res, 0); + rc = prepare_statement(db_meta, SQL_FIND_CHART_UUID, &res); if (rc != SQLITE_OK) { error_report("Failed to prepare statement to lookup chart UUID in the database"); return NULL; @@ -449,7 +477,7 @@ int sql_store_host( } if (unlikely((!res))) { - rc = sqlite3_prepare_v2(db_meta, SQL_STORE_HOST, -1, &res, 0); + rc = prepare_statement(db_meta, SQL_STORE_HOST, &res); if (unlikely(rc != SQLITE_OK)) { error_report("Failed to prepare statement to store host, rc = %d", rc); return 1; @@ -510,7 +538,7 @@ int sql_store_chart( const char *context, const char *title, const char *units, const char *plugin, const char *module, long priority, int update_every, int chart_type, int memory_mode, long history_entries) { - static __thread sqlite3_stmt *res; + static __thread sqlite3_stmt *res = NULL; int rc, param = 0; if (unlikely(!db_meta)) { @@ -521,7 +549,7 @@ int sql_store_chart( } if (unlikely(!res)) { - rc = sqlite3_prepare_v2(db_meta, SQL_STORE_CHART, -1, &res, 0); + rc = prepare_statement(db_meta, SQL_STORE_CHART, &res); if (unlikely(rc != SQLITE_OK)) { error_report("Failed to prepare statement to store chart, rc = %d", rc); return 1; @@ -647,7 +675,7 @@ int sql_store_dimension( } if (unlikely(!res)) { - rc = sqlite3_prepare_v2(db_meta, SQL_STORE_DIMENSION, -1, &res, 0); + rc = prepare_statement(db_meta, SQL_STORE_DIMENSION, &res); if (unlikely(rc != SQLITE_OK)) { error_report("Failed to prepare statement to store dimension, rc = %d", rc); return 1; @@ -1252,6 +1280,11 @@ void sql_build_context_param_list(struct context_param **param_list, RRDHOST *ho sprintf(id, "%s.%s", sqlite3_column_text(res, 3), sqlite3_column_text(res, 1)); if (!st || uuid_compare(*(uuid_t *)sqlite3_column_blob(res, 7), chart_id)) { + if (unlikely(st && !st->counter)) { + freez(st->context); + freez((char *) st->name); + freez(st); + } st = callocz(1, sizeof(*st)); char n[RRD_ID_LENGTH_MAX + 1]; @@ -1282,8 +1315,16 @@ void sql_build_context_param_list(struct context_param **param_list, RRDHOST *ho rd->next = (*param_list)->rd; (*param_list)->rd = rd; } - if (likely(st && context && !st->context)) - st->context = strdupz(context); + if (st) { + if (!st->counter) { + freez(st->context); + freez((char *)st->name); + freez(st); + } + else + if (!st->context && context) + st->context = strdupz(context); + } failed: rc = sqlite3_finalize(res); diff --git a/web/api/formatters/json_wrapper.c b/web/api/formatters/json_wrapper.c index 1c06a8ff44..1d9c2472af 100644 --- a/web/api/formatters/json_wrapper.c +++ b/web/api/formatters/json_wrapper.c @@ -48,8 +48,8 @@ void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, RRDR_OPTIONS , kq, kq, sq, context_mode && temp_rd?r->st->context:r->st->name, sq , kq, kq, r->update_every , kq, kq, r->st->update_every - , kq, kq, (uint32_t) (context_param_list ? context_param_list->first_entry_t : rrdset_first_entry_t(r->st)) - , kq, kq, (uint32_t) (context_param_list ? context_param_list->last_entry_t : rrdset_last_entry_t(r->st)) + , kq, kq, (uint32_t) (context_param_list ? context_param_list->first_entry_t : rrdset_first_entry_t_nolock(r->st)) + , kq, kq, (uint32_t) (context_param_list ? context_param_list->last_entry_t : rrdset_last_entry_t_nolock(r->st)) , kq, kq, (uint32_t)r->before , kq, kq, (uint32_t)r->after , kq, kq); diff --git a/web/api/formatters/rrd2json.c b/web/api/formatters/rrd2json.c index 82be7627c1..5b12c89bac 100644 --- a/web/api/formatters/rrd2json.c +++ b/web/api/formatters/rrd2json.c @@ -2,7 +2,28 @@ #include "web/api/web_api_v1.h" -static inline void free_temp_rrddim(RRDDIM *temp_rd) +static inline void free_single_rrdrim(RRDDIM *temp_rd, int archive_mode) +{ + if (unlikely(!temp_rd)) + return; + + freez((char *)temp_rd->id); + freez((char *)temp_rd->name); + + if (unlikely(archive_mode)) { + temp_rd->rrdset->counter--; + if (!temp_rd->rrdset->counter) { + freez((char *)temp_rd->rrdset->name); + freez(temp_rd->rrdset->context); + freez(temp_rd->rrdset); + } + } + freez(temp_rd->state->metric_uuid); + freez(temp_rd->state); + freez(temp_rd); +} + +static inline void free_rrddim_list(RRDDIM *temp_rd, int archive_mode) { if (unlikely(!temp_rd)) return; @@ -10,14 +31,7 @@ static inline void free_temp_rrddim(RRDDIM *temp_rd) RRDDIM *t; while (temp_rd) { t = temp_rd->next; - freez((char *)temp_rd->id); - freez((char *)temp_rd->name); -#ifdef ENABLE_DBENGINE - if (temp_rd->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) - freez(temp_rd->state->metric_uuid); -#endif - freez(temp_rd->state); - freez(temp_rd); + free_single_rrdrim(temp_rd, archive_mode); temp_rd = t; } } @@ -27,7 +41,7 @@ void free_context_param_list(struct context_param **param_list) if (unlikely(!param_list || !*param_list)) return; - free_temp_rrddim(((*param_list)->rd)); + free_rrddim_list(((*param_list)->rd), (*param_list)->flags & CONTEXT_FLAGS_ARCHIVE); freez((*param_list)); *param_list = NULL; } @@ -36,21 +50,17 @@ void rebuild_context_param_list(struct context_param *context_param_list, time_t { RRDDIM *temp_rd = context_param_list->rd; RRDDIM *new_rd_list = NULL, *t; + int is_archived = (context_param_list->flags & CONTEXT_FLAGS_ARCHIVE); while (temp_rd) { t = temp_rd->next; - if (rrdset_last_entry_t(temp_rd->rrdset) >= after_requested) { + RRDSET *st = temp_rd->rrdset; + time_t last_entry_t = is_archived ? st->last_entry_t : rrdset_last_entry_t(st); + + if (last_entry_t >= after_requested) { temp_rd->next = new_rd_list; new_rd_list = temp_rd; - } else { - freez((char *)temp_rd->id); - freez((char *)temp_rd->name); -#ifdef ENABLE_DBENGINE - if (temp_rd->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) - freez(temp_rd->state->metric_uuid); -#endif - freez(temp_rd->state); - freez(temp_rd); - } + } else + free_single_rrdrim(temp_rd, is_archived); temp_rd = t; } context_param_list->rd = new_rd_list; @@ -65,7 +75,7 @@ void build_context_param_list(struct context_param **param_list, RRDSET *st) *param_list = mallocz(sizeof(struct context_param)); (*param_list)->first_entry_t = LONG_MAX; (*param_list)->last_entry_t = 0; - (*param_list)->flags = 0; + (*param_list)->flags = CONTEXT_FLAGS_CONTEXT; (*param_list)->rd = NULL; } |