summaryrefslogtreecommitdiffstats
path: root/database/rrdset.c
diff options
context:
space:
mode:
Diffstat (limited to 'database/rrdset.c')
-rw-r--r--database/rrdset.c659
1 files changed, 335 insertions, 324 deletions
diff --git a/database/rrdset.c b/database/rrdset.c
index 1e00d5c8a2..d55be76f1b 100644
--- a/database/rrdset.c
+++ b/database/rrdset.c
@@ -1,9 +1,290 @@
// SPDX-License-Identifier: GPL-3.0-or-later
-#define NETDATA_RRD_INTERNALS
#include "rrd.h"
#include <sched.h>
-#include "storage_engine.h"
+
+#ifdef NETDATA_INTERNAL_CHECKS
+#define rrdset_debug(st, fmt, args...) do { \
+ if(unlikely((debug_flags & D_RRD_STATS) && rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) \
+ debug_int(__FILE__, __FUNCTION__, __LINE__, "%s: " fmt, rrdset_name(st), ##args); \
+} while(0)
+#else
+#define rrdset_debug(st, fmt, args...) debug_dummy()
+#endif
+
+// ----------------------------------------------------------------------------
+// RRDSET - helpers for rrdset_create()
+
+inline long align_entries_to_pagesize(STORAGE_ENGINE_ID id, long entries) {
+ if(id == STORAGE_ENGINE_DBENGINE)
+ return 0;
+
+ if(id == STORAGE_ENGINE_NONE)
+ return 5;
+
+ if(entries < 5) entries = 5;
+ if(entries > RRD_HISTORY_ENTRIES_MAX) entries = RRD_HISTORY_ENTRIES_MAX;
+
+ if(id == STORAGE_ENGINE_MAP || id == STORAGE_ENGINE_SAVE || id == STORAGE_ENGINE_RAM) {
+ long header_size = 0;
+
+ if(id == STORAGE_ENGINE_MAP || id == STORAGE_ENGINE_SAVE)
+ header_size = (long)rrddim_memory_file_header_size();
+
+ long page = (long)sysconf(_SC_PAGESIZE);
+ long size = (long)(header_size + entries * sizeof(storage_number));
+ if (unlikely(size % page)) {
+ size -= (size % page);
+ size += page;
+
+ long n = (long)((size - header_size) / sizeof(storage_number));
+ return n;
+ }
+ }
+
+ return entries;
+}
+
+static inline void last_collected_time_align(RRDSET *st) {
+ st->last_collected_time.tv_sec -= st->last_collected_time.tv_sec % st->update_every;
+
+ if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_STORE_FIRST)))
+ st->last_collected_time.tv_usec = 0;
+ else
+ st->last_collected_time.tv_usec = 500000;
+}
+
+static inline void last_updated_time_align(RRDSET *st) {
+ st->last_updated.tv_sec -= st->last_updated.tv_sec % st->update_every;
+ st->last_updated.tv_usec = 0;
+}
+
+// ----------------------------------------------------------------------------
+// compatibility layer for RRDSET files v019
+
+#define RRDSET_MAGIC_V019 "NETDATA RRD SET FILE V019"
+#define RRD_ID_LENGTH_MAX_V019 200
+
+struct avl_element_v019 {
+ void *avl_link[2];
+ signed char avl_balance;
+};
+
+struct avl_tree_type_v019 {
+ void *root;
+ int (*compar)(void *a, void *b);
+};
+
+struct avl_tree_lock_v019 {
+ struct avl_tree_type_v019 avl_tree;
+ pthread_rwlock_t rwlock;
+};
+
+struct rrdset_map_save_v019 {
+ struct avl_element_v019 avl; // ignored
+ struct avl_element_v019 avlname; // ignored
+ char id[RRD_ID_LENGTH_MAX_V019 + 1]; // check to reset all - update on load
+ void *name; // ignored
+ void *unused_ptr; // ignored
+ void *type; // ignored
+ void *family; // ignored
+ void *title; // ignored
+ void *units; // ignored
+ void *context; // ignored
+ uint32_t hash_context; // ignored
+ uint32_t chart_type; // ignored
+ int update_every; // check to reset all - update on load
+ long entries; // check to reset all - update on load
+ long current_entry; // NEEDS TO BE UPDATED - FIXED ON LOAD
+ uint32_t flags; // ignored
+ void *exporting_flags; // ignored
+ int gap_when_lost_iterations_above; // ignored
+ long priority; // ignored
+ uint32_t storage_engine_id; // ignored
+ void *cache_dir; // ignored
+ char cache_filename[FILENAME_MAX+1]; // ignored - update on load
+ pthread_rwlock_t rrdset_rwlock; // ignored
+ size_t counter; // NEEDS TO BE UPDATED - maintained on load
+ size_t counter_done; // ignored
+ union { //
+ time_t last_accessed_time_s; // ignored
+ time_t last_entry_s; // ignored
+ }; //
+ time_t upstream_resync_time; // ignored
+ void *plugin_name; // ignored
+ void *module_name; // ignored
+ void *chart_uuid; // ignored
+ void *state; // ignored
+ size_t unused[3]; // ignored
+ size_t rrddim_page_alignment; // ignored
+ uint32_t hash; // ignored
+ uint32_t hash_name; // ignored
+ usec_t usec_since_last_update; // NEEDS TO BE UPDATED - maintained on load
+ struct timeval last_updated; // NEEDS TO BE UPDATED - check to reset all - fixed on load
+ struct timeval last_collected_time; // ignored
+ long long collected_total; // ignored
+ long long last_collected_total; // ignored
+ void *rrdfamily; // ignored
+ void *rrdhost; // ignored
+ void *next; // ignored
+ long double green; // ignored
+ long double red; // ignored
+ struct avl_tree_lock_v019 rrdvar_root_index; // ignored
+ void *variables; // ignored
+ void *alarms; // ignored
+ unsigned long memsize; // check to reset all - update on load
+ char magic[sizeof(RRDSET_MAGIC_V019) + 1]; // check to reset all - update on load
+ struct avl_tree_lock_v019 dimensions_index; // ignored
+ void *dimensions; // ignored
+};
+
+void rrdset_memory_file_update(RRDSET *st) {
+ if(!st->db.st_on_file) return;
+ struct rrdset_map_save_v019 *st_on_file = st->db.st_on_file;
+
+ st_on_file->current_entry = st->db.current_entry;
+ st_on_file->counter = st->counter;
+ st_on_file->usec_since_last_update = st->usec_since_last_update;
+ st_on_file->last_updated.tv_sec = st->last_updated.tv_sec;
+ st_on_file->last_updated.tv_usec = st->last_updated.tv_usec;
+}
+
+const char *rrdset_cache_filename(RRDSET *st) {
+ if(!st->db.st_on_file) return NULL;
+ struct rrdset_map_save_v019 *st_on_file = st->db.st_on_file;
+ return st_on_file->cache_filename;
+}
+
+const char *rrdset_cache_dir(RRDSET *st) {
+ if (st->db.cache_dir)
+ return st->db.cache_dir;
+
+ char b[FILENAME_MAX + 1];
+ rrdset_strncpyz_name(b, rrdset_id(st), FILENAME_MAX);
+
+ char n[FILENAME_MAX + 1];
+ snprintfz(n, FILENAME_MAX, "%s/%s", st->rrdhost->cache_dir, b);
+
+ st->db.cache_dir = strdupz(n);
+
+ if (st->rrdhost->storage_engine_id == STORAGE_ENGINE_MAP ||
+ st->rrdhost->storage_engine_id == STORAGE_ENGINE_SAVE)
+ {
+ int r = mkdir(st->db.cache_dir, 0775);
+ if(r != 0 && errno != EEXIST)
+ netdata_log_error("Cannot create directory '%s'", st->db.cache_dir);
+ }
+
+ return st->db.cache_dir;
+}
+
+void rrdset_memory_file_free(RRDSET *st) {
+ if(!st->db.st_on_file) return;
+
+ // needed for storage engine MAP, to save the latest state
+ rrdset_memory_file_update(st);
+
+ struct rrdset_map_save_v019 *st_on_file = st->db.st_on_file;
+ __atomic_sub_fetch(&rrddim_db_memory_size, st_on_file->memsize, __ATOMIC_RELAXED);
+ netdata_munmap(st_on_file, st_on_file->memsize);
+
+ // remove the pointers from the RRDDIM
+ st->db.st_on_file = NULL;
+}
+
+void rrdset_memory_file_save(RRDSET *st) {
+ if(!st->db.st_on_file) return;
+
+ rrdset_memory_file_update(st);
+
+ struct rrdset_map_save_v019 *st_on_file = st->db.st_on_file;
+ if(st_on_file->storage_engine_id != STORAGE_ENGINE_SAVE) return;
+
+ memory_file_save(st_on_file->cache_filename, st->db.st_on_file, st_on_file->memsize);
+}
+
+static bool rrdset_memory_load_or_create_map_save(RRDSET *st) {
+ if (st->storage_engine_id != STORAGE_ENGINE_SAVE && st->storage_engine_id != STORAGE_ENGINE_MAP)
+ return false;
+
+ char fullfilename[FILENAME_MAX + 1];
+ snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", rrdset_cache_dir(st));
+
+ unsigned long size = sizeof(struct rrdset_map_save_v019);
+ struct rrdset_map_save_v019 *st_on_file = (struct rrdset_map_save_v019 *)netdata_mmap(
+ fullfilename, size, ((st->storage_engine_id == STORAGE_ENGINE_MAP) ? MAP_SHARED : MAP_PRIVATE), 0, false, NULL);
+
+ if(!st_on_file) return false;
+
+ time_t now_s = now_realtime_sec();
+
+ st_on_file->magic[sizeof(RRDSET_MAGIC_V019)] = '\0';
+ if(strcmp(st_on_file->magic, RRDSET_MAGIC_V019) != 0) {
+ netdata_log_info("Initializing file '%s'.", fullfilename);
+ memset(st_on_file, 0, size);
+ }
+ else if(strncmp(st_on_file->id, rrdset_id(st), RRD_ID_LENGTH_MAX_V019) != 0) {
+ netdata_log_error("File '%s' contents are not for chart '%s'. Clearing it.", fullfilename, rrdset_id(st));
+ memset(st_on_file, 0, size);
+ }
+ else if(st_on_file->memsize != size || st_on_file->entries != st->db.entries) {
+ netdata_log_error("File '%s' does not have the desired size. Clearing it.", fullfilename);
+ memset(st_on_file, 0, size);
+ }
+ else if(st_on_file->update_every != st->update_every) {
+ netdata_log_error("File '%s' does not have the desired granularity. Clearing it.", fullfilename);
+ memset(st_on_file, 0, size);
+ }
+ else if((now_s - st_on_file->last_updated.tv_sec) > (long)st->update_every * (long)st->db.entries) {
+ netdata_log_info("File '%s' is too old. Clearing it.", fullfilename);
+ memset(st_on_file, 0, size);
+ }
+ else if(st_on_file->last_updated.tv_sec > now_s + st->update_every) {
+ netdata_log_error("File '%s' refers to the future by %zd secs. Resetting it to now.", fullfilename, (ssize_t)(st_on_file->last_updated.tv_sec - now_s));
+ st_on_file->last_updated.tv_sec = now_s;
+ }
+
+ if(st_on_file->current_entry >= st_on_file->entries)
+ st_on_file->current_entry = 0;
+
+ // make sure the database is aligned
+ bool align_last_updated = false;
+ if(st_on_file->last_updated.tv_sec) {
+ st_on_file->update_every = st->update_every;
+ align_last_updated = true;
+ }
+
+ // copy the useful values to st
+ st->db.current_entry = st_on_file->current_entry;
+ st->counter = st_on_file->counter;
+ st->usec_since_last_update = st_on_file->usec_since_last_update;
+ st->last_updated.tv_sec = st_on_file->last_updated.tv_sec;
+ st->last_updated.tv_usec = st_on_file->last_updated.tv_usec;
+
+ // link it to st
+ st->db.st_on_file = st_on_file;
+
+ // clear everything
+ memset(st_on_file, 0, size);
+
+ // set the values we need
+ strncpyz(st_on_file->id, rrdset_id(st), RRD_ID_LENGTH_MAX_V019);
+ strcpy(st_on_file->cache_filename, fullfilename);
+ strcpy(st_on_file->magic, RRDSET_MAGIC_V019);
+ st_on_file->memsize = size;
+ st_on_file->entries = st->db.entries;
+ st_on_file->update_every = st->update_every;
+ st_on_file->storage_engine_id = st->storage_engine_id;
+
+ if(align_last_updated)
+ last_updated_time_align(st);
+
+ // copy the useful values back to st_on_file
+ rrdset_memory_file_update(st);
+
+ __atomic_add_fetch(&rrddim_db_memory_size, st_on_file->memsize, __ATOMIC_RELAXED);
+ return true;
+}
// ----------------------------------------------------------------------------
// RRDSET name index
@@ -87,7 +368,7 @@ struct rrdset_constructor {
long priority;
int update_every;
RRDSET_TYPE chart_type;
- RRD_MEMORY_MODE memory_mode;
+ STORAGE_ENGINE_ID storage_engine_id;
long history_entries;
enum {
@@ -128,9 +409,9 @@ static void rrdset_insert_callback(const DICTIONARY_ITEM *item __maybe_unused, v
st->module_name = rrd_string_strdupz(ctr->module);
st->priority = ctr->priority;
- st->db.entries = (ctr->memory_mode != RRD_MEMORY_MODE_DBENGINE) ? align_entries_to_pagesize(ctr->memory_mode, ctr->history_entries) : 5;
+ st->db.entries = (ctr->storage_engine_id != STORAGE_ENGINE_DBENGINE) ? align_entries_to_pagesize(ctr->storage_engine_id, ctr->history_entries) : 5;
st->update_every = ctr->update_every;
- st->rrd_memory_mode = ctr->memory_mode;
+ st->storage_engine_id = ctr->storage_engine_id;
st->chart_type = ctr->chart_type;
st->rrdhost = host;
@@ -145,20 +426,18 @@ static void rrdset_insert_callback(const DICTIONARY_ITEM *item __maybe_unused, v
rw_spinlock_init(&st->alerts.spinlock);
- if(st->rrd_memory_mode == RRD_MEMORY_MODE_SAVE || st->rrd_memory_mode == RRD_MEMORY_MODE_MAP) {
- if(!rrdset_memory_load_or_create_map_save(st, st->rrd_memory_mode)) {
- netdata_log_info("Failed to use db mode %s for chart '%s', falling back to ram mode.", (st->rrd_memory_mode == RRD_MEMORY_MODE_MAP)?"map":"save", rrdset_name(st));
- st->rrd_memory_mode = RRD_MEMORY_MODE_RAM;
+ if(st->storage_engine_id == STORAGE_ENGINE_SAVE || st->storage_engine_id == STORAGE_ENGINE_MAP) {
+ if(!rrdset_memory_load_or_create_map_save(st)) {
+ netdata_log_info("Failed to use db mode %s for chart '%s', falling back to ram mode.", (st->storage_engine_id == STORAGE_ENGINE_MAP)?"map":"save", rrdset_name(st));
+ st->storage_engine_id = STORAGE_ENGINE_RAM;
}
}
// initialize the db tiers
{
- for(size_t tier = 0; tier < storage_tiers ; tier++) {
- STORAGE_ENGINE *eng = st->rrdhost->db[tier].eng;
- if(!eng) continue;
-
- st->storage_metrics_groups[tier] = storage_engine_metrics_group_get(eng->backend, host->db[tier].instance, &st->chart_uuid);
+ for (size_t tier = 0; tier < rrdb.storage_tiers ; tier++) {
+ STORAGE_ENGINE_ID storage_engine_id = st->rrdhost->db[tier].id;
+ st->storage_metrics_groups[tier] = storage_engine_metrics_group_get(storage_engine_id, host->db[tier].instance, &st->chart_uuid);
}
}
@@ -198,12 +477,11 @@ void rrdset_finalize_collection(RRDSET *st, bool dimensions_too) {
rrddim_foreach_done(rd);
}
- for(size_t tier = 0; tier < storage_tiers ; tier++) {
- STORAGE_ENGINE *eng = st->rrdhost->db[tier].eng;
- if(!eng) continue;
+ for(size_t tier = 0; tier < rrdb.storage_tiers ; tier++) {
+ STORAGE_ENGINE_ID storage_engine_id = st->rrdhost->db[tier].id;
if(st->storage_metrics_groups[tier]) {
- storage_engine_metrics_group_release(eng->backend, host->db[tier].instance, st->storage_metrics_groups[tier]);
+ storage_engine_metrics_group_release(storage_engine_id, host->db[tier].instance, st->storage_metrics_groups[tier]);
st->storage_metrics_groups[tier] = NULL;
}
}
@@ -449,7 +727,7 @@ static RRDSET *rrdset_index_find(RRDHOST *host, const char *id) {
// ----------------------------------------------------------------------------
// RRDSET - find charts
-inline RRDSET *rrdset_find(RRDHOST *host, const char *id) {
+inline RRDSET *rrdset_find_by_id(RRDHOST *host, const char *id) {
netdata_log_debug(D_RRD_CALLS, "rrdset_find() for chart '%s' in host '%s'", id, rrdhost_hostname(host));
RRDSET *st = rrdset_index_find(host, id);
@@ -459,7 +737,7 @@ inline RRDSET *rrdset_find(RRDHOST *host, const char *id) {
return(st);
}
-inline RRDSET *rrdset_find_bytype(RRDHOST *host, const char *type, const char *id) {
+inline RRDSET *rrdset_find_by_type(RRDHOST *host, const char *type, const char *id) {
netdata_log_debug(D_RRD_CALLS, "rrdset_find_bytype() for chart '%s.%s' in host '%s'", type, id, rrdhost_hostname(host));
char buf[RRD_ID_LENGTH_MAX + 1];
@@ -468,10 +746,10 @@ inline RRDSET *rrdset_find_bytype(RRDHOST *host, const char *type, const char *i
int len = (int) strlen(buf);
strncpyz(&buf[len], id, (size_t) (RRD_ID_LENGTH_MAX - len));
- return(rrdset_find(host, buf));
+ return(rrdset_find_by_id(host, buf));
}
-inline RRDSET *rrdset_find_byname(RRDHOST *host, const char *name) {
+inline RRDSET *rrdset_find_by_name(RRDHOST *host, const char *name) {
netdata_log_debug(D_RRD_CALLS, "rrdset_find_byname() for chart '%s' in host '%s'", name, rrdhost_hostname(host));
RRDSET *st = rrdset_index_find_name(host, name);
return(st);
@@ -597,7 +875,7 @@ time_t rrdset_first_entry_s(RRDSET *st) {
}
time_t rrdset_first_entry_s_of_tier(RRDSET *st, size_t tier) {
- if(unlikely(tier > storage_tiers))
+ if(unlikely(tier > rrdb.storage_tiers))
return 0;
RRDDIM *rd;
@@ -741,10 +1019,7 @@ inline void rrdset_update_heterogeneous_flag(RRDSET *st) {
}
}
-// ----------------------------------------------------------------------------
-// RRDSET - reset a chart
-
-void rrdset_reset(RRDSET *st) {
+static void rrdset_reset(RRDSET *st) {
netdata_log_debug(D_RRD_CALLS, "rrdset_reset() %s", rrdset_name(st));
st->last_collected_time.tv_sec = 0;
@@ -762,58 +1037,16 @@ void rrdset_reset(RRDSET *st) {
rd->collector.counter = 0;
if(!rrddim_flag_check(rd, RRDDIM_FLAG_ARCHIVED)) {
- for(size_t tier = 0; tier < storage_tiers ;tier++)
- storage_engine_store_flush(rd->tiers[tier].db_collection_handle);
+ for(size_t tier = 0; tier < rrdb.storage_tiers ;tier++) {
+ if (rd->tiers[tier].db_collection_handle)
+ storage_engine_store_flush(st->storage_engine_id, rd->tiers[tier].db_collection_handle);
+ }
}
}
rrddim_foreach_done(rd);
}
// ----------------------------------------------------------------------------
-// RRDSET - helpers for rrdset_create()
-
-inline long align_entries_to_pagesize(RRD_MEMORY_MODE mode, long entries) {
- if(mode == RRD_MEMORY_MODE_DBENGINE) return 0;
- if(mode == RRD_MEMORY_MODE_NONE) return 5;
-
- if(entries < 5) entries = 5;
- if(entries > RRD_HISTORY_ENTRIES_MAX) entries = RRD_HISTORY_ENTRIES_MAX;
-
- if(mode == RRD_MEMORY_MODE_MAP || mode == RRD_MEMORY_MODE_SAVE || mode == RRD_MEMORY_MODE_RAM) {
- long header_size = 0;
-
- if(mode == RRD_MEMORY_MODE_MAP || mode == RRD_MEMORY_MODE_SAVE)
- header_size = (long)rrddim_memory_file_header_size();
-
- long page = (long)sysconf(_SC_PAGESIZE);
- long size = (long)(header_size + entries * sizeof(storage_number));
- if (unlikely(size % page)) {
- size -= (size % page);
- size += page;
-
- long n = (long)((size - header_size) / sizeof(storage_number));
- return n;
- }
- }
-
- return entries;
-}
-
-static inline void last_collected_time_align(RRDSET *st) {
- st->last_collected_time.tv_sec -= st->last_collected_time.tv_sec % st->update_every;
-
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_STORE_FIRST)))
- st->last_collected_time.tv_usec = 0;
- else
- st->last_collected_time.tv_usec = 500000;
-}
-
-static inline void last_updated_time_align(RRDSET *st) {
- st->last_updated.tv_sec -= st->last_updated.tv_sec % st->update_every;
- st->last_updated.tv_usec = 0;
-}
-
-// ----------------------------------------------------------------------------
// RRDSET - free a chart
void rrdset_free(RRDSET *st) {
@@ -835,7 +1068,7 @@ void rrdset_delete_files(RRDSET *st) {
netdata_log_info("Deleting chart '%s' ('%s') from disk...", rrdset_id(st), rrdset_name(st));
- if(st->rrd_memory_mode == RRD_MEMORY_MODE_SAVE || st->rrd_memory_mode == RRD_MEMORY_MODE_MAP) {
+ if(st->storage_engine_id == STORAGE_ENGINE_SAVE || st->storage_engine_id == STORAGE_ENGINE_MAP) {
const char *cache_filename = rrdset_cache_filename(st);
if(cache_filename) {
netdata_log_info("Deleting chart header file '%s'.", cache_filename);
@@ -860,23 +1093,6 @@ void rrdset_delete_files(RRDSET *st) {
recursively_delete_dir(st->db.cache_dir, "left-over chart");
}
-void rrdset_delete_obsolete_dimensions(RRDSET *st) {
- RRDDIM *rd;
-
- netdata_log_info("Deleting dimensions of chart '%s' ('%s') from disk...", rrdset_id(st), rrdset_name(st));
-
- rrddim_foreach_read(rd, st) {
- if(rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE)) {
- const char *cache_filename = rrddim_cache_filename(rd);
- if(!cache_filename) continue;
- netdata_log_info("Deleting dimension file '%s'.", cache_filename);
- if(unlikely(unlink(cache_filename) == -1))
- netdata_log_error("Cannot delete dimension file '%s'", cache_filename);
- }
- }
- rrddim_foreach_done(rd);
-}
-
// ----------------------------------------------------------------------------
// RRDSET - create a chart
@@ -894,10 +1110,10 @@ RRDSET *rrdset_create_custom(
, long priority
, int update_every
, RRDSET_TYPE chart_type
- , RRD_MEMORY_MODE memory_mode
+ , STORAGE_ENGINE_ID storage_engine_id
, long history_entries
) {
- if (host != localhost)
+ if (host != rrdb.localhost)
host->child_last_chart_command = now_realtime_sec();
if(!type || !type[0])
@@ -949,7 +1165,7 @@ RRDSET *rrdset_create_custom(
.priority = priority,
.update_every = update_every,
.chart_type = chart_type,
- .memory_mode = memory_mode,
+ .storage_engine_id = storage_engine_id,
.history_entries = history_entries,
};
@@ -1127,14 +1343,15 @@ static inline void rrdset_init_last_updated_time(RRDSET *st) {
static __thread size_t rrdset_done_statistics_points_stored_per_tier[RRD_STORAGE_TIERS];
-static inline time_t tier_next_point_time_s(RRDDIM *rd, struct rrddim_tier *t, time_t now_s) {
- time_t loop = (time_t)rd->rrdset->update_every * (time_t)t->tier_grouping;
+static inline time_t tier_next_point_time_s(RRDDIM *rd, size_t tier, time_t now_s) {
+ uint32_t tier_grouping = rd->rrdset->rrdhost->db[tier].tier_grouping;
+ time_t loop = (time_t)rd->rrdset->update_every * (time_t) tier_grouping;
return now_s + loop - ((now_s + loop) % loop);
}
void store_metric_at_tier(RRDDIM *rd, size_t tier, struct rrddim_tier *t, STORAGE_POINT sp, usec_t now_ut __maybe_unused) {
if (unlikely(!t->next_point_end_time_s))
- t->next_point_end_time_s = tier_next_point_time_s(rd, t, sp.end_time_s);
+ t->next_point_end_time_s = tier_next_point_time_s(rd, tier, sp.end_time_s);
if(unlikely(sp.start_time_s >= t->next_point_end_time_s)) {
// flush the virtual point, it is done
@@ -1142,6 +1359,7 @@ void store_metric_at_tier(RRDDIM *rd, size_t tier, struct rrddim_tier *t, STORAG
if (likely(!storage_point_is_unset(t->virtual_point))) {
storage_engine_store_metric(
+ rd->rrdset->storage_engine_id,
t->db_collection_handle,
t->next_point_end_time_s * USEC_PER_SEC,
t->virtual_point.sum,
@@ -1153,6 +1371,7 @@ void store_metric_at_tier(RRDDIM *rd, size_t tier, struct rrddim_tier *t, STORAG
}
else {
storage_engine_store_metric(
+ rd->rrdset->storage_engine_id,
t->db_collection_handle,
t->next_point_end_time_s * USEC_PER_SEC,
NAN,
@@ -1164,7 +1383,7 @@ void store_metric_at_tier(RRDDIM *rd, size_t tier, struct rrddim_tier *t, STORAG
rrdset_done_statistics_points_stored_per_tier[tier]++;
t->virtual_point.count = 0; // make the point unset
- t->next_point_end_time_s = tier_next_point_time_s(rd, t, sp.end_time_s);
+ t->next_point_end_time_s = tier_next_point_time_s(rd, tier, sp.end_time_s);
}
// merge the dates into our virtual point
@@ -1224,9 +1443,8 @@ void rrddim_store_metric(RRDDIM *rd, usec_t point_end_time_ut, NETDATA_DOUBLE n,
#endif // NETDATA_LOG_COLLECTION_ERRORS
// store the metric on tier 0
- storage_engine_store_metric(rd->tiers[0].db_collection_handle, point_end_time_ut,
- n, 0, 0,
- 1, 0, flags);
+ storage_engine_store_metric(rd->rrdset->storage_engine_id, rd->tiers[0].db_collection_handle, point_end_time_ut,
+ n, 0, 0, 1, 0, flags);
rrdset_done_statistics_points_stored_per_tier[0]++;
@@ -1243,7 +1461,7 @@ void rrddim_store_metric(RRDDIM *rd, usec_t point_end_time_ut, NETDATA_DOUBLE n,
.flags = flags
};
- for(size_t tier = 1; tier < storage_tiers ;tier++) {
+ for(size_t tier = 1; tier < rrdb.storage_tiers ;tier++) {
if(unlikely(!rd->tiers[tier].db_metric_handle)) continue;
struct rrddim_tier *t = &rd->tiers[tier];
@@ -1381,11 +1599,8 @@ static inline size_t rrdset_done_interpolate(
new_value /= (NETDATA_DOUBLE)st->update_every;
if(unlikely(next_store_ut - last_stored_ut < update_every_ut)) {
-
rrdset_debug(st, "%s: COLLECTION POINT IS SHORT " NETDATA_DOUBLE_FORMAT " - EXTRAPOLATING",
- rrddim_name(rd)
- , (NETDATA_DOUBLE)(next_store_ut - last_stored_ut)
- );
+ rrddim_name(rd) , (NETDATA_DOUBLE)(next_store_ut - last_stored_ut));
new_value = new_value * (NETDATA_DOUBLE)(st->update_every * USEC_PER_SEC) / (NETDATA_DOUBLE)(next_store_ut - last_stored_ut);
}
@@ -1439,7 +1654,7 @@ static inline size_t rrdset_done_interpolate(
continue;
}
- if(likely(rrddim_check_updated(rd) && rd->collector.counter > 1 && iterations < gap_when_lost_iterations_above)) {
+ if(likely(rrddim_check_updated(rd) && rd->collector.counter > 1 && iterations < rrdb.gap_when_lost_iterations_above)) {
uint32_t dim_storage_flags = storage_flags;
if (ml_dimension_is_anomalous(rd, current_time_s, new_value, true)) {
@@ -1583,7 +1798,7 @@ void rrdset_timed_done(RRDSET *st, struct timeval now, bool pending_rrdset_next)
// check if we will re-write the entire data set
if(unlikely(dt_usec(&st->last_collected_time, &st->last_updated) > st->db.entries * update_every_ut &&
- st->rrd_memory_mode != RRD_MEMORY_MODE_DBENGINE)) {
+ st->storage_engine_id != STORAGE_ENGINE_DBENGINE)) {
netdata_log_info(
"'%s': too old data (last updated at %"PRId64".%"PRId64", last collected at %"PRId64".%"PRId64"). "
"Resetting it. Will not store the next entry.",
@@ -1643,8 +1858,8 @@ void rrdset_timed_done(RRDSET *st, struct timeval now, bool pending_rrdset_next)
size_t dim_id;
size_t dimensions = 0;
struct rda_item *rda = rda_base;
- total_number collected_total = 0;
- total_number last_collected_total = 0;
+ collected_number collected_total = 0;
+ collected_number last_collected_total = 0;
rrddim_foreach_read(rd, st) {
if(rd_dfe.counter >= rda_slots)
break;
@@ -1882,14 +2097,6 @@ void rrdset_timed_done(RRDSET *st, struct timeval now, bool pending_rrdset_next)
// at this point we have all the calculated values ready
// it is now time to interpolate values on a second boundary
-// #ifdef NETDATA_INTERNAL_CHECKS
-// if(unlikely(now_collect_ut < next_store_ut && st->counter_done > 1)) {
-// // this is collected in the same interpolation point
-// rrdset_debug(st, "THIS IS IN THE SAME INTERPOLATION POINT");
-// netdata_log_info("INTERNAL CHECK: host '%s', chart '%s' collection %zu is in the same interpolation point: short by %llu microseconds", st->rrdhost->hostname, rrdset_name(st), st->counter_done, next_store_ut - now_collect_ut);
-// }
-// #endif
-
rrdset_done_interpolate(
&stream_buffer
, st
@@ -1967,7 +2174,7 @@ void rrdset_timed_done(RRDSET *st, struct timeval now, bool pending_rrdset_next)
// ALL DONE ABOUT THE DATA UPDATE
// --------------------------------------------------------------------
- if(unlikely(st->rrd_memory_mode == RRD_MEMORY_MODE_MAP)) {
+ if(unlikely(st->storage_engine_id == STORAGE_ENGINE_MAP)) {
// update the memory mapped files with the latest values
rrdset_memory_file_update(st);
@@ -2006,9 +2213,10 @@ time_t rrdset_set_update_every_s(RRDSET *st, time_t update_every_s) {
// switch update every to the storage engine
RRDDIM *rd;
rrddim_foreach_read(rd, st) {
- for (size_t tier = 0; tier < storage_tiers; tier++) {
+ for (size_t tier = 0; tier < rrdb.storage_tiers; tier++) {
if (rd->tiers[tier].db_collection_handle)
storage_engine_store_change_collection_frequency(
+ st->storage_engine_id,
rd->tiers[tier].db_collection_handle,
(int)(st->rrdhost->db[tier].tier_grouping * st->update_every));
}
@@ -2018,210 +2226,13 @@ time_t rrdset_set_update_every_s(RRDSET *st, time_t update_every_s) {
return prev_update_every_s;
}
-// ----------------------------------------------------------------------------
-// compatibility layer for RRDSET files v019
+void rrdset_update_rrdlabels(RRDSET *st, DICTIONARY *new_rrdlabels) {
+ if(!st->rrdlabels)
+ st->rrdlabels = rrdlabels_create();
-#define RRDSET_MAGIC_V019 "NETDATA RRD SET FILE V019"
-#define RRD_ID_LENGTH_MAX_V019 200
+ if (new_rrdlabels)
+ rrdlabels_migrate_to_these(st->rrdlabels, new_rrdlabels);
-struct avl_element_v019 {
- void *avl_link[2];
- signed char avl_balance;
-};
-struct avl_tree_type_v019 {
- void *root;
- int (*compar)(void *a, void *b);
-};
-struct avl_tree_lock_v019 {
- struct avl_tree_type_v019 avl_tree;
- pthread_rwlock_t rwlock;
-};
-struct rrdset_map_save_v019 {
- struct avl_element_v019 avl; // ignored
- struct avl_element_v019 avlname; // ignored
- char id[RRD_ID_LENGTH_MAX_V019 + 1]; // check to reset all - update on load
- void *name; // ignored
- void *unused_ptr; // ignored
- void *type; // ignored
- void *family; // ignored
- void *title; // ignored
- void *units; // ignored
- void *context; // ignored
- uint32_t hash_context; // ignored
- uint32_t chart_type; // ignored
- int update_every; // check to reset all - update on load
- long entries; // check to reset all - update on load
- long current_entry; // NEEDS TO BE UPDATED - FIXED ON LOAD
- uint32_t flags; // ignored
- void *exporting_flags; // ignored
- int gap_when_lost_iterations_above; // ignored
- long priority; // ignored
- uint32_t rrd_memory_mode; // ignored
- void *cache_dir; // ignored
- char cache_filename[FILENAME_MAX+1]; // ignored - update on load
- pthread_rwlock_t rrdset_rwlock; // ignored
- size_t counter; // NEEDS TO BE UPDATED - maintained on load
- size_t counter_done; // ignored
- union { //
- time_t last_accessed_time_s; // ignored
- time_t last_entry_s; // ignored
- }; //
- time_t upstream_resync_time; // ignored
- void *plugin_name; // ignored
- void *module_name; // ignored
- void *chart_uuid; // ignored
- void *state; // ignored
- size_t unused[3]; // ignored
- size_t rrddim_page_alignment; // ignored
- uint32_t hash; // ignored
- uint32_t hash_name; // ignored
- usec_t usec_since_last_update; // NEEDS TO BE UPDATED - maintained on load
- struct timeval last_updated; // NEEDS TO BE UPDATED - check to reset all - fixed on load
- struct timeval last_collected_time; // ignored
- long long collected_total; // ignored
- long long last_collected_total; // ignored
- void *rrdfamily; // ignored
- void *rrdhost; // ignored
- void *next; // ignored
- long double green; // ignored
- long double red; // ignored
- struct avl_tree_lock_v019 rrdvar_root_index; // ignored
- void *variables; // ignored
- void *alarms; // ignored
- unsigned long memsize; // check to reset all - update on load
- char magic[sizeof(RRDSET_MAGIC_V019) + 1]; // check to reset all - update on load
- struct avl_tree_lock_v019 dimensions_index; // ignored
- void *dimensions; // ignored
-};
-
-void rrdset_memory_file_update(RRDSET *st) {
- if(!st->db.st_on_file) return;
- struct rrdset_map_save_v019 *st_on_file = st->db.st_on_file;
-
- st_on_file->current_entry = st->db.current_entry;
- st_on_file->counter = st->counter;
- st_on_file->usec_since_last_update = st->usec_since_last_update;
- st_on_file->last_updated.tv_sec = st->last_updated.tv_sec;
- st_on_file->last_updated.tv_usec = st->last_updated.tv_usec;
-}
-
-const char *rrdset_cache_filename(RRDSET *st) {
- if(!st->db.st_on_file) return NULL;
- struct rrdset_map_save_v019 *st_on_file = st->db.st_on_file;
- return st_on_file->cache_filename;
-}
-
-const char *rrdset_cache_dir(RRDSET *st) {
- if(!st->db.cache_dir)
- st->db.cache_dir = rrdhost_cache_dir_for_rrdset_alloc(st->rrdhost, rrdset_id(st));
-
- return st->db.cache_dir;
-}
-
-void rrdset_memory_file_free(RRDSET *st) {
- if(!st->db.st_on_file) return;
-
- // needed for memory mode map, to save the latest state
- rrdset_memory_file_update(st);
-
- struct rrdset_map_save_v019 *st_on_file = st->db.st_on_file;
- __atomic_sub_fetch(&rrddim_db_memory_size, st_on_file->memsize, __ATOMIC_RELAXED);
- netdata_munmap(st_on_file, st_on_file->memsize);
-
- // remove the pointers from the RRDDIM
- st->db.st_on_file = NULL;
-}
-
-void rrdset_memory_file_save(RRDSET *st) {
- if(!st->db.st_on_file) return;
-
- rrdset_memory_file_update(st);
-
- struct rrdset_map_save_v019 *st_on_file = st->db.st_on_file;
- if(st_on_file->rrd_memory_mode != RRD_MEMORY_MODE_SAVE) return;
-
- memory_file_save(st_on_file->cache_filename, st->db.st_on_file, st_on_file->memsize);
-}
-
-bool rrdset_memory_load_or_create_map_save(RRDSET *st, RRD_MEMORY_MODE memory_mode) {
- if(memory_mode != RRD_MEMORY_MODE_SAVE && memory_mode != RRD_MEMORY_MODE_MAP)
- return false;
-
- char fullfilename[FILENAME_MAX + 1];
- snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", rrdset_cache_dir(st));
-
- unsigned long size = sizeof(struct rrdset_map_save_v019);
- struct rrdset_map_save_v019 *st_on_file = (struct rrdset_map_save_v019 *)netdata_mmap(
- fullfilename, size, ((memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE), 0, false, NULL);
-
- if(!st_on_file) return false;
-
- time_t now_s = now_realtime_sec();
-
- st_on_file->magic[sizeof(RRDSET_MAGIC_V019)] = '\0';
- if(strcmp(st_on_file->magic, RRDSET_MAGIC_V019) != 0) {
- netdata_log_info("Initializing file '%s'.", fullfilename);
- memset(st_on_file, 0, size);
- }
- else if(strncmp(st_on_file->id, rrdset_id(st), RRD_ID_LENGTH_MAX_V019) != 0) {
- netdata_log_error("File '%s' contents are not for chart '%s'. Clearing it.", fullfilename, rrdset_id(st));
- memset(st_on_file, 0, size);
- }
- else if(st_on_file->memsize != size || st_on_file->entries != st->db.entries) {
- netdata_log_error("F