summaryrefslogtreecommitdiffstats
path: root/database
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2021-05-19 12:33:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2021-05-19 12:33:27 +0000
commit841395dd16f470e3c051a0a4fff5b91efc983c30 (patch)
tree4115f6eedcddda75067130b80acaff9e51612f49 /database
parentAdding upstream version 1.30.1. (diff)
downloadnetdata-841395dd16f470e3c051a0a4fff5b91efc983c30.tar.xz
netdata-841395dd16f470e3c051a0a4fff5b91efc983c30.zip
Adding upstream version 1.31.0.upstream/1.31.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'database')
-rw-r--r--database/engine/metadata_log/metadatalog.h2
-rw-r--r--database/engine/pagecache.c2
-rw-r--r--database/engine/rrdengine.h2
-rwxr-xr-xdatabase/engine/rrdengineapi.c4
-rw-r--r--database/rrd.h18
-rw-r--r--database/rrdcalc.c17
-rw-r--r--database/rrdcalc.h5
-rw-r--r--database/rrdcalctemplate.c8
-rw-r--r--database/rrdcalctemplate.h7
-rw-r--r--database/rrddim.c10
-rw-r--r--database/rrdhost.c2
-rw-r--r--database/rrdset.c13
-rw-r--r--database/sqlite/sqlite_functions.c297
-rw-r--r--database/sqlite/sqlite_functions.h17
14 files changed, 387 insertions, 17 deletions
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