The option will cause SiriDB to ignore broken or corrupted data that would otherwise prevent the server or database from fully loading.
This is useful for transient data on systems prone to hard resets, which might leave the database in an inconsistent state.
char server_address[SIRI_CFG_MAX_LEN_ADDRESS];
char db_path[XPATH_MAX];
char pipe_client_name[XPATH_MAX];
+
+ uint8_t ignore_broken_data;
};
#endif /* SIRI_CFG_H_ */
#
# SiriDB will not open more shard files than max_open_files. Note that the
-# total number of open files can be sligtly higher since SiriDB also needs
+# total number of open files can be slightly higher since SiriDB also needs
# a few other files to write to.
#
max_open_files = 32768
#
enable_shard_auto_duration = 1
+#
+# SiriDB will ignore corrupted or broken shards and related database files even
+# at the cost of losing some or all data.
+#
+# This option is useful especially for transient data on systems prone to power
+# outage or frequent hard resets.
+#
+ignore_broken_data = 0
+
#
# Enable named pipe support for client connections.
#
.pipe_support=0,
.pipe_client_name="siridb_client.sock",
.buffer_sync_interval=0,
+ .ignore_broken_data=0
};
static void SIRI_CFG_read_uint(
static void SIRI_CFG_read_shard_compression(cfgparser_t * cfgparser);
static void SIRI_CFG_read_shard_auto_duration(cfgparser_t * cfgparser);
static void SIRI_CFG_read_pipe_support(cfgparser_t * cfgparser);
+static void SIRI_CFG_ignore_broken_data(cfgparser_t * cfgparser);
void siri_cfg_init(siri_t * siri)
{
&tmp);
siri_cfg.buffer_sync_interval = (uint32_t) tmp;
+ SIRI_CFG_ignore_broken_data(cfgparser);
+
cfgparser_free(cfgparser);
}
}
}
+static void SIRI_CFG_ignore_broken_data(cfgparser_t * cfgparser)
+{
+ cfgparser_option_t * option;
+ cfgparser_return_t rc;
+ rc = cfgparser_get_option(
+ &option,
+ cfgparser,
+ "siridb",
+ "ignore_broken_data");
+ if (rc != CFGPARSER_SUCCESS)
+ {
+ return; // optional config option
+ }
+ else if (option->tp != CFGPARSER_TP_INTEGER || option->val->integer > 1)
+ {
+ log_warning(
+ "Error reading 'ignore_broken_data' in '%s': %s.",
+ siri.args->config,
+ "error: expecting 0 or 1");
+ }
+ else if (option->val->integer == 1)
+ {
+ siri_cfg.ignore_broken_data = 1;
+ }
+}
+
static void SIRI_CFG_read_addr(
cfgparser_t * cfgparser,
const char * option_name,
#include <unistd.h>
#include <xpath/xpath.h>
#include <assert.h>
+#include <stdbool.h>
#define SIRIDB_BUFFER_FN "buffer.dat"
char * buf, * pt;
long int offset = 0;
siridb_series_t * series;
- _Bool log_migrate = 1;
+ bool log_migrate = true;
uint32_t buf_start, series_id;
uint64_t * ts;
+ uint8_t ignore_broken_data = siri.cfg->ignore_broken_data;
log_info("Loading and cleanup buffer");
if (xpath_file_exist(fn_temp))
{
- free(buf);
- log_error(
+ if (ignore_broken_data)
+ {
+ log_error("Temporary buffer file found: '%s'. Removing...", fn_temp);
+ if (unlink(fn_temp))
+ {
+ free(buf);
+ log_error("Failed to remove temporary buffer: %s", fn_temp);
+ return -1;
+ }
+ } else
+ {
+ free(buf);
+ log_error(
"Temporary buffer file found: '%s'. "
"Check if something went wrong or remove this file", fn_temp);
- return -1;
+ return -1;
+ }
}
if ((fp = fopen(fn, "r")) == NULL)
if (log_migrate)
{
log_warning("Buffer will be migrated");
- log_migrate = 0;
+ log_migrate = false;
}
buffer__migrate_to_new(pt, cur_size);
}
)));
}
+static bool SHARDS_remove_shard_file(const char * path, const char * fn)
+{
+ siridb_misc_get_fn(shard_path, path, fn);
+ if (unlink(shard_path))
+ {
+ log_error("Error while removing shard file: '%s'", shard_path);
+ return false;
+ }
+
+ siridb_shard_idx_file(index_path, shard_path);
+ if (xpath_file_exist(index_path) && unlink(index_path))
+ {
+ log_error("Error while removing index file: '%s'", index_path);
+ return false;
+ }
+
+ log_warning("Shard file '%s' removed", fn);
+ return true;
+}
+
/*
* Returns 0 if successful or -1 in case of an error.
char buffer[XPATH_MAX];
int n, total, rc = 0;
uint64_t shard_id, duration;
+ bool ignore_broken_data = siri.cfg->ignore_broken_data;
memset(&st, 0, sizeof(struct stat));
if (siridb_shard_migrate(siridb, shard_id, &duration))
{
log_error("Error while migrating shard: '%s'", base_fn);
- rc = -1;
- break;
+ if (!ignore_broken_data || !SHARDS_remove_shard_file(path, base_fn))
+ {
+ rc = -1;
+ break;
+ } else {
+ continue;
+ }
}
}
else
if (siridb_shard_load(siridb, shard_id, duration))
{
log_error("Error while loading shard: '%s'", base_fn);
- rc = -1;
- break;
+ if (!ignore_broken_data || !SHARDS_remove_shard_file(path, base_fn))
+ {
+ rc = -1;
+ break;
+ } else {
+ continue;
+ }
}
}