From 2bf0bfb268917ead34776c2e4c68b10554956b24 Mon Sep 17 00:00:00 2001 From: Stelios Fragkakis <52996999+stelfrag@users.noreply.github.com> Date: Thu, 14 Jul 2022 13:17:30 +0300 Subject: Hold additional information for host -- prepare to load archived hosts on startup --- database/rrdhost.c | 3 +- database/sqlite/sqlite_db_migration.c | 23 ++++++ database/sqlite/sqlite_functions.c | 128 +++++++++++++++++++++++++++++++++- database/sqlite/sqlite_functions.h | 5 +- 4 files changed, 153 insertions(+), 6 deletions(-) diff --git a/database/rrdhost.c b/database/rrdhost.c index 296cf81305..4f33a88c4b 100644 --- a/database/rrdhost.c +++ b/database/rrdhost.c @@ -340,8 +340,7 @@ RRDHOST *rrdhost_create(const char *hostname, } if (likely(!uuid_parse(host->machine_guid, host->host_uuid))) { - int rc = sql_store_host(&host->host_uuid, hostname, registry_hostname, update_every, os, timezone, tags, - host->system_info ? host->system_info->hops : 0); + int rc = sql_store_host_info(host); if (unlikely(rc)) error_report("Failed to store machine GUID to the database"); sql_load_node_id(host); diff --git a/database/sqlite/sqlite_db_migration.c b/database/sqlite/sqlite_db_migration.c index b34be7feb3..ce9c8fe501 100644 --- a/database/sqlite/sqlite_db_migration.c +++ b/database/sqlite/sqlite_db_migration.c @@ -34,6 +34,17 @@ const char *database_migrate_v1_v2[] = { NULL }; +const char *database_migrate_v2_v3[] = { + "ALTER TABLE host ADD memory_mode INT;", + "ALTER TABLE host ADD abbrev_timezone TEXT;", + "ALTER TABLE host ADD utc_offset INT;", + "ALTER TABLE host ADD program_name TEXT;", + "ALTER TABLE host ADD program_version TEXT;", + "ALTER TABLE host ADD entries INT;", + "ALTER TABLE host ADD health_enabled INT;", + NULL +}; + static int do_migration_v1_v2(sqlite3 *database, const char *name) { UNUSED(name); @@ -44,6 +55,17 @@ static int do_migration_v1_v2(sqlite3 *database, const char *name) return 0; } +static int do_migration_v2_v3(sqlite3 *database, const char *name) +{ + UNUSED(name); + info("Running \"%s\" database migration", name); + + if (!column_exists_in_table("host", "memory_mode")) + return init_database_batch(database, DB_CHECK_NONE, 0, &database_migrate_v2_v3[0]); + return 0; +} + + static int do_migration_noop(sqlite3 *database, const char *name) { UNUSED(database); @@ -89,6 +111,7 @@ static int migrate_database(sqlite3 *database, int target_version, char *db_name DATABASE_FUNC_MIGRATION_LIST migration_action[] = { {.name = "v0 to v1", .func = do_migration_noop}, {.name = "v1 to v2", .func = do_migration_v1_v2}, + {.name = "v2 to v3", .func = do_migration_v2_v3}, // the terminator of this array {.name = NULL, .func = NULL} }; diff --git a/database/sqlite/sqlite_functions.c b/database/sqlite/sqlite_functions.c index 7569ca8bc9..7a62d3a8b6 100644 --- a/database/sqlite/sqlite_functions.c +++ b/database/sqlite/sqlite_functions.c @@ -3,11 +3,15 @@ #include "sqlite_functions.h" #include "sqlite_db_migration.h" -#define DB_METADATA_VERSION 2 +#define DB_METADATA_VERSION 3 const char *database_config[] = { - "CREATE TABLE IF NOT EXISTS host(host_id blob PRIMARY KEY, hostname text, " - "registry_hostname text, update_every int, os text, timezone text, tags text, hops INT);", + "CREATE TABLE IF NOT EXISTS host(host_id BLOB PRIMARY KEY, hostname TEXT, " + "registry_hostname TEXT, update_every INT, " + "os TEXT, timezone TEXT, tags TEXT, hops INT" + "memory_mode INT, abbrev_timezone TEXT, utc_offset INT, program_name TEXT, program_version TEXT, entries INT," + "health_enabled INT);", + "CREATE TABLE IF NOT EXISTS chart(chart_id blob PRIMARY KEY, host_id blob, type text, id text, name text, " "family text, context text, title text, unit text, plugin text, module text, priority int, update_every int, " "chart_type int, memory_mode int, history_entries);", @@ -849,6 +853,113 @@ bind_fail: return 1; } +// +// Store host and host system info information in the database +#define SQL_STORE_HOST_INFO "INSERT OR REPLACE INTO host " \ + "(host_id, hostname, registry_hostname, update_every, os, timezone," \ + "tags, hops, memory_mode, abbrev_timezone, utc_offset, program_name, program_version," \ + "entries, health_enabled) " \ + "values (@host_id, @hostname, @registry_hostname, @update_every, @os, @timezone, @tags, @hops, @memory_mode, " \ + "@abbrev_timezone, @utc_offset, @program_name, @program_version, " \ + "@entries, @health_enabled);" + +int sql_store_host_info(RRDHOST *host) +{ + static __thread sqlite3_stmt *res = NULL; + int rc; + + 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_HOST_INFO, &res); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to prepare statement to store host, rc = %d", rc); + return 1; + } + } + + rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + rc = bind_text_null(res, 2, host->hostname, 0); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + rc = bind_text_null(res, 3, host->registry_hostname, 1); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + rc = sqlite3_bind_int(res, 4, host->rrd_update_every); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + rc = bind_text_null(res, 5, host->os, 1); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + rc = bind_text_null(res, 6, host->timezone, 1); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + rc = bind_text_null(res, 7, host->tags, 1); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + rc = sqlite3_bind_int(res, 8, host->system_info ? host->system_info->hops : 0); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + rc = sqlite3_bind_int(res, 9, host->rrd_memory_mode); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + rc = bind_text_null(res, 10, host->abbrev_timezone, 1); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + rc = sqlite3_bind_int(res, 11, host->utc_offset); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + rc = bind_text_null(res, 12, host->program_name, 1); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + rc = bind_text_null(res, 13, host->program_version, 1); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + rc = sqlite3_bind_int64(res, 14, host->rrd_history_entries); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + rc = sqlite3_bind_int(res, 15, host->health_enabled); + if (unlikely(rc != SQLITE_OK)) + goto bind_fail; + + int store_rc = sqlite3_step(res); + if (unlikely(store_rc != SQLITE_DONE)) + error_report("Failed to store host %s, rc = %d", host->hostname, rc); + + rc = sqlite3_reset(res); + if (unlikely(rc != SQLITE_OK)) + error_report("Failed to reset statement to store host %s, rc = %d", host->hostname, rc); + + return !(store_rc == SQLITE_DONE); +bind_fail: + error_report("Failed to bind parameter to store host %s, rc = %d", host->hostname, rc); + rc = sqlite3_reset(res); + if (unlikely(rc != SQLITE_OK)) + error_report("Failed to reset statement to store host %s, rc = %d", host->hostname, rc); + return 1; +} + /* * Store a chart in the database */ @@ -2313,3 +2424,14 @@ failed: return; }; + +// Utils +int bind_text_null(sqlite3_stmt *res, int position, const char *text, bool can_be_null) +{ + if (likely(text)) + return sqlite3_bind_text(res, position, text, -1, SQLITE_STATIC); + if (!can_be_null) + return 1; + return sqlite3_bind_null(res, position); +} + diff --git a/database/sqlite/sqlite_functions.h b/database/sqlite/sqlite_functions.h index b26da6dab1..5295659c12 100644 --- a/database/sqlite/sqlite_functions.h +++ b/database/sqlite/sqlite_functions.h @@ -60,9 +60,12 @@ typedef enum db_check_action_type { extern int sql_init_database(db_check_action_type_t rebuild, int memory); extern void sql_close_database(void); - +extern int bind_text_null(sqlite3_stmt *res, int position, const char *text, bool can_be_null); extern int sql_store_host(uuid_t *guid, const char *hostname, const char *registry_hostname, int update_every, const char *os, const char *timezone, const char *tags, int hops); + +extern int sql_store_host_info(RRDHOST *host); + extern int sql_store_chart( uuid_t *chart_uuid, uuid_t *host_uuid, const char *type, const char *id, const char *name, const char *family, const char *context, const char *title, const char *units, const char *plugin, const char *module, long priority, -- cgit v1.2.3