diff options
Diffstat (limited to 'src/database/sqlite/sqlite_health.c')
-rw-r--r-- | src/database/sqlite/sqlite_health.c | 986 |
1 files changed, 348 insertions, 638 deletions
diff --git a/src/database/sqlite/sqlite_health.c b/src/database/sqlite/sqlite_health.c index ea883c51b9..8ce9b04942 100644 --- a/src/database/sqlite/sqlite_health.c +++ b/src/database/sqlite/sqlite_health.c @@ -6,8 +6,8 @@ #include "health/health_internals.h" #define MAX_HEALTH_SQL_SIZE 2048 -#define SQLITE3_BIND_STRING_OR_NULL(res, key, param) \ - ((key) ? sqlite3_bind_text(res, param, string2str(key), -1, SQLITE_STATIC) : sqlite3_bind_null(res, param)) +#define SQLITE3_BIND_STRING_OR_NULL(res, param, key) \ + ((key) ? sqlite3_bind_text((res), (param), string2str(key), -1, SQLITE_STATIC) : sqlite3_bind_null((res), (param))) #define SQLITE3_COLUMN_STRINGDUP_OR_NULL(res, param) \ ({ \ @@ -26,7 +26,7 @@ static void sql_health_alarm_log_update(RRDHOST *host, ALARM_ENTRY *ae) { - sqlite3_stmt *res = NULL; + static __thread sqlite3_stmt *res = NULL; int rc; if (unlikely(!db_meta)) { @@ -35,75 +35,40 @@ static void sql_health_alarm_log_update(RRDHOST *host, ALARM_ENTRY *ae) return; } - rc = sqlite3_prepare_v2(db_meta, SQL_UPDATE_HEALTH_LOG, -1, &res, 0); - if (unlikely(rc != SQLITE_OK)) { - error_report("HEALTH [%s]: Failed to prepare statement for SQL_UPDATE_HEALTH_LOG", rrdhost_hostname(host)); - return; - } - - rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) ae->updated_by_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind updated_by_id parameter for SQL_UPDATE_HEALTH_LOG"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) ae->flags); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind flags parameter for SQL_UPDATE_HEALTH_LOG"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) ae->exec_run_timestamp); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind exec_run_timestamp parameter for SQL_UPDATE_HEALTH_LOG"); - goto failed; - } - - rc = sqlite3_bind_int(res, 4, ae->exec_code); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind exec_code parameter for SQL_UPDATE_HEALTH_LOG"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 5, (sqlite3_int64) ae->unique_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind unique_id parameter for SQL_UPDATE_HEALTH_LOG"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 6, (sqlite3_int64) ae->alarm_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind unique_id parameter for SQL_UPDATE_HEALTH_LOG"); - goto failed; + if (unlikely(!res)) { + rc = prepare_statement(db_meta, SQL_UPDATE_HEALTH_LOG, &res); + if (unlikely(rc != SQLITE_OK)) { + error_report("HEALTH [%s]: Failed to prepare statement for SQL_UPDATE_HEALTH_LOG", rrdhost_hostname(host)); + return; + } } - rc = sqlite3_bind_blob(res, 7, &ae->transition_id, sizeof(ae->transition_id), SQLITE_STATIC); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind host_id for SQL_UPDATE_HEALTH_LOG."); - goto failed; - } + int param = 0; + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) ae->updated_by_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) ae->flags)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) ae->exec_run_timestamp)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int(res, ++param, ae->exec_code)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) ae->unique_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) ae->alarm_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &ae->transition_id, sizeof(ae->transition_id), SQLITE_STATIC)); + param = 0; rc = execute_insert(res); if (unlikely(rc != SQLITE_DONE)) { error_report("HEALTH [%s]: Failed to update health log, rc = %d", rrdhost_hostname(host), rc); } -failed: - if (unlikely(sqlite3_finalize(res) != SQLITE_OK)) - error_report("HEALTH [%s]: Failed to finalize the prepared statement for updating health log.", rrdhost_hostname(host)); +done: + REPORT_BIND_FAIL(res, param); + + if (unlikely(sqlite3_reset(res) != SQLITE_OK)) + error_report("HEALTH [%s]: Failed to reset statement for updating health log.", rrdhost_hostname(host)); } /* Health related SQL queries Inserts an entry in the table */ -#define SQL_INSERT_HEALTH_LOG \ - "INSERT INTO health_log (host_id, alarm_id, " \ - "config_hash_id, name, chart, exec, recipient, units, chart_context, last_transition_id, chart_name) " \ - "VALUES (@host_id,@alarm_id, @config_hash_id,@name,@chart,@exec,@recipient,@units,@chart_context," \ - "@last_transition_id,@chart_name) ON CONFLICT (host_id, alarm_id) DO UPDATE " \ - "SET last_transition_id = excluded.last_transition_id, chart_name = excluded.chart_name, " \ - "config_hash_id=excluded.config_hash_id RETURNING health_log_id" #define SQL_INSERT_HEALTH_LOG_DETAIL \ "INSERT INTO health_log_detail (health_log_id, unique_id, alarm_id, alarm_event_id, " \ @@ -113,256 +78,114 @@ failed: "@non_clear_duration,@flags,@exec_run_timestamp,@delay_up_to_timestamp, @info,@exec_code,@new_status,@old_status," \ "@delay,@new_value,@old_value,@last_repeat,@transition_id,@global_id,@summary)" -static void sql_health_alarm_log_insert(RRDHOST *host, ALARM_ENTRY *ae) { - sqlite3_stmt *res = NULL; +static void sql_health_alarm_log_insert_detail(RRDHOST *host, uint64_t health_log_id, ALARM_ENTRY *ae) +{ + static __thread sqlite3_stmt *res = NULL; int rc; - uint64_t health_log_id = 0; - - if (unlikely(!db_meta)) { - if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) - error_report("HEALTH [%s]: Database has not been initialized", rrdhost_hostname(host)); - return; - } - - rc = sqlite3_prepare_v2(db_meta, SQL_INSERT_HEALTH_LOG, -1, &res, 0); - if (unlikely(rc != SQLITE_OK)) { - error_report("HEALTH [%s]: Failed to prepare statement for SQL_INSERT_HEALTH_LOG", rrdhost_hostname(host)); - return; - } - rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind host_id for SQL_INSERT_HEALTH_LOG."); - goto failed; - } - - rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) ae->alarm_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind alarm_id parameter for SQL_INSERT_HEALTH_LOG"); - goto failed; - } - - rc = sqlite3_bind_blob(res, 3, &ae->config_hash_id, sizeof(ae->config_hash_id), SQLITE_STATIC); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind config_hash_id parameter for SQL_INSERT_HEALTH_LOG"); - goto failed; - } - - rc = SQLITE3_BIND_STRING_OR_NULL(res, ae->name, 4); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind name parameter for SQL_INSERT_HEALTH_LOG"); - goto failed; + if (unlikely(!res)) { + rc = prepare_statement(db_meta, SQL_INSERT_HEALTH_LOG_DETAIL, &res); + if (unlikely(rc != SQLITE_OK)) { + error_report( + "HEALTH [%s]: Failed to prepare statement for SQL_INSERT_HEALTH_LOG_DETAIL", rrdhost_hostname(host)); + return; + } } - rc = SQLITE3_BIND_STRING_OR_NULL(res, ae->chart, 5); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind chart parameter for SQL_INSERT_HEALTH_LOG"); - goto failed; - } + int param = 0; + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)health_log_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)ae->unique_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)ae->alarm_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)ae->alarm_event_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)ae->updated_by_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)ae->updates_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)ae->when)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)ae->duration)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)ae->non_clear_duration)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)ae->flags)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)ae->exec_run_timestamp)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)ae->delay_up_to_timestamp)); + SQLITE_BIND_FAIL(done, SQLITE3_BIND_STRING_OR_NULL(res, ++param, ae->info)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int(res, ++param, ae->exec_code)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int(res, ++param, ae->new_status)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int(res, ++param, ae->old_status)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int(res, ++param, ae->delay)); + SQLITE_BIND_FAIL(done, sqlite3_bind_double(res, ++param, ae->new_value)); + SQLITE_BIND_FAIL(done, sqlite3_bind_double(res, ++param, ae->old_value)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)ae->last_repeat)); + SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &ae->transition_id, sizeof(ae->transition_id), SQLITE_STATIC)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)ae->global_id)); + SQLITE_BIND_FAIL(done, SQLITE3_BIND_STRING_OR_NULL(res, ++param, ae->summary)); + + param = 0; + rc = execute_insert(res); + if (rc == SQLITE_DONE) + ae->flags |= HEALTH_ENTRY_FLAG_SAVED; + else + error_report( + "HEALTH [%s]: Failed to execute SQL_INSERT_HEALTH_LOG_DETAIL, rc = %d", rrdhost_hostname(host), rc); - rc = SQLITE3_BIND_STRING_OR_NULL(res, ae->exec, 6); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind exec parameter for SQL_INSERT_HEALTH_LOG"); - goto failed; - } +done: + REPORT_BIND_FAIL(res, param); - rc = SQLITE3_BIND_STRING_OR_NULL(res, ae->recipient, 7); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind recipient parameter for SQL_INSERT_HEALTH_LOG"); - goto failed; - } + if (unlikely(sqlite3_reset(res) != SQLITE_OK)) + error_report("HEALTH [%s]: Failed to reset statement for inserting to health log detail", rrdhost_hostname(host)); +} - rc = SQLITE3_BIND_STRING_OR_NULL(res, ae->units, 8); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind host_id parameter to store node instance information"); - goto failed; - } +#define SQL_INSERT_HEALTH_LOG \ + "INSERT INTO health_log (host_id, alarm_id, " \ + "config_hash_id, name, chart, exec, recipient, units, chart_context, last_transition_id, chart_name) " \ + "VALUES (@host_id,@alarm_id, @config_hash_id,@name,@chart,@exec,@recipient,@units,@chart_context," \ + "@last_transition_id,@chart_name) ON CONFLICT (host_id, alarm_id) DO UPDATE " \ + "SET last_transition_id = excluded.last_transition_id, chart_name = excluded.chart_name, " \ + "config_hash_id=excluded.config_hash_id RETURNING health_log_id" - rc = SQLITE3_BIND_STRING_OR_NULL(res, ae->chart_context, 9); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind chart_context parameter for SQL_INSERT_HEALTH_LOG"); - goto failed; - } +static void sql_health_alarm_log_insert(RRDHOST *host, ALARM_ENTRY *ae) +{ + static __thread sqlite3_stmt *res = NULL; + int rc; + uint64_t health_log_id; - rc = sqlite3_bind_blob(res, 10, &ae->transition_id, sizeof(ae->transition_id), SQLITE_STATIC); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind transition_id parameter for SQL_INSERT_HEALTH_LOG"); - goto failed; + if (unlikely(!db_meta)) { + if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) + error_report("HEALTH [%s]: Database has not been initialized", rrdhost_hostname(host)); + return; } - rc = SQLITE3_BIND_STRING_OR_NULL(res, ae->chart_name, 11); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind chart_name parameter for SQL_INSERT_HEALTH_LOG"); - goto failed; + if (unlikely(!res)) { + rc = prepare_statement(db_meta, SQL_INSERT_HEALTH_LOG, &res); + if (unlikely(rc != SQLITE_OK)) { + error_report("HEALTH [%s]: Failed to prepare statement for SQL_INSERT_HEALTH_LOG", rrdhost_hostname(host)); + return; + } } + int param = 0; + SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) ae->alarm_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &ae->config_hash_id, sizeof(ae->config_hash_id), SQLITE_STATIC)); + SQLITE_BIND_FAIL(done, SQLITE3_BIND_STRING_OR_NULL(res, ++param, ae->name)); + SQLITE_BIND_FAIL(done, SQLITE3_BIND_STRING_OR_NULL(res, ++param, ae->chart)); + SQLITE_BIND_FAIL(done, SQLITE3_BIND_STRING_OR_NULL(res, ++param, ae->exec)); + SQLITE_BIND_FAIL(done, SQLITE3_BIND_STRING_OR_NULL(res, ++param, ae->recipient)); + SQLITE_BIND_FAIL(done, SQLITE3_BIND_STRING_OR_NULL(res, ++param, ae->units)); + SQLITE_BIND_FAIL(done, SQLITE3_BIND_STRING_OR_NULL(res, ++param, ae->chart_context)); + SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &ae->transition_id, sizeof(ae->transition_id), SQLITE_STATIC)); + SQLITE_BIND_FAIL(done, SQLITE3_BIND_STRING_OR_NULL(res, ++param, ae->chart_name)); + + param = 0; rc = sqlite3_step_monitored(res); - if (likely(rc == SQLITE_ROW)) - health_log_id = (size_t) sqlite3_column_int64(res, 0); - else { + if (rc == SQLITE_ROW) { + health_log_id = (size_t)sqlite3_column_int64(res, 0); + sql_health_alarm_log_insert_detail(host, health_log_id, ae); + } else error_report("HEALTH [%s]: Failed to execute SQL_INSERT_HEALTH_LOG, rc = %d", rrdhost_hostname(host), rc); - goto failed; - } - - rc = sqlite3_finalize(res); - if (unlikely(rc != SQLITE_OK)) - error_report("HEALTH [%s]: Failed to finalize the prepared statement for inserting to health log.", rrdhost_hostname(host)); - - rc = sqlite3_prepare_v2(db_meta, SQL_INSERT_HEALTH_LOG_DETAIL, -1, &res, 0); - if (unlikely(rc != SQLITE_OK)) { - error_report("HEALTH [%s]: Failed to prepare statement for SQL_INSERT_HEALTH_LOG_DETAIL", rrdhost_hostname(host)); - return; - } - - rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) health_log_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind unique_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) ae->unique_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind unique_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) ae->alarm_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind unique_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 4, (sqlite3_int64) ae->alarm_event_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind alarm_event_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 5, (sqlite3_int64) ae->updated_by_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind updated_by_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 6, (sqlite3_int64) ae->updates_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind updates_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 7, (sqlite3_int64) ae->when); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind when parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 8, (sqlite3_int64) ae->duration); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind duration parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 9, (sqlite3_int64) ae->non_clear_duration); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind non_clear_duration parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 10, (sqlite3_int64) ae->flags); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind flags parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - rc = sqlite3_bind_int64(res, 11, (sqlite3_int64) ae->exec_run_timestamp); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind exec_run_timestamp parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 12, (sqlite3_int64) ae->delay_up_to_timestamp); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind delay_up_to_timestamp parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = SQLITE3_BIND_STRING_OR_NULL(res, ae->info, 13); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind info parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int(res, 14, ae->exec_code); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind exec_code parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int(res, 15, ae->new_status); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind new_status parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int(res, 16, ae->old_status); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind old_status parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int(res, 17, ae->delay); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind delay parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_double(res, 18, ae->new_value); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind new_value parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_double(res, 19, ae->old_value); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind old_value parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 20, (sqlite3_int64) ae->last_repeat); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind last_repeat parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_blob(res, 21, &ae->transition_id, sizeof(ae->transition_id), SQLITE_STATIC); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind transition_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 22, (sqlite3_int64) ae->global_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind global_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = SQLITE3_BIND_STRING_OR_NULL(res, ae->summary, 23); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind summary parameter for SQL_INSERT_HEALTH_LOG_DETAIL"); - goto failed; - } - - rc = execute_insert(res); - if (unlikely(rc != SQLITE_DONE)) { - error_report("HEALTH [%s]: Failed to execute SQL_INSERT_HEALTH_LOG_DETAIL, rc = %d", rrdhost_hostname(host), rc); - goto failed; - } - - ae->flags |= HEALTH_ENTRY_FLAG_SAVED; +done: + REPORT_BIND_FAIL(res, param); -failed: - if (unlikely(sqlite3_finalize(res) != SQLITE_OK)) - error_report("HEALTH [%s]: Failed to finalize the prepared statement for inserting to health log.", rrdhost_hostname(host)); + if (unlikely(sqlite3_reset(res) != SQLITE_OK)) + error_report("HEALTH [%s]: Failed to reset statement for inserting to health log", rrdhost_hostname(host)); } void sql_health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae) @@ -433,18 +256,11 @@ void sql_health_alarm_log_cleanup(RRDHOST *host, bool claimed) { return; } - rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind first host_id for sql_health_alarm_log_cleanup."); - goto done; - } - - rc = sqlite3_bind_int64(res, 2, (sqlite3_int64)host->health_log.health_log_history); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind health log history for sql_health_alarm_log_cleanup."); - goto done; - } + int param = 0; + SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)host->health_log.health_log_history)); + param = 0; rc = sqlite3_step_monitored(res); if (unlikely(rc != SQLITE_DONE)) error_report("Failed to cleanup health log detail table, rc = %d", rc); @@ -453,6 +269,8 @@ void sql_health_alarm_log_cleanup(RRDHOST *host, bool claimed) { sql_aclk_alert_clean_dead_entries(host); done: + REPORT_BIND_FAIL(res, param); + rc = sqlite3_finalize(res); if (unlikely(rc != SQLITE_OK)) error_report("Failed to finalize the prepared statement to cleanup health log detail table (claimed)"); @@ -471,153 +289,115 @@ done: #define SQL_INJECT_REMOVED_UPDATE_LOG \ "UPDATE health_log SET last_transition_id = ?1 WHERE alarm_id = ?2 AND last_transition_id = ?3 AND host_id = ?4" -void sql_inject_removed_status( - RRDHOST *host, - uint32_t alarm_id, - uint32_t alarm_event_id, - uint32_t unique_id, - uint32_t max_unique_id, - uuid_t *prev_transition_id) +bool sql_update_removed_in_health_log(RRDHOST *host, uint32_t alarm_id, uuid_t *transition_id, uuid_t *last_transition) { int rc; + sqlite3_stmt *res; - if (!alarm_id || !alarm_event_id || !unique_id || !max_unique_id) - return; - - sqlite3_stmt *res = NULL; - - rc = sqlite3_prepare_v2(db_meta, SQL_INJECT_REMOVED, -1, &res, 0); + rc = sqlite3_prepare_v2(db_meta, SQL_INJECT_REMOVED_UPDATE_LOG, -1, &res, 0); if (rc != SQLITE_OK) { - error_report("Failed to prepare statement when trying to inject removed event"); - return; + error_report("Failed to prepare statement when trying to update health_log during inject removed event"); + return false; } - rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) max_unique_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind max_unique_id parameter for SQL_INJECT_REMOVED"); - goto failed; - } + int param = 0; + SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, transition_id, sizeof(*transition_id), SQLITE_STATIC)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)alarm_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, last_transition, sizeof(*last_transition), SQLITE_STATIC)); + SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC)); - rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) alarm_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind alarm_id parameter for SQL_INJECT_REMOVED"); - goto failed; - } + param = 0; + rc = execute_insert(res); + if (unlikely(rc != SQLITE_DONE)) + error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED_UPDATE_DETAIL, rc = %d", rc); - rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) alarm_event_id + 1); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind alarm_event_id parameter for SQL_INJECT_REMOVED"); - goto failed; - } +done: + REPORT_BIND_FAIL(res, param); - rc = sqlite3_bind_int64(res, 4, (sqlite3_int64) unique_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED"); - goto failed; - } + if (unlikely(sqlite3_finalize(res) != SQLITE_OK)) + error_report("HEALTH [N/A]: Failed to finalize the prepared statement for injecting removed event."); - uuid_t transition_id; - uuid_generate_random(transition_id); - rc = sqlite3_bind_blob(res, 5, &transition_id, sizeof(transition_id), SQLITE_STATIC); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind config_hash_id parameter for SQL_INJECT_REMOVED"); - goto failed; - } + return (param == 0 && rc == SQLITE_DONE); +} - rc = sqlite3_bind_int64(res, 6, (sqlite3_int64) unique_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED"); - goto failed; - } +bool sql_update_removed_in_health_log_detail(uint32_t unique_id, uint32_t max_unique_id, uuid_t *prev_transition_id) +{ + int rc; + sqlite3_stmt *res; - rc = sqlite3_bind_blob(res, 7, prev_transition_id, sizeof(*prev_transition_id), SQLITE_STATIC); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED."); - goto failed; + rc = sqlite3_prepare_v2(db_meta, SQL_INJECT_REMOVED_UPDATE_DETAIL, -1, &res, 0); + if (rc != SQLITE_OK) { + error_report("Failed to prepare statement when trying to update health_log_detail during inject removed event"); + return false; } + int param = 0; + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) HEALTH_ENTRY_FLAG_UPDATED)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) max_unique_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) unique_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, prev_transition_id, sizeof(*prev_transition_id), SQLITE_STATIC)); + + param = 0; rc = execute_insert(res); - if (unlikely(rc != SQLITE_DONE)) { - error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED, rc = %d", rc); - goto failed; - } + if (unlikely(rc != SQLITE_DONE)) + error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED_UPDATE_DETAIL, rc = %d", rc); + +done: + REPORT_BIND_FAIL(res, param); if (unlikely(sqlite3_finalize(res) != SQLITE_OK)) error_report("HEALTH [N/A]: Failed to finalize the prepared statement for injecting removed event."); - //update the old entry in health_log_detail - rc = sqlite3_prepare_v2(db_meta, SQL_INJECT_REMOVED_UPDATE_DETAIL, -1, &res, 0); - if (rc != SQLITE_OK) { - error_report("Failed to prepare statement when trying to update health_log_detail during inject removed event"); - return; - } - - rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) HEALTH_ENTRY_FLAG_UPDATED); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind flags parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) max_unique_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind max_unique_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL"); - goto failed; - } + return (param == 0 && rc == SQLITE_DONE); +} - rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) unique_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL"); - goto failed; - } +void sql_inject_removed_status( + RRDHOST *host, + uint32_t alarm_id, + uint32_t alarm_event_id, + uint32_t unique_id, + uint32_t max_unique_id, + uuid_t *last_transition) +{ + int rc; - rc = sqlite3_bind_blob(res, 4, prev_transition_id, sizeof(*prev_transition_id), SQLITE_STATIC); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL"); - goto failed; - } + if (!alarm_id || !alarm_event_id || !unique_id || !max_unique_id) + return; - rc = execute_insert(res); - if (unlikely(rc != SQLITE_DONE)) { - error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED_UPDATE_DETAIL, rc = %d", rc); - goto failed; - } + sqlite3_stmt *res = NULL; - //update the health_log_table - rc = sqlite3_prepare_v2(db_meta, SQL_INJECT_REMOVED_UPDATE_LOG, -1, &res, 0); + rc = sqlite3_prepare_v2(db_meta, SQL_INJECT_REMOVED, -1, &res, 0); if (rc != SQLITE_OK) { - error_report("Failed to prepare statement when trying to update health_log during inject removed event"); + error_report("Failed to prepare statement when trying to inject removed event"); return; } - rc = sqlite3_bind_blob(res, 1, &transition_id, sizeof(transition_id), SQLITE_STATIC); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED_UPDATE_LOG"); - goto failed; - } - - rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) alarm_id); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL"); - goto failed; - } + uuid_t transition_id; + uuid_generate_random(transition_id); - rc = sqlite3_bind_blob(res, 3, prev_transition_id, sizeof(*prev_transition_id), SQLITE_STATIC); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED_UPDATE_LOG"); - goto failed; - } + int param = 0; + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) max_unique_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) alarm_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) alarm_event_id + 1)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) unique_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &transition_id, sizeof(transition_id), SQLITE_STATIC)); + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) unique_id)); + SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, last_transition, sizeof(*last_transition), SQLITE_STATIC)); - rc = sqlite3_bind_blob(res, 4, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC); - if (unlikely(rc != SQLITE_OK)) { - error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL"); - goto failed; + param = 0; + rc = execute_insert(res); + if (rc == SQLITE_DONE) { + //update the old entry in health_log_detail + sql_update_removed_in_health_log_detail(unique_id, max_unique_id, last_transition); + //update the old entry in health_log + sql_update_removed_in_health_log(host, alarm_id, &transition_id, last_transition); } + else + error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED, rc = %d", rc); - rc = execute_insert(res); - if (unlikely(rc != SQLITE_DONE)) - error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED_UPDATE_DETAIL, rc = %d", rc); +done: + REPORT_BIND_FAIL(res, param); -failed: if (unlikely(sqlite3_finalize(res) != SQLITE_OK)) error_report("HEALTH [N/A]: Failed to finalize the prepared statement for injecting removed event."); } @@ -704,6 +484,76 @@ void sql_check_removed_alerts_state(RRDHOST *host) error_report("Failed to finalize the statement"); } +#define SQL_DELETE_MISSING_CHART_ALERT \ + "DELETE FROM health_log WHERE host_id = @host_id AND chart NOT IN " \ + "(SELECT type||'.'||id FROM chart WHERE host_id = @host_id)" + +static void sql_remove_alerts_from_deleted_charts(RRDHOST *host, uuid_t *host_id) +{ + sqlite3_stmt *res = NULL; + int ret; + + ret = sqlite3_prepare_v2(db_meta, SQL_DELETE_MISSING_CHART_ALERT, -1, &res, 0); + if (unlikely(ret != SQLITE_OK)) { + error_report("HEALTH [%s]: Failed to prepare sql statement to sql_remove_alerts_from_deleted_charts", rrdhost_hostname(host)); + return; + } + + if (host) + ret = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC); + else + ret = sqlite3_bind_blob(res, 1, host_id, sizeof(*host_id), SQLITE_STATIC); + + if (unlikely(ret != SQLITE_OK)) { + error_report("Failed to bind host_id parameter for sql_remove_alerts_from_deleted_charts."); + sqlite3_finalize(res); + return; + } + + ret = execute_insert(res); + if (ret != SQLITE_DONE) + error_report("Failed to execute command to delete missing charts from health_log"); + + ret = sqlite3_finalize(res); + if (unlikely(ret != SQLITE_OK)) + error_report("Failed to finalize statement when deleting missing charts from health_log"); +} + +static int clean_host_alerts(void *data, int argc, char **argv, char **column) +{ + UNUSED(argc); + UNUSED(data); + UNUSED(column); + + char guid[UUID_STR_LEN]; + uuid_unparse_lower(*(uuid_t *)argv[0], guid); + + netdata_log_info("Checking host %s (%s)", guid, (const char *) argv[1]); + sql_remove_alerts_from_deleted_charts(NULL, (uuid_t *)argv[0]); + + return 0; +} + + +#define SQL_HEALTH_CHECK_ALL_HOSTS "SELECT host_id, hostname FROM host" + +void sql_alert_cleanup(bool cli) +{ + UNUSED(cli); + + errno = 0; + if (sql_init_meta_database(DB_CHECK_NONE, 0)) { + netdata_log_error("Failed to open database"); + return; + } + netdata_log_info("Alert cleanup running ..."); + int rc = sqlite3_exec_monitored(db_meta, SQL_HEALTH_CHECK_ALL_HOSTS, clean_host_alerts, NULL, NULL); + if (rc != SQLITE_OK) + netdata_log_error("Failed to check host alerts"); + else + netdata_log_info("Alert cleanup done"); + +} /* Health related SQL queries Load from the health log table */ @@ -909,121 +759,64 @@ void sql_health_alarm_log_load(RRDHOST *host) "@p_db_lookup_before,@p_update_every,@source,@chart_labels,@summary, @time_group_condition, " \ "@time_group_value, @dims_group, @data_source)" -int sql_alert_store_config(RRD_ALERT_PROTOTYPE *ap __maybe_unused) +void sql_alert_store_config(RRD_ALERT_PROTOTYPE *ap __maybe_unused) { static __thread sqlite3_stmt *res = NULL; int rc, param = 0; - if (unlikely(!db_meta)) { - if (default_rrd_memory_mode != RRD_MEMORY_MODE_DBENGINE) - return 0; - error_report("Database has not been initialized"); - return 1; - } - if (unlikely(!res)) { rc = prepare_statement(db_meta, SQL_STORE_ALERT_CONFIG_HASH, &res); if (unlikely(rc != SQLITE_OK)) { error_report("Failed to prepare statement to store alert configuration, rc = %d", rc); - return 1; + return; } } - BUFFER *buf = buffer_create(128, NULL); - - rc = sqlite3_bind_blob(res, ++param, &ap->config.hash_id, sizeof(ap->config.hash_id), SQLITE_STATIC); - if (unlikely(rc != SQLITE_OK)) - goto bind_fail; - - if (ap->match.is_template) - rc = SQLITE3_BIND_STRING_OR_NULL(res, NULL, ++param); - else - rc = SQLITE3_BIND_STRING_OR_NULL(res, ap->config.name, ++param); - - if (unlikely(rc != SQLITE_OK)) - goto bind_fail; - - if (ap->match.is_template) - rc = SQLITE3_BIND_STRING_OR_NULL(res, ap->config.name, ++param); - else - rc = SQLITE3_BIND_STRING_OR_NULL(res, NULL, ++param); - if (unlikely(rc != SQLITE_OK)) - goto bind_fail; - - if (ap->match.is_template) |