#include "samples_db.h" #include namespace pex { static const char* k_schema = R"SQL( CREATE TABLE IF NOT EXISTS samples ( host_id INTEGER NOT NULL, unix_ts INTEGER NOT NULL, cpu_pct REAL NOT NULL, ram_used_mb REAL NOT NULL, ram_total_mb REAL NOT NULL, disk_read_mb_s REAL NOT NULL, disk_write_mb_s REAL NOT NULL, net_rx_mb_s REAL NOT NULL, net_tx_mb_s REAL NOT NULL, gpu_pct REAL NOT NULL, PRIMARY KEY(host_id, unix_ts) ); CREATE INDEX IF NOT EXISTS idx_samples_host_ts ON samples(host_id, unix_ts); )SQL"; SamplesDb::SamplesDb() = default; SamplesDb::~SamplesDb() { close(); } bool SamplesDb::open(const std::string& path) { if (sqlite3_open(path.c_str(), &db_) != SQLITE_OK) { db_ = nullptr; return false; } char* err = nullptr; if (sqlite3_exec(db_, k_schema, nullptr, nullptr, &err) != SQLITE_OK) { sqlite3_free(err); close(); return false; } return true; } void SamplesDb::close() { if (db_) { sqlite3_close(db_); db_ = nullptr; } } bool SamplesDb::insert(const Sample& s) { if (!db_) return false; const char* sql = "INSERT OR REPLACE INTO samples(host_id,unix_ts,cpu_pct,ram_used_mb,ram_total_mb," "disk_read_mb_s,disk_write_mb_s,net_rx_mb_s,net_tx_mb_s,gpu_pct) " "VALUES(?,?,?,?,?,?,?,?,?,?)"; sqlite3_stmt* st = nullptr; if (sqlite3_prepare_v2(db_, sql, -1, &st, nullptr) != SQLITE_OK) return false; sqlite3_bind_int64(st, 1, s.host_id); sqlite3_bind_int64(st, 2, s.unix_ts); sqlite3_bind_double(st, 3, s.cpu_pct); sqlite3_bind_double(st, 4, s.ram_used_mb); sqlite3_bind_double(st, 5, s.ram_total_mb); sqlite3_bind_double(st, 6, s.disk_read_mb_s); sqlite3_bind_double(st, 7, s.disk_write_mb_s); sqlite3_bind_double(st, 8, s.net_rx_mb_s); sqlite3_bind_double(st, 9, s.net_tx_mb_s); sqlite3_bind_double(st, 10, s.gpu_pct); bool ok = sqlite3_step(st) == SQLITE_DONE; sqlite3_finalize(st); return ok; } std::vector SamplesDb::query_range(int64_t host_id, int64_t unix_from, int64_t unix_to) { std::vector out; if (!db_) return out; const char* sql = "SELECT host_id,unix_ts,cpu_pct,ram_used_mb,ram_total_mb," "disk_read_mb_s,disk_write_mb_s,net_rx_mb_s,net_tx_mb_s,gpu_pct " "FROM samples WHERE host_id=? AND unix_ts BETWEEN ? AND ? ORDER BY unix_ts ASC"; sqlite3_stmt* st = nullptr; if (sqlite3_prepare_v2(db_, sql, -1, &st, nullptr) != SQLITE_OK) return out; sqlite3_bind_int64(st, 1, host_id); sqlite3_bind_int64(st, 2, unix_from); sqlite3_bind_int64(st, 3, unix_to); while (sqlite3_step(st) == SQLITE_ROW) { Sample s; s.host_id = sqlite3_column_int64(st, 0); s.unix_ts = sqlite3_column_int64(st, 1); s.cpu_pct = (float)sqlite3_column_double(st, 2); s.ram_used_mb = (float)sqlite3_column_double(st, 3); s.ram_total_mb = (float)sqlite3_column_double(st, 4); s.disk_read_mb_s = (float)sqlite3_column_double(st, 5); s.disk_write_mb_s = (float)sqlite3_column_double(st, 6); s.net_rx_mb_s = (float)sqlite3_column_double(st, 7); s.net_tx_mb_s = (float)sqlite3_column_double(st, 8); s.gpu_pct = (float)sqlite3_column_double(st, 9); out.push_back(s); } sqlite3_finalize(st); return out; } } // namespace pex