From 1ee0c09c5742557e037df5421ca62abddb90ae22 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 19 May 2021 14:33:38 +0200 Subject: Merging upstream version 1.31.0. Signed-off-by: Daniel Baumann --- database/engine/metadata_log/metadatalog.h | 2 +- database/engine/pagecache.c | 2 +- database/engine/rrdengine.h | 2 +- database/engine/rrdengineapi.c | 4 +- database/rrd.h | 18 +- database/rrdcalc.c | 17 ++ database/rrdcalc.h | 5 +- database/rrdcalctemplate.c | 8 + database/rrdcalctemplate.h | 7 + database/rrddim.c | 10 +- database/rrdhost.c | 2 + database/rrdset.c | 13 +- database/sqlite/sqlite_functions.c | 297 ++++++++++++++++++++++++++++- database/sqlite/sqlite_functions.h | 17 ++ 14 files changed, 387 insertions(+), 17 deletions(-) (limited to 'database') diff --git a/database/engine/metadata_log/metadatalog.h b/database/engine/metadata_log/metadatalog.h index b484686de..483036a91 100644 --- a/database/engine/metadata_log/metadatalog.h +++ b/database/engine/metadata_log/metadatalog.h @@ -12,7 +12,7 @@ #include "metadatalogapi.h" #include "compaction.h" -/* Forward declerations */ +/* Forward declarations */ struct metalog_instance; struct parser_user_object; diff --git a/database/engine/pagecache.c b/database/engine/pagecache.c index d7698de01..f17afc22b 100644 --- a/database/engine/pagecache.c +++ b/database/engine/pagecache.c @@ -3,7 +3,7 @@ #include "rrdengine.h" -/* Forward declerations */ +/* Forward declarations */ static int pg_cache_try_evict_one_page_unsafe(struct rrdengine_instance *ctx); /* always inserts into tail */ diff --git a/database/engine/rrdengine.h b/database/engine/rrdengine.h index 2d48665f8..07cc1479d 100644 --- a/database/engine/rrdengine.h +++ b/database/engine/rrdengine.h @@ -26,7 +26,7 @@ #endif /* NETDATA_RRD_INTERNALS */ -/* Forward declerations */ +/* Forward declarations */ struct rrdengine_instance; #define MAX_PAGES_PER_EXTENT (64) /* TODO: can go higher only when journal supports bigger than 4KiB transactions */ diff --git a/database/engine/rrdengineapi.c b/database/engine/rrdengineapi.c index cb46e06e3..d847969e8 100755 --- a/database/engine/rrdengineapi.c +++ b/database/engine/rrdengineapi.c @@ -32,7 +32,7 @@ void rrdeng_generate_legacy_uuid(const char *dim_id, char *chart_id, uuid_t *ret memcpy(ret_uuid, hash_value, sizeof(uuid_t)); } -/* Transform legacy UUID to be unique across hosts deterministacally */ +/* Transform legacy UUID to be unique across hosts deterministically */ void rrdeng_convert_legacy_uuid_to_multihost(char machine_guid[GUID_LEN + 1], uuid_t *legacy_uuid, uuid_t *ret_uuid) { EVP_MD_CTX *evpctx; @@ -359,7 +359,7 @@ static inline uint32_t *pginfo_to_points(struct rrdeng_page_info *page_info) * reference dimension that that have different data collection intervals and overlap with the time range * [start_time,end_time]. The caller must free (*region_info_arrayp) with freez(). If region_info_arrayp is set * to NULL nothing was allocated. - * @param max_intervalp is derefenced and set to be the largest data collection interval of all regions. + * @param max_intervalp is dereferenced and set to be the largest data collection interval of all regions. * @return number of regions with different data collection intervals. */ unsigned rrdeng_variable_step_boundaries(RRDSET *st, time_t start_time, time_t end_time, diff --git a/database/rrd.h b/database/rrd.h index 59d0501bd..380ccb161 100644 --- a/database/rrd.h +++ b/database/rrd.h @@ -454,8 +454,8 @@ typedef enum rrdset_flags { // (the master data set should be the one that has the same family and is not detail) RRDSET_FLAG_DEBUG = 1 << 2, // enables or disables debugging for a chart RRDSET_FLAG_OBSOLETE = 1 << 3, // this is marked by the collector/module as obsolete - RRDSET_FLAG_BACKEND_SEND = 1 << 4, // if set, this chart should be sent to backends - RRDSET_FLAG_BACKEND_IGNORE = 1 << 5, // if set, this chart should not be sent to backends + RRDSET_FLAG_EXPORTING_SEND = 1 << 4, // if set, this chart should be sent to Prometheus web API + RRDSET_FLAG_EXPORTING_IGNORE = 1 << 5, // if set, this chart should not be sent to Prometheus web API RRDSET_FLAG_UPSTREAM_SEND = 1 << 6, // if set, this chart should be sent upstream (streaming) RRDSET_FLAG_UPSTREAM_IGNORE = 1 << 7, // if set, this chart should not be sent upstream (streaming) RRDSET_FLAG_UPSTREAM_EXPOSED = 1 << 8, // if set, we have sent this chart definition to netdata parent (streaming) @@ -468,7 +468,9 @@ typedef enum rrdset_flags { // No new values have been collected for this chart since agent start or it was marked RRDSET_FLAG_OBSOLETE at // least rrdset_free_obsolete_time seconds ago. RRDSET_FLAG_ARCHIVED = 1 << 15, - RRDSET_FLAG_ACLK = 1 << 16 + RRDSET_FLAG_ACLK = 1 << 16, + RRDSET_FLAG_BACKEND_SEND = 1 << 17, // if set, this chart should be sent to backends + RRDSET_FLAG_BACKEND_IGNORE = 1 << 18 // if set, this chart should not be sent to backends } RRDSET_FLAGS; #ifdef HAVE_C___ATOMIC @@ -666,6 +668,10 @@ struct alarm_entry { char *family; + char *classification; + char *component; + char *type; + char *exec; char *recipient; time_t exec_run_timestamp; @@ -758,6 +764,9 @@ struct rrdhost { const char *os; // the O/S type of the host const char *tags; // tags for this host const char *timezone; // the timezone of the host +#ifdef ENABLE_ACLK + long obsolete_count; +#endif RRDHOST_FLAGS flags; // flags about this RRDHOST RRDHOST_FLAGS *exporting_flags; // array of flags for exporting connector instances @@ -819,7 +828,7 @@ struct rrdhost { char *health_default_exec; // the full path of the alarms notifications program char *health_default_recipient; // the default recipient for all alarms char *health_log_filename; // the alarms event log filename - size_t health_log_entries_written; // the number of alarm events writtern to the alarms event log + size_t health_log_entries_written; // the number of alarm events written to the alarms event log FILE *health_log_fp; // the FILE pointer to the open alarms event log file uint32_t health_default_warn_repeat_every; // the default value for the interval between repeating warning notifications uint32_t health_default_crit_repeat_every; // the default value for the interval between repeating critical notifications @@ -873,6 +882,7 @@ struct rrdhost { struct rrdengine_instance *rrdeng_ctx; // DB engine instance for this host #endif uuid_t host_uuid; // Global GUID for this host + uuid_t *node_id; // Cloud node_id #ifdef ENABLE_HTTPS struct netdata_ssl ssl; //Structure used to encrypt the connection diff --git a/database/rrdcalc.c b/database/rrdcalc.c index bc91da64f..85b9efb75 100644 --- a/database/rrdcalc.c +++ b/database/rrdcalc.c @@ -91,6 +91,9 @@ static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) { rc->name, rc->rrdset->id, rc->rrdset->family, + rc->classification, + rc->component, + rc->type, rc->exec, rc->recipient, now - rc->last_status_change, @@ -165,6 +168,9 @@ inline void rrdsetcalc_unlink(RRDCALC *rc) { rc->name, rc->rrdset->id, rc->rrdset->family, + rc->classification, + rc->component, + rc->type, rc->exec, rc->recipient, now - rc->last_status_change, @@ -428,6 +434,10 @@ inline RRDCALC *rrdcalc_create_from_template(RRDHOST *host, RRDCALCTEMPLATE *rt, if(rt->units) rc->units = strdupz(rt->units); if(rt->info) rc->info = strdupz(rt->info); + if (rt->classification) rc->classification = strdupz(rt->classification); + if (rt->component) rc->component = strdupz(rt->component); + if (rt->type) rc->type = strdupz(rt->type); + if(rt->calculation) { rc->calculation = expression_parse(rt->calculation->source, NULL, NULL); if(!rc->calculation) @@ -535,6 +545,10 @@ inline RRDCALC *rrdcalc_create_from_rrdcalc(RRDCALC *rc, RRDHOST *host, const ch if(rc->units) newrc->units = strdupz(rc->units); if(rc->info) newrc->info = strdupz(rc->info); + if (rc->classification) newrc->classification = strdupz(rc->classification); + if (rc->component) newrc->component = strdupz(rc->component); + if (rc->type) newrc->type = strdupz(rc->type); + if(rc->calculation) { newrc->calculation = expression_parse(rc->calculation->source, NULL, NULL); if(!newrc->calculation) @@ -573,6 +587,9 @@ void rrdcalc_free(RRDCALC *rc) { freez(rc->source); freez(rc->units); freez(rc->info); + freez(rc->classification); + freez(rc->component); + freez(rc->type); simple_pattern_free(rc->spdim); freez(rc->labels); simple_pattern_free(rc->splabels); diff --git a/database/rrdcalc.h b/database/rrdcalc.h index 27ff99a89..b4122c605 100644 --- a/database/rrdcalc.h +++ b/database/rrdcalc.h @@ -42,10 +42,13 @@ struct rrdcalc { char *exec; // the command to execute when this alarm switches state char *recipient; // the recipient of the alarm (the first parameter to exec) + char *classification; // the class that this alarm belongs + char *component; // the component that this alarm refers to + char *type; // type of the alarm + char *chart; // the chart id this should be linked to uint32_t hash_chart; - char *plugin_match; //the plugin name that should be linked to SIMPLE_PATTERN *plugin_pattern; diff --git a/database/rrdcalctemplate.c b/database/rrdcalctemplate.c index 007b8c5d6..5060313ec 100644 --- a/database/rrdcalctemplate.c +++ b/database/rrdcalctemplate.c @@ -45,6 +45,11 @@ static int rrdcalctemplate_is_there_label_restriction(RRDCALCTEMPLATE *rt, RRDH } static inline int rrdcalctemplate_test_additional_restriction(RRDCALCTEMPLATE *rt, RRDSET *st) { + if (rt->charts_pattern && + !(simple_pattern_matches(rt->charts_pattern, st->id) || + simple_pattern_matches(rt->charts_pattern, st->name))) + return 0; + if (rt->family_pattern && !simple_pattern_matches(rt->family_pattern, st->family)) return 0; @@ -111,6 +116,9 @@ inline void rrdcalctemplate_free(RRDCALCTEMPLATE *rt) { freez(rt->module_match); simple_pattern_free(rt->module_pattern); + freez(rt->charts_match); + simple_pattern_free(rt->charts_pattern); + freez(rt->name); freez(rt->exec); freez(rt->recipient); diff --git a/database/rrdcalctemplate.h b/database/rrdcalctemplate.h index fb9347d73..65114da6a 100644 --- a/database/rrdcalctemplate.h +++ b/database/rrdcalctemplate.h @@ -15,6 +15,10 @@ struct rrdcalctemplate { char *exec; char *recipient; + char *classification; + char *component; + char *type; + char *context; uint32_t hash_context; @@ -27,6 +31,9 @@ struct rrdcalctemplate { char *module_match; SIMPLE_PATTERN *module_pattern; + char *charts_match; + SIMPLE_PATTERN *charts_pattern; + char *source; // the source of this alarm char *units; // the units of the alarm char *info; // a short description of the alarm diff --git a/database/rrddim.c b/database/rrddim.c index b4ea34d2d..510538d4b 100644 --- a/database/rrddim.c +++ b/database/rrddim.c @@ -187,14 +187,14 @@ void rrdcalc_link_to_rrddim(RRDDIM *rd, RRDSET *st, RRDHOST *host) { for (rrdc = host->alarms_with_foreach; rrdc ; rrdc = rrdc->next) { if (simple_pattern_matches(rrdc->spdim, rd->id) || simple_pattern_matches(rrdc->spdim, rd->name)) { if (rrdc->hash_chart == st->hash_name || !strcmp(rrdc->chart, st->name) || !strcmp(rrdc->chart, st->id)) { - char *usename = alarm_name_with_dim(rrdc->name, strlen(rrdc->name), rd->name, strlen(rd->name)); - if (usename) { - if(rrdcalc_exists(host, st->name, usename, 0, 0)){ - freez(usename); + char *name = alarm_name_with_dim(rrdc->name, strlen(rrdc->name), rd->name, strlen(rd->name)); + if (name) { + if(rrdcalc_exists(host, st->name, name, 0, 0)){ + freez(name); continue; } - RRDCALC *child = rrdcalc_create_from_rrdcalc(rrdc, host, usename, rd->name); + RRDCALC *child = rrdcalc_create_from_rrdcalc(rrdc, host, name, rd->name); if (child) { rrdcalc_add_to_host(host, child); RRDCALC *rdcmp = (RRDCALC *) avl_insert_lock(&(host)->alarms_idx_health_log,(avl_t *)child); diff --git a/database/rrdhost.c b/database/rrdhost.c index ae49036a8..5ce5366d2 100644 --- a/database/rrdhost.c +++ b/database/rrdhost.c @@ -302,6 +302,7 @@ RRDHOST *rrdhost_create(const char *hostname, int rc = sql_store_host(&host->host_uuid, hostname, registry_hostname, update_every, os, timezone, tags); if (unlikely(rc)) error_report("Failed to store machine GUID to the database"); + sql_load_node_id(host); } else error_report("Host machine GUID %s is not valid", host->machine_guid); @@ -899,6 +900,7 @@ void rrdhost_free(RRDHOST *host) { netdata_rwlock_destroy(&host->labels.labels_rwlock); netdata_rwlock_destroy(&host->health_log.alarm_log_rwlock); netdata_rwlock_destroy(&host->rrdhost_rwlock); + freez(host->node_id); freez(host); diff --git a/database/rrdset.c b/database/rrdset.c index 15640d3ed..fd6605dff 100644 --- a/database/rrdset.c +++ b/database/rrdset.c @@ -175,6 +175,8 @@ int rrdset_set_name(RRDSET *st, const char *name) { if(unlikely(rrdset_index_add_name(host, st) != st)) error("RRDSET: INTERNAL ERROR: attempted to index duplicate chart name '%s'", st->name); + rrdset_flag_clear(st, RRDSET_FLAG_EXPORTING_SEND); + rrdset_flag_clear(st, RRDSET_FLAG_EXPORTING_IGNORE); rrdset_flag_clear(st, RRDSET_FLAG_BACKEND_SEND); rrdset_flag_clear(st, RRDSET_FLAG_BACKEND_IGNORE); rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_SEND); @@ -450,7 +452,7 @@ void rrdset_delete_custom(RRDSET *st, int db_rotated) { #ifdef ENABLE_ACLK if ((netdata_cloud_setting) && (db_rotated || RRD_MEMORY_MODE_DBENGINE != st->rrd_memory_mode)) { aclk_del_collector(st->rrdhost, st->plugin_name, st->module_name); - aclk_update_chart(st->rrdhost, st->id, ACLK_CMD_CHARTDEL); + st->rrdhost->obsolete_count++; } #endif @@ -858,6 +860,8 @@ RRDSET *rrdset_create_custom( rrdset_flag_clear(st, RRDSET_FLAG_DETAIL); rrdset_flag_clear(st, RRDSET_FLAG_DEBUG); rrdset_flag_clear(st, RRDSET_FLAG_OBSOLETE); + rrdset_flag_clear(st, RRDSET_FLAG_EXPORTING_SEND); + rrdset_flag_clear(st, RRDSET_FLAG_EXPORTING_IGNORE); rrdset_flag_clear(st, RRDSET_FLAG_BACKEND_SEND); rrdset_flag_clear(st, RRDSET_FLAG_BACKEND_IGNORE); rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_SEND); @@ -928,7 +932,14 @@ RRDSET *rrdset_create_custom( store_active_chart(st->chart_uuid); +#ifdef ENABLE_ACLK + host->obsolete_count = 0; +#endif rrdhost_cleanup_obsolete_charts(host); +#ifdef ENABLE_ACLK + if (host->obsolete_count) + aclk_update_chart(st->rrdhost, "dummy-chart", ACLK_CMD_CHARTDEL); +#endif rrdhost_unlock(host); #ifdef ENABLE_ACLK diff --git a/database/sqlite/sqlite_functions.c b/database/sqlite/sqlite_functions.c index 694b86330..382ed8b02 100644 --- a/database/sqlite/sqlite_functions.c +++ b/database/sqlite/sqlite_functions.c @@ -19,7 +19,7 @@ const char *database_config[] = { "CREATE INDEX IF NOT EXISTS ind_c1 on chart (host_id, id, type, name);", "CREATE TABLE IF NOT EXISTS chart_label(chart_id blob, source_type int, label_key text, " "label_value text, date_created int, PRIMARY KEY (chart_id, label_key));", - + "CREATE TABLE IF NOT EXISTS node_instance (host_id blob PRIMARY KEY, claim_id, node_id, date_created);", "delete from chart_active;", "delete from dimension_active;", "delete from chart where chart_id not in (select chart_id from dimension);", @@ -1338,3 +1338,298 @@ failed: #endif return; } + +#define SQL_STORE_CLAIM_ID "insert into node_instance " \ + "(host_id, claim_id, date_created) values (@host_id, @claim_id, strftime('%s')) " \ + "on conflict(host_id) do update set claim_id = excluded.claim_id;" + +void store_claim_id(uuid_t *host_id, uuid_t *claim_id) +{ + sqlite3_stmt *res = NULL; + int rc; + + if (unlikely(!db_meta)) { + if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) + error_report("Database has not been initialized"); + return; + } + + rc = sqlite3_prepare_v2(db_meta, SQL_STORE_CLAIM_ID, -1, &res, 0); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to prepare statement store chart labels"); + return; + } + + rc = sqlite3_bind_blob(res, 1, host_id, sizeof(*host_id), SQLITE_STATIC); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to bind host_id parameter to store node instance information"); + goto failed; + } + + if (claim_id) + rc = sqlite3_bind_blob(res, 2, claim_id, sizeof(*claim_id), SQLITE_STATIC); + else + rc = sqlite3_bind_null(res, 2); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to bind claim_id parameter to store node instance information"); + goto failed; + } + + rc = execute_insert(res); + if (unlikely(rc != SQLITE_DONE)) + error_report("Failed to store node instance information, rc = %d", rc); + +failed: + if (unlikely(sqlite3_finalize(res) != SQLITE_OK)) + error_report("Failed to finalize the prepared statement when storing node instance information"); + + return; +} + +static inline void set_host_node_id(RRDHOST *host, uuid_t *node_id) +{ + if (unlikely(!host)) + return; + + if (unlikely(!node_id)) { + freez(host->node_id); + host->node_id = NULL; + return; + } + + if (unlikely(!host->node_id)) + host->node_id = mallocz(sizeof(*host->node_id)); + uuid_copy(*(host->node_id), *node_id); + return; +} + +#define SQL_UPDATE_NODE_ID "update node_instance set node_id = @node_id where host_id = @host_id;" + +int update_node_id(uuid_t *host_id, uuid_t *node_id) +{ + sqlite3_stmt *res = NULL; + RRDHOST *host = NULL; + int rc = 2; + + if (unlikely(!db_meta)) { + if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) + error_report("Database has not been initialized"); + return 1; + } + + rc = sqlite3_prepare_v2(db_meta, SQL_UPDATE_NODE_ID, -1, &res, 0); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to prepare statement to store node instance information"); + return 1; + } + + rc = sqlite3_bind_blob(res, 1, node_id, sizeof(*node_id), SQLITE_STATIC); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to bind host_id parameter to store node instance information"); + goto failed; + } + + rc = sqlite3_bind_blob(res, 2, host_id, sizeof(*host_id), SQLITE_STATIC); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to bind host_id parameter to store node instance information"); + goto failed; + } + + rc = execute_insert(res); + if (unlikely(rc != SQLITE_DONE)) + error_report("Failed to store node instance information, rc = %d", rc); + rc = sqlite3_changes(db_meta); + + char host_guid[GUID_LEN + 1]; + uuid_unparse_lower(*host_id, host_guid); + rrd_wrlock(); + host = rrdhost_find_by_guid(host_guid, 0); + if (likely(host)) + set_host_node_id(host, node_id); + rrd_unlock(); + +failed: + if (unlikely(sqlite3_finalize(res) != SQLITE_OK)) + error_report("Failed to finalize the prepared statement when storing node instance information"); + + return rc - 1; +} + +#define SQL_SELECT_NODE_ID "select node_id from node_instance where host_id = @host_id and node_id not null;" + +int get_node_id(uuid_t *host_id, uuid_t *node_id) +{ + sqlite3_stmt *res = NULL; + int rc; + + if (unlikely(!db_meta)) { + if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) + error_report("Database has not been initialized"); + return 1; + } + + rc = sqlite3_prepare_v2(db_meta, SQL_SELECT_NODE_ID, -1, &res, 0); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to prepare statement to select node instance information for a host"); + return 1; + } + + rc = sqlite3_bind_blob(res, 1, host_id, sizeof(*host_id), SQLITE_STATIC); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to bind host_id parameter to select node instance information"); + goto failed; + } + + rc = sqlite3_step(res); + if (likely(rc == SQLITE_ROW && node_id)) + uuid_copy(*node_id, *((uuid_t *) sqlite3_column_blob(res, 0))); + +failed: + if (unlikely(sqlite3_finalize(res) != SQLITE_OK)) + error_report("Failed to finalize the prepared statement when selecting node instance information"); + + return (rc == SQLITE_ROW) ? 0 : -1; +} + +#define SQL_INVALIDATE_NODE_INSTANCES "update node_instance set node_id = NULL where exists " \ + "(select host_id from node_instance where host_id = @host_id and (@claim_id is null or claim_id <> @claim_id));" + +void invalidate_node_instances(uuid_t *host_id, uuid_t *claim_id) +{ + sqlite3_stmt *res = NULL; + int rc; + + if (unlikely(!db_meta)) { + if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) + error_report("Database has not been initialized"); + return; + } + + rc = sqlite3_prepare_v2(db_meta, SQL_INVALIDATE_NODE_INSTANCES, -1, &res, 0); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to prepare statement to invalidate node instance ids"); + return; + } + + rc = sqlite3_bind_blob(res, 1, host_id, sizeof(*host_id), SQLITE_STATIC); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to bind host_id parameter to invalidate node instance information"); + goto failed; + } + + if (claim_id) + rc = sqlite3_bind_blob(res, 2, claim_id, sizeof(*claim_id), SQLITE_STATIC); + else + rc = sqlite3_bind_null(res, 2); + + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to bind claim_id parameter to invalidate node instance information"); + goto failed; + } + + rc = execute_insert(res); + if (unlikely(rc != SQLITE_DONE)) + error_report("Failed to invalidate node instance information, rc = %d", rc); + +failed: + if (unlikely(sqlite3_finalize(res) != SQLITE_OK)) + error_report("Failed to finalize the prepared statement when invalidating node instance information"); +} + +#define SQL_GET_NODE_INSTANCE_LIST "select ni.node_id, ni.host_id, h.hostname " \ + "from node_instance ni, host h where ni.host_id = h.host_id;" + +struct node_instance_list *get_node_list(void) +{ + struct node_instance_list *node_list = NULL; + sqlite3_stmt *res = NULL; + int rc; + + if (unlikely(!db_meta)) { + if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) + error_report("Database has not been initialized"); + return NULL; + } + + rc = sqlite3_prepare_v2(db_meta, SQL_GET_NODE_INSTANCE_LIST, -1, &res, 0); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to prepare statement store chart labels"); + return NULL; + }; + + int row = 0; + char host_guid[37]; + while (sqlite3_step(res) == SQLITE_ROW) + row++; + + if (sqlite3_reset(res) != SQLITE_OK) { + error_report("Failed to reset the prepared statement fetching storing node instance information"); + goto failed; + } + node_list = callocz(row + 1, sizeof(*node_list)); + int max_rows = row; + row = 0; + while (sqlite3_step(res) == SQLITE_ROW) { + if (sqlite3_column_bytes(res, 0) == sizeof(uuid_t)) + uuid_copy(node_list[row].node_id, *((uuid_t *)sqlite3_column_blob(res, 0))); + if (sqlite3_column_bytes(res, 1) == sizeof(uuid_t)) { + uuid_t *host_id = (uuid_t *)sqlite3_column_blob(res, 1); + uuid_copy(node_list[row].host_id, *host_id); + node_list[row].querable = 1; + uuid_unparse_lower(*host_id, host_guid); + node_list[row].live = rrdhost_find_by_guid(host_guid, 0) ? 1 : 0; + node_list[row].hops = uuid_compare(*host_id, localhost->host_uuid) ? 1 : 0; + node_list[row].hostname = + sqlite3_column_bytes(res, 2) ? strdupz((char *)sqlite3_column_text(res, 2)) : NULL; + } + row++; + if (row == max_rows) + break; + } + +failed: + if (unlikely(sqlite3_finalize(res) != SQLITE_OK)) + error_report("Failed to finalize the prepared statement when storing node instance information"); + + return node_list; +}; + +#define SQL_GET_HOST_NODE_ID "select node_id from node_instance where host_id = @host_id;" + +void sql_load_node_id(RRDHOST *host) +{ + sqlite3_stmt *res = NULL; + int rc; + + if (unlikely(!db_meta)) { + if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) + error_report("Database has not been initialized"); + return; + } + + rc = sqlite3_prepare_v2(db_meta, SQL_GET_HOST_NODE_ID, -1, &res, 0); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to prepare statement store chart labels"); + 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 parameter to store node instance information"); + goto failed; + } + + rc = sqlite3_step(res); + if (likely(rc == SQLITE_ROW)) { + if (likely(sqlite3_column_bytes(res, 0) == sizeof(uuid_t))) + set_host_node_id(host, (uuid_t *)sqlite3_column_blob(res, 0)); + else + set_host_node_id(host, NULL); + } + +failed: + if (unlikely(sqlite3_finalize(res) != SQLITE_OK)) + error_report("Failed to finalize the prepared statement when storing node instance information"); + + return; +}; diff --git a/database/sqlite/sqlite_functions.h b/database/sqlite/sqlite_functions.h index d2bee75d2..30a52bf73 100644 --- a/database/sqlite/sqlite_functions.h +++ b/database/sqlite/sqlite_functions.h @@ -6,6 +6,17 @@ #include "../../daemon/common.h" #include "sqlite3.h" +// return a node list +struct node_instance_list { + uuid_t node_id; + uuid_t host_id; + char *hostname; + int live; + int querable; + int hops; +}; + + #define SQLITE_INSERT_DELAY (50) // Insert delay in case of lock #define SQL_STORE_HOST "insert or replace into host (host_id,hostname,registry_hostname,update_every,os,timezone,tags) values (?1,?2,?3,?4,?5,?6,?7);" @@ -60,4 +71,10 @@ extern void db_lock(void); extern void delete_dimension_uuid(uuid_t *dimension_uuid); extern void sql_store_chart_label(uuid_t *chart_uuid, int source_type, char *label, char *value); extern void sql_build_context_param_list(struct context_param **param_list, RRDHOST *host, char *context, char *chart); +extern void store_claim_id(uuid_t *host_id, uuid_t *claim_id); +extern int update_node_id(uuid_t *host_id, uuid_t *node_id); +extern int get_node_id(uuid_t *host_id, uuid_t *node_id); +extern void invalidate_node_instances(uuid_t *host_id, uuid_t *claim_id); +extern struct node_instance_list *get_node_list(void); +extern void sql_load_node_id(RRDHOST *host); #endif //NETDATA_SQLITE_FUNCTIONS_H -- cgit v1.2.3