// SPDX-License-Identifier: GPL-3.0-or-later
#include "sqlite_functions.h"
const char *database_config[] = {
"PRAGMA auto_vacuum=incremental; PRAGMA synchronous=1 ; PRAGMA journal_mode=WAL; PRAGMA temp_store=MEMORY;",
"PRAGMA journal_size_limit=16777216;",
"CREATE TABLE IF NOT EXISTS host(host_id blob PRIMARY KEY, hostname text, "
"registry_hostname text, update_every int, os text, timezone text, tags text);",
"CREATE TABLE IF NOT EXISTS chart(chart_id blob PRIMARY KEY, host_id blob, type text, id text, name text, "
"family text, context text, title text, unit text, plugin text, module text, priority int, update_every int, "
"chart_type int, memory_mode int, history_entries);",
"CREATE TABLE IF NOT EXISTS dimension(dim_id blob PRIMARY KEY, chart_id blob, id text, name text, "
"multiplier int, divisor int , algorithm int, options text);",
"CREATE TABLE IF NOT EXISTS chart_active(chart_id blob PRIMARY KEY, date_created int);",
"CREATE TABLE IF NOT EXISTS dimension_active(dim_id blob primary key, date_created int);",
"CREATE TABLE IF NOT EXISTS metadata_migration(filename text, file_size, date_created int);",
"CREATE INDEX IF NOT EXISTS ind_d1 on dimension (chart_id, id, name);",
"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));",
"delete from chart_active;",
"delete from dimension_active;",
"delete from chart where chart_id not in (select chart_id from dimension);",
"delete from host where host_id not in (select host_id from chart);",
"delete from chart_label where chart_id not in (select chart_id from chart);",
NULL
};
sqlite3 *db_meta = NULL;
static uv_mutex_t sqlite_transaction_lock;
static int execute_insert(sqlite3_stmt *res)
{
int rc;
while ((rc = sqlite3_step(res)) != SQLITE_DONE && unlikely(netdata_exit)) {
if (likely(rc == SQLITE_BUSY || rc == SQLITE_LOCKED))
usleep(SQLITE_INSERT_DELAY * USEC_PER_MS);
else {
error_report("SQLite error %d", rc);
break;
}
}
return rc;
}
/*
* Store a chart or dimension UUID in chart_active or dimension_active
* The statement that will be prepared determines that
*/
static int store_active_uuid_object(sqlite3_stmt **res, char *statement, uuid_t *uuid)
{
int rc;
// Check if we should need to prepare the statement
if (!*res) {
rc = sqlite3_prepare_v2(db_meta, statement, -1, res, 0);
if (unlikely(rc != SQLITE_OK)) {
error_report("Failed to prepare statement to store active object, rc = %d", rc);
return rc;
}
}
rc = sqlite3_bind_blob(*res, 1, uuid, sizeof(*uuid), SQLITE_STATIC);
if (unlikely(rc != SQLITE_OK))
error_report("Failed to bind input parameter to store active object, rc = %d", rc);
else
rc = execute_insert(*res);
return rc;
}
/*
* Marks a chart with UUID as active
* Input: UUID
*/
void store_active_chart(uuid_t *chart_uuid)
{
sqlite3_stmt *res = NULL;
int rc;
if (unlikely(!db_meta)) {
error_report("Database has not been initialized");
return;
}
if (unlikely(!chart_uuid))
return;
rc = store_active_uuid_object(&res, SQL_STORE_ACTIVE_CHART, chart_uuid);
if (rc != SQLITE_DONE)
error_report("Failed to store active chart, rc = %d", rc);
rc = sqlite3_finalize(res);
if (unlikely(rc != SQLITE_OK))
error_report("Failed to finalize statement in store active chart, rc = %d", rc);
return;
}
/*
* Marks a dimension with UUID as active
* Input: UUID
*/
void store_active_dimension(uuid_t *dimension_uuid)
{
sqlite3_stmt *res = NULL;
int rc;
if (unlikely(!db_meta)) {
error_report("Database has not been initialized");
return;
}
if (unlikely(!dimension_uuid))
return;
rc = store_active_uuid_object(&res, SQL_STORE_ACTIVE_DIMENSION, dimension_uuid);
if