summaryrefslogtreecommitdiffstats
path: root/database/rrddim.c
diff options
context:
space:
mode:
Diffstat (limited to 'database/rrddim.c')
-rw-r--r--database/rrddim.c443
1 files changed, 210 insertions, 233 deletions
diff --git a/database/rrddim.c b/database/rrddim.c
index 0f99f98df7..57c18d07e8 100644
--- a/database/rrddim.c
+++ b/database/rrddim.c
@@ -1,8 +1,181 @@
// SPDX-License-Identifier: GPL-3.0-or-later
-#define NETDATA_RRD_INTERNALS
#include "rrd.h"
-#include "storage_engine.h"
+
+// ----------------------------------------------------------------------------
+// compatibility layer for RRDDIM files v019
+
+#define RRDDIMENSION_MAGIC_V019 "NETDATA RRD DIMENSION FILE V019"
+
+struct avl_element_v019 {
+ void *avl_link[2];
+ signed char avl_balance;
+};
+
+struct rrddim_map_save_v019 {
+ struct avl_element_v019 avl; // ignored
+ void *id; // ignored
+ void *name; // ignored
+ uint32_t algorithm; // print warning on mismatch - update on load
+ uint32_t storage_engine_id; // ignored
+ long long multiplier; // print warning on mismatch - update on load
+ long long divisor; // print warning on mismatch - update on load
+ uint32_t flags; // ignored
+ uint32_t hash; // ignored
+ uint32_t hash_name; // ignored
+ void *cache_filename; // ignored - we use it to keep the filename to save back
+ size_t collections_counter; // ignored
+ void *state; // ignored
+ size_t unused[8]; // ignored
+ long long collected_value_max; // ignored
+ unsigned int updated:1; // ignored
+ unsigned int exposed:1; // ignored
+ struct timeval last_collected_time; // check to reset all - ignored after load
+ long double calculated_value; // ignored
+ long double last_calculated_value; // ignored
+ long double last_stored_value; // ignored
+ long long collected_value; // ignored
+ long long last_collected_value; // load and save
+ long double collected_volume; // ignored
+ long double stored_volume; // ignored
+ void *next; // ignored
+ void *rrdset; // ignored
+ long entries; // check to reset all - update on load
+ int update_every; // check to reset all - update on load
+ size_t memsize; // check to reset all - update on load
+ char magic[sizeof(RRDDIMENSION_MAGIC_V019) + 1];// check to reset all - update on load
+ void *variables; // ignored
+ storage_number values[]; // the array of values
+};
+
+size_t rrddim_memory_file_header_size(void) {
+ return sizeof(struct rrddim_map_save_v019);
+}
+
+void rrddim_memory_file_update(RRDDIM *rd) {
+ if(!rd || !rd->db.rd_on_file) return;
+ struct rrddim_map_save_v019 *rd_on_file = rd->db.rd_on_file;
+
+ rd_on_file->last_collected_time.tv_sec = rd->collector.last_collected_time.tv_sec;
+ rd_on_file->last_collected_time.tv_usec = rd->collector.last_collected_time.tv_usec;
+ rd_on_file->last_collected_value = rd->collector.last_collected_value;
+}
+
+void rrddim_memory_file_free(RRDDIM *rd) {
+ if(!rd || !rd->db.rd_on_file) return;
+
+ // needed for storage engine MAP, to save the latest state
+ rrddim_memory_file_update(rd);
+
+ struct rrddim_map_save_v019 *rd_on_file = rd->db.rd_on_file;
+ __atomic_sub_fetch(&rrddim_db_memory_size, rd_on_file->memsize + strlen(rd_on_file->cache_filename), __ATOMIC_RELAXED);
+ freez(rd_on_file->cache_filename);
+ netdata_munmap(rd_on_file, rd_on_file->memsize);
+
+ // remove the pointers from the RRDDIM
+ rd->db.rd_on_file = NULL;
+ rd->db.data = NULL;
+}
+
+const char *rrddim_cache_filename(RRDDIM *rd) {
+ if(!rd || !rd->db.rd_on_file) return NULL;
+ struct rrddim_map_save_v019 *rd_on_file = rd->db.rd_on_file;
+ return rd_on_file->cache_filename;
+}
+
+void rrddim_memory_file_save(RRDDIM *rd) {
+ if(!rd || !rd->db.rd_on_file) return;
+
+ rrddim_memory_file_update(rd);
+
+ struct rrddim_map_save_v019 *rd_on_file = rd->db.rd_on_file;
+ if(rd_on_file->storage_engine_id != STORAGE_ENGINE_SAVE) return;
+
+ memory_file_save(rd_on_file->cache_filename, rd_on_file, rd_on_file->memsize);
+}
+
+static bool rrddim_memory_load_or_create_map_save(RRDSET *st, RRDDIM *rd) {
+ assert(st->storage_engine_id == STORAGE_ENGINE_SAVE || st->storage_engine_id == STORAGE_ENGINE_MAP);
+
+ struct rrddim_map_save_v019 *rd_on_file = NULL;
+
+ unsigned long size = sizeof(struct rrddim_map_save_v019) + (st->db.entries * sizeof(storage_number));
+
+ char filename[FILENAME_MAX + 1];
+ char fullfilename[FILENAME_MAX + 1];
+ rrdset_strncpyz_name(filename, rrddim_id(rd), FILENAME_MAX);
+ snprintfz(fullfilename, FILENAME_MAX, "%s/%s.db", rrdset_cache_dir(st), filename);
+
+ rd_on_file = (struct rrddim_map_save_v019 *)netdata_mmap(
+ fullfilename, size, ((st->storage_engine_id == STORAGE_ENGINE_MAP) ? MAP_SHARED : MAP_PRIVATE), 1, false, NULL);
+
+ if(unlikely(!rd_on_file)) return false;
+
+ struct timeval now;
+ now_realtime_timeval(&now);
+
+ int reset = 0;
+ rd_on_file->magic[sizeof(RRDDIMENSION_MAGIC_V019)] = '\0';
+ if(strcmp(rd_on_file->magic, RRDDIMENSION_MAGIC_V019) != 0) {
+ netdata_log_info("Initializing file %s.", fullfilename);
+ memset(rd_on_file, 0, size);
+ reset = 1;
+ }
+ else if(rd_on_file->memsize != size) {
+ netdata_log_error("File %s does not have the desired size, expected %lu but found %lu. Clearing it.", fullfilename, size, (unsigned long int) rd_on_file->memsize);
+ memset(rd_on_file, 0, size);
+ reset = 1;
+ }
+ else if(rd_on_file->update_every != st->update_every) {
+ netdata_log_error("File %s does not have the same update frequency, expected %d but found %d. Clearing it.", fullfilename, st->update_every, rd_on_file->update_every);
+ memset(rd_on_file, 0, size);
+ reset = 1;
+ }
+ else if(dt_usec(&now, &rd_on_file->last_collected_time) > (rd_on_file->entries * rd_on_file->update_every * USEC_PER_SEC)) {
+ netdata_log_info("File %s is too old (last collected %llu seconds ago, but the database is %ld seconds). Clearing it.", fullfilename, dt_usec(&now, &rd_on_file->last_collected_time) / USEC_PER_SEC, rd_on_file->entries * rd_on_file->update_every);
+ memset(rd_on_file, 0, size);
+ reset = 1;
+ }
+
+ if(!reset) {
+ rd->collector.last_collected_value = rd_on_file->last_collected_value;
+
+ if(rd_on_file->algorithm != rd->algorithm)
+ netdata_log_info("File %s does not have the expected algorithm (expected %u '%s', found %u '%s'). Previous values may be wrong.",
+ fullfilename, rd->algorithm, rrd_algorithm_name(rd->algorithm), rd_on_file->algorithm, rrd_algorithm_name(rd_on_file->algorithm));
+
+ if(rd_on_file->multiplier != rd->multiplier)
+ netdata_log_info("File %s does not have the expected multiplier (expected %d, found %ld). "
+ "Previous values may be wrong.", fullfilename, rd->multiplier, (long)rd_on_file->multiplier);
+
+ if(rd_on_file->divisor != rd->divisor)
+ netdata_log_info("File %s does not have the expected divisor (expected %d, found %ld). "
+ "Previous values may be wrong.", fullfilename, rd->divisor, (long)rd_on_file->divisor);
+ }
+
+ // zero the entire header
+ memset(rd_on_file, 0, sizeof(struct rrddim_map_save_v019));
+
+ // set the important fields
+ strcpy(rd_on_file->magic, RRDDIMENSION_MAGIC_V019);
+ rd_on_file->algorithm = rd->algorithm;
+ rd_on_file->multiplier = rd->multiplier;
+ rd_on_file->divisor = rd->divisor;
+ rd_on_file->entries = st->db.entries;
+ rd_on_file->update_every = rd->rrdset->update_every;
+ rd_on_file->memsize = size;
+ rd_on_file->storage_engine_id = st->storage_engine_id;
+ rd_on_file->cache_filename = strdupz(fullfilename);
+
+ __atomic_add_fetch(&rrddim_db_memory_size, rd_on_file->memsize + strlen(rd_on_file->cache_filename), __ATOMIC_RELAXED);
+
+ rd->db.data = &rd_on_file->values[0];
+ rd->db.rd_on_file = rd_on_file;
+ rd->db.memsize = size;
+ rrddim_memory_file_update(rd);
+
+ return true;
+}
// ----------------------------------------------------------------------------
// RRDDIM index
@@ -14,7 +187,6 @@ struct rrddim_constructor {
collected_number multiplier;
collected_number divisor;
RRD_ALGORITHM algorithm;
- RRD_MEMORY_MODE memory_mode;
enum {
RRDDIM_REACT_NONE = 0,
@@ -26,7 +198,7 @@ struct rrddim_constructor {
// isolated call to appear
// separate in statistics
-static void *rrddim_alloc_db(size_t entries) {
+static storage_number *rrddim_alloc_db(size_t entries) {
return callocz(entries, sizeof(storage_number));
}
@@ -51,21 +223,22 @@ static void rrddim_insert_callback(const DICTIONARY_ITEM *item __maybe_unused, v
if(rrdset_flag_check(st, RRDSET_FLAG_STORE_FIRST))
rd->collector.counter = 1;
- if(ctr->memory_mode == RRD_MEMORY_MODE_MAP || ctr->memory_mode == RRD_MEMORY_MODE_SAVE) {
- if(!rrddim_memory_load_or_create_map_save(st, rd, ctr->memory_mode)) {
- netdata_log_info("Failed to use memory mode %s for chart '%s', dimension '%s', falling back to ram", (ctr->memory_mode == RRD_MEMORY_MODE_MAP)?"map":"save", rrdset_name(st), rrddim_name(rd));
- ctr->memory_mode = RRD_MEMORY_MODE_RAM;
+ if (st->storage_engine_id == STORAGE_ENGINE_MAP || st->storage_engine_id == STORAGE_ENGINE_SAVE) {
+ if(!rrddim_memory_load_or_create_map_save(st, rd)) {
+ netdata_log_info("Failed to use memory mode %s for chart '%s', dimension '%s', falling back to ram",
+ storage_engine_name(st->storage_engine_id), rrdset_name(st), rrddim_name(rd));
+ st->storage_engine_id = STORAGE_ENGINE_RAM;
}
}
- if(ctr->memory_mode == RRD_MEMORY_MODE_RAM) {
+ if (st->storage_engine_id == STORAGE_ENGINE_RAM) {
size_t entries = st->db.entries;
if(!entries) entries = 5;
rd->db.data = netdata_mmap(NULL, entries * sizeof(storage_number), MAP_PRIVATE, 1, false, NULL);
if(!rd->db.data) {
netdata_log_info("Failed to use memory mode ram for chart '%s', dimension '%s', falling back to alloc", rrdset_name(st), rrddim_name(rd));
- ctr->memory_mode = RRD_MEMORY_MODE_ALLOC;
+ st->storage_engine_id = STORAGE_ENGINE_ALLOC;
}
else {
rd->db.memsize = entries * sizeof(storage_number);
@@ -73,7 +246,7 @@ static void rrddim_insert_callback(const DICTIONARY_ITEM *item __maybe_unused, v
}
}
- if(ctr->memory_mode == RRD_MEMORY_MODE_ALLOC || ctr->memory_mode == RRD_MEMORY_MODE_NONE) {
+ if (st->storage_engine_id == STORAGE_ENGINE_ALLOC || st->storage_engine_id == STORAGE_ENGINE_NONE) {
size_t entries = st->db.entries;
if(entries < 5) entries = 5;
@@ -82,19 +255,14 @@ static void rrddim_insert_callback(const DICTIONARY_ITEM *item __maybe_unused, v
__atomic_add_fetch(&rrddim_db_memory_size, rd->db.memsize, __ATOMIC_RELAXED);
}
- rd->rrd_memory_mode = ctr->memory_mode;
-
if (unlikely(rrdcontext_find_dimension_uuid(st, rrddim_id(rd), &(rd->metric_uuid))))
uuid_generate(rd->metric_uuid);
// initialize the db tiers
{
size_t initialized = 0;
- for(size_t tier = 0; tier < storage_tiers ; tier++) {
- STORAGE_ENGINE *eng = host->db[tier].eng;
- rd->tiers[tier].backend = eng->backend;
- rd->tiers[tier].tier_grouping = host->db[tier].tier_grouping;
- rd->tiers[tier].db_metric_handle = eng->api.metric_get_or_create(rd, host->db[tier].instance);
+ for (size_t tier = 0; tier < rrdb.storage_tiers; tier++) {
+ rd->tiers[tier].db_metric_handle = storage_engine_metric_get_or_create(rd, host->db[tier].id, host->db[tier].instance);
storage_point_unset(rd->tiers[tier].virtual_point);
initialized++;
@@ -111,10 +279,10 @@ static void rrddim_insert_callback(const DICTIONARY_ITEM *item __maybe_unused, v
// initialize data collection for all tiers
{
size_t initialized = 0;
- for (size_t tier = 0; tier < storage_tiers; tier++) {
+ for (size_t tier = 0; tier < rrdb.storage_tiers; tier++) {
if (rd->tiers[tier].db_metric_handle) {
rd->tiers[tier].db_collection_handle =
- storage_metric_store_init(rd->tiers[tier].backend, rd->tiers[tier].db_metric_handle, st->rrdhost->db[tier].tier_grouping * st->update_every, rd->rrdset->storage_metrics_groups[tier]);
+ storage_metric_store_init(st->storage_engine_id, rd->tiers[tier].db_metric_handle, st->rrdhost->db[tier].tier_grouping * st->update_every, rd->rrdset->storage_metrics_groups[tier]);
initialized++;
}
}
@@ -169,13 +337,13 @@ static void rrddim_insert_callback(const DICTIONARY_ITEM *item __maybe_unused, v
bool rrddim_finalize_collection_and_check_retention(RRDDIM *rd) {
size_t tiers_available = 0, tiers_said_no_retention = 0;
- 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)
continue;
tiers_available++;
- if(storage_engine_store_finalize(rd->tiers[tier].db_collection_handle))
+ if(storage_engine_store_finalize(rd->rrdset->storage_engine_id, rd->tiers[tier].db_collection_handle))
tiers_said_no_retention++;
rd->tiers[tier].db_collection_handle = NULL;
@@ -199,7 +367,7 @@ static void rrddim_delete_callback(const DICTIONARY_ITEM *item __maybe_unused, v
netdata_log_debug(D_RRD_CALLS, "rrddim_free() %s.%s", rrdset_name(st), rrddim_name(rd));
- if (!rrddim_finalize_collection_and_check_retention(rd) && rd->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) {
+ if (!rrddim_finalize_collection_and_check_retention(rd) && st->storage_engine_id == STORAGE_ENGINE_DBENGINE) {
/* This metric has no data and no references */
metaqueue_delete_dimension_uuid(&rd->metric_uuid);
}
@@ -215,18 +383,17 @@ static void rrddim_delete_callback(const DICTIONARY_ITEM *item __maybe_unused, v
// this will free MEMORY_MODE_SAVE and MEMORY_MODE_MAP structures
rrddim_memory_file_free(rd);
- for(size_t tier = 0; tier < storage_tiers ;tier++) {
+ for (size_t tier = 0; tier < rrdb.storage_tiers ;tier++) {
if(!rd->tiers[tier].db_metric_handle) continue;
- STORAGE_ENGINE* eng = host->db[tier].eng;
- eng->api.metric_release(rd->tiers[tier].db_metric_handle);
+ storage_engine_metric_release(host->db[tier].id, rd->tiers[tier].db_metric_handle);
rd->tiers[tier].db_metric_handle = NULL;
}
if(rd->db.data) {
__atomic_sub_fetch(&rrddim_db_memory_size, rd->db.memsize, __ATOMIC_RELAXED);
- if(rd->rrd_memory_mode == RRD_MEMORY_MODE_RAM)
+ if(st->storage_engine_id == STORAGE_ENGINE_RAM)
netdata_munmap(rd->db.data, rd->db.memsize);
else
freez(rd->db.data);
@@ -250,10 +417,10 @@ static bool rrddim_conflict_callback(const DICTIONARY_ITEM *item __maybe_unused,
rc += rrddim_set_multiplier(st, rd, ctr->multiplier);
rc += rrddim_set_divisor(st, rd, ctr->divisor);
- 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)
rd->tiers[tier].db_collection_handle =
- storage_metric_store_init(rd->tiers[tier].backend, rd->tiers[tier].db_metric_handle, st->rrdhost->db[tier].tier_grouping * st->update_every, rd->rrdset->storage_metrics_groups[tier]);
+ storage_metric_store_init(st->storage_engine_id, rd->tiers[tier].db_metric_handle, st->rrdhost->db[tier].tier_grouping * st->update_every, rd->rrdset->storage_metrics_groups[tier]);
}
if(rrddim_flag_check(rd, RRDDIM_FLAG_ARCHIVED)) {
@@ -290,7 +457,7 @@ static void rrddim_react_callback(const DICTIONARY_ITEM *item __maybe_unused, vo
}
size_t rrddim_size(void) {
- return sizeof(RRDDIM) + storage_tiers * sizeof(struct rrddim_tier);
+ return sizeof(RRDDIM) + rrdb.storage_tiers * sizeof(struct rrddim_tier);
}
void rrddim_index_init(RRDSET *st) {
@@ -317,7 +484,7 @@ static inline RRDDIM *rrddim_index_find(RRDSET *st, const char *id) {
// ----------------------------------------------------------------------------
// RRDDIM - find a dimension
-inline RRDDIM *rrddim_find(RRDSET *st, const char *id) {
+inline RRDDIM *rrddim_find_by_id(RRDSET *st, const char *id) {
netdata_log_debug(D_RRD_CALLS, "rrddim_find() for chart %s, dimension %s", rrdset_name(st), id);
return rrddim_index_find(st, id);
@@ -344,15 +511,6 @@ void rrddim_acquired_release(RRDDIM_ACQUIRED *rda) {
dictionary_acquired_item_release(rd->rrdset->rrddim_root_index, (const DICTIONARY_ITEM *)rda);
}
-// This will not return dimensions that are archived
-RRDDIM *rrddim_find_active(RRDSET *st, const char *id) {
- RRDDIM *rd = rrddim_find(st, id);
-
- if (unlikely(rd && rrddim_flag_check(rd, RRDDIM_FLAG_ARCHIVED)))
- return NULL;
-
- return rd;
-}
// ----------------------------------------------------------------------------
// RRDDIM rename a dimension
@@ -419,17 +577,17 @@ inline int rrddim_set_divisor(RRDSET *st, RRDDIM *rd, int32_t divisor) {
// ----------------------------------------------------------------------------
time_t rrddim_last_entry_s_of_tier(RRDDIM *rd, size_t tier) {
- if(unlikely(tier > storage_tiers || !rd->tiers[tier].db_metric_handle))
+ if (unlikely(tier > rrdb.storage_tiers || !rd->tiers[tier].db_metric_handle))
return 0;
- return storage_engine_latest_time_s(rd->tiers[tier].backend, rd->tiers[tier].db_metric_handle);
+ return storage_engine_latest_time_s(rd->rrdset->storage_engine_id, rd->tiers[tier].db_metric_handle);
}
// get the timestamp of the last entry in the round-robin database
time_t rrddim_last_entry_s(RRDDIM *rd) {
time_t latest_time_s = rrddim_last_entry_s_of_tier(rd, 0);
- 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;
time_t t = rrddim_last_entry_s_of_tier(rd, tier);
@@ -441,16 +599,16 @@ time_t rrddim_last_entry_s(RRDDIM *rd) {
}
time_t rrddim_first_entry_s_of_tier(RRDDIM *rd, size_t tier) {
- if(unlikely(tier > storage_tiers || !rd->tiers[tier].db_metric_handle))
+ if (unlikely(tier > rrdb.storage_tiers || !rd->tiers[tier].db_metric_handle))
return 0;
- return storage_engine_oldest_time_s(rd->tiers[tier].backend, rd->tiers[tier].db_metric_handle);
+ return storage_engine_oldest_time_s(rd->rrdset->storage_engine_id, rd->tiers[tier].db_metric_handle);
}
time_t rrddim_first_entry_s(RRDDIM *rd) {
time_t oldest_time_s = 0;
- for(size_t tier = 0; tier < storage_tiers ;tier++) {
+ for (size_t tier = 0; tier < rrdb.storage_tiers ;tier++) {
time_t t = rrddim_first_entry_s_of_tier(rd, tier);
if(t != 0 && (oldest_time_s == 0 || t < oldest_time_s))
oldest_time_s = t;
@@ -459,14 +617,9 @@ time_t rrddim_first_entry_s(RRDDIM *rd) {
return oldest_time_s;
}
-RRDDIM *rrddim_add_custom(RRDSET *st
- , const char *id
- , const char *name
- , collected_number multiplier
- , collected_number divisor
- , RRD_ALGORITHM algorithm
- , RRD_MEMORY_MODE memory_mode
- ) {
+RRDDIM *rrddim_add(RRDSET *st ,const char *id, const char *name,
+ collected_number multiplier, collected_number divisor, RRD_ALGORITHM algorithm)
+{
struct rrddim_constructor tmp = {
.st = st,
.id = id,
@@ -474,7 +627,6 @@ RRDDIM *rrddim_add_custom(RRDSET *st
.multiplier = multiplier,
.divisor = divisor,
.algorithm = algorithm,
- .memory_mode = memory_mode,
};
RRDDIM *rd = dictionary_set_advanced(st->rrddim_root_index, tmp.id, -1, NULL, rrddim_size(), &tmp);
@@ -497,7 +649,7 @@ int rrddim_hide(RRDSET *st, const char *id) {
RRDHOST *host = st->rrdhost;
- RRDDIM *rd = rrddim_find(st, id);
+ RRDDIM *rd = rrddim_find_by_id(st, id);
if(unlikely(!rd)) {
netdata_log_error("Cannot find dimension with id '%s' on stats '%s' (%s) on host '%s'.", id, rrdset_name(st), rrdset_id(st), rrdhost_hostname(host));
return 1;
@@ -516,7 +668,7 @@ int rrddim_unhide(RRDSET *st, const char *id) {
netdata_log_debug(D_RRD_CALLS, "rrddim_unhide() for chart %s, dimension %s", rrdset_name(st), id);
RRDHOST *host = st->rrdhost;
- RRDDIM *rd = rrddim_find(st, id);
+ RRDDIM *rd = rrddim_find_by_id(st, id);
if(unlikely(!rd)) {
netdata_log_error("Cannot find dimension with id '%s' on stats '%s' (%s) on host '%s'.", id, rrdset_name(st), rrdset_id(st), rrdhost_hostname(host));
return 1;
@@ -580,7 +732,7 @@ collected_number rrddim_timed_set_by_pointer(RRDSET *st __maybe_unused, RRDDIM *
collected_number rrddim_set(RRDSET *st, const char *id, collected_number value) {
RRDHOST *host = st->rrdhost;
- RRDDIM *rd = rrddim_find(st, id);
+ RRDDIM *rd = rrddim_find_by_id(st, id);
if(unlikely(!rd)) {
netdata_log_error("Cannot find dimension with id '%s' on stats '%s' (%s) on host '%s'.", id, rrdset_name(st), rrdset_id(st), rrdhost_hostname(host));
return 0;
@@ -590,178 +742,3 @@ collected_number rrddim_set(RRDSET *st, const char *id, collected_number value)
}
-// ----------------------------------------------------------------------------
-// compatibility layer for RRDDIM files v019
-
-#define RRDDIMENSION_MAGIC_V019 "NETDATA RRD DIMENSION FILE V019"
-
-struct avl_element_v019 {
- void *avl_link[2];
- signed char avl_balance;
-};
-
-struct rrddim_map_save_v019 {
- struct avl_element_v019 avl; // ignored
- void *id; // ignored
- void *name; // ignored
- uint32_t algorithm; // print warning on mismatch - update on load
- uint32_t rrd_memory_mode; // ignored
- long long multiplier; // print warning on mismatch - update on load
- long long divisor; // print warning on mismatch - update on load
- uint32_t flags; // ignored
- uint32_t hash; // ignored
- uint32_t hash_name; // ignored
- void *cache_filename; // ignored - we use it to keep the filename to save back
- size_t collections_counter; // ignored
- void *state; // ignored
- size_t unused[8]; // ignored
- long long collected_value_max; // ignored
- unsigned int updated:1; // ignored
- unsigned int exposed:1; // ignored
- struct timeval last_collected_time; // check to reset all - ignored after load
- long double calculated_value; // ignored
- long double last_calculated_value; // ignored
- long double last_stored_value; // ignored
- long long collected_value; // ignored
- long long last_collected_value; // load and save
- long double collected_volume; // ignored
- long double stored_volume; // ignored
- void *next; // ignored
- void *rrdset; // ignored
- long entries; // check to reset all - update on load
- int update_every; // check to reset all - update on load
- size_t memsize; // check to reset all - update on load
- char magic[sizeof(RRDDIMENSION_MAGIC_V019) + 1];// check to reset all - update on load
- void *variables; // ignored
- storage_number values[]; // the array of values
-};
-
-size_t rrddim_memory_file_header_size(void) {
- return sizeof(struct rrddim_map_save_v019);
-}
-
-void rrddim_memory_file_update(RRDDIM *rd) {
- if(!rd || !rd->db.rd_on_file) return;
- struct rrddim_map_save_v019 *rd_on_file = rd->db.rd_on_file;
-
- rd_on_file->last_collected_time.tv_sec = rd->collector.last_collected_time.tv_sec;
- rd_on_file->last_collected_time.tv_usec = rd->collector.last_collected_time.tv_usec;
- rd_on_file->last_collected_value = rd->collector.last_collected_value;
-}
-
-void rrddim_memory_file_free(RRDDIM *rd) {
- if(!rd || !rd->db.rd_on_file) return;
-
- // needed for memory mode map, to save the latest state
- rrddim_memory_file_update(rd);
-
- struct rrddim_map_save_v019 *rd_on_file = rd->db.rd_on_file;
- __atomic_sub_fetch(&rrddim_db_memory_size, rd_on_file->memsize + strlen(rd_on_file->cache_filename), __ATOMIC_RELAXED);
- freez(rd_on_file->cache_filename);
- netdata_munmap(rd_on_file, rd_on_file->memsize);
-
- // remove the pointers from the RRDDIM
- rd->db.rd_on_file = NULL;
- rd->db.data = NULL;
-}
-
-const char *rrddim_cache_filename(RRDDIM *rd) {
- if(!rd || !rd->db.rd_on_file) return NULL;
- struct rrddim_map_save_v019 *rd_on_file = rd->db.rd_on_file;
- return rd_on_file->cache_filename;
-}
-
-void rrddim_memory_file_save(RRDDIM *rd) {
- if(!rd || !rd->db.rd_on_file) return;
-
- rrddim_memory_file_update(rd);
-
- struct rrddim_map_save_v019 *rd_on_file = rd->db.rd_on_file;
- if(rd_on_file->rrd_memory_mode != RRD_MEMORY_MODE_SAVE) return;
-
- memory_file_save(rd_on_file->cache_filename, rd_on_file, rd_on_file->memsize);
-}
-
-bool rrddim_memory_load_or_create_map_save(RRDSET *st, RRDDIM *rd, RRD_MEMORY_MODE memory_mode) {
- if(memory_mode != RRD_MEMORY_MODE_SAVE && memory_mode != RRD_MEMORY_MODE_MAP)
- return false;
-
- struct rrddim_map_save_v019 *rd_on_file = NULL;
-
- unsigned long size = sizeof(struct rrddim_map_save_v019) + (st->db.entries * sizeof(storage_number));
-
- char filename[FILENAME_MAX + 1];
- char fullfilename[FILENAME_MAX + 1];
- rrdset_strncpyz_name(filename, rrddim_id(rd), FILENAME_MAX);
- snprintfz(fullfilename, FILENAME_MAX, "%s/%s.db", rrdset_cache_dir(st), filename);
-
- rd_on_file = (struct rrddim_map_save_v019 *)netdata_mmap(
- fullfilename, size, ((memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE), 1, false, NULL);
-
- if(unlikely(!rd_on_file)) return false;
-
- struct timeval now;
- now_realtime_timeval(&now);
-
- int reset = 0;
- rd_on_file->magic[sizeof(RRDDIMENSION_MAGIC_V019)] = '\0';
- if(strcmp(rd_on_file->magic, RRDDIMENSION_MAGIC_V019) != 0) {
- netdata_log_info("Initializing file %s.", fullfilename);
- memset(rd_on_file, 0, size);
- reset = 1;
- }
- else if(rd_on_file->memsize != size) {
- netdata_log_error("File %s does not have the desired size, expected %lu but found %lu. Clearing it.", fullfilename, size, (unsigned long int) rd_on_file->memsize);
- memset(rd_on_file, 0, size);
- reset = 1;
- }
- else if(rd_on_file->update_every != st->update_every) {
- netdata_log_error("File %s does not have the same update frequency, expected %d but found %d. Clearing it.", fullfilename, st->update_every, rd_on_file->update_every);
- memset(rd_on_file, 0, size);
- reset = 1;
- }
- else if(dt_usec(&now, &rd_on_file->last_collected_time) > (rd_on_file->entries * rd_on_file->update_every * USEC_PER_SEC)) {
- netdata_log_info("File %s is too old (last collected %llu seconds ago, but the database is %ld seconds). Clearing it.", fullfilename, dt_usec(&now, &rd_on_file->last_collected_time) / USEC_PER_SEC, rd_on_file->entries * rd_on_file->update_every);
- memset(rd_on_file, 0, size);
- reset = 1;
- }
-
- if(!reset) {
- rd->collector.last_collected_value = rd_on_file->last_collected_value;
-
- if(rd_on_file->algorithm != rd->algorithm)
- netdata_log_info("File %s does not have the expected algorithm (expected %u '%s', found %u '%s'). Previous values may be wrong.",
- fullfilename, rd->algorithm, rrd_algorithm_name(rd->algorithm), rd_on_file->algorithm, rrd_algorithm_name(rd_on_file->algorithm));
-
- if(rd_on_file->multiplier != rd->multiplier)
- netdata_log_info("File %s does not have the expected multiplier (expected %d, found %ld). "
- "Previous values may be wrong.", fullfilename, rd->multiplier, (long)rd_on_file->multiplier);
-
- if(rd_on_file->divisor != rd->divisor)
- netdata_log_info("File %s does not have the expected divisor (expected %d, found %ld). "
- "Previous values may be wrong.", fullfilename, rd->divisor, (long)rd_on_file->divisor);
- }
-
- // zero the entire header
- memset(rd_on_file, 0, sizeof(struct rrddim_map_save_v019));
-
- // set the important fields
- strcpy(rd_on_file->magic, RRDDIMENSION_MAGIC_V019);
- rd_on_file->algorithm = rd->algorithm;
- rd_on_file->multiplier = rd->multiplier;
- rd_on_file->divisor = rd->divisor;
- rd_on_file->entries = st->db.entries;
- rd_on_file->update_every = rd->rrdset->update_every;
- rd_on_file->memsize = size;
- rd_on_file->rrd_memory_mode = memory_mode;
- rd_on_file->cache_filename = strdupz(fullfilename);
-
- __atomic_add_fetch(&rrddim_db_memory_size, rd_on_file->memsize + strlen(rd_on_file->cache_filename), __ATOMIC_RELAXED);
-
- rd->db.data = &rd_on_file->values[0];
- rd->db.rd_on_file = rd_on_file;
- rd->db.memsize = size;
- rrddim_memory_file_update(rd);
-
- return true;
-}