Skip to content

Commit

Permalink
WIP, WILL OVERRIDE COMMIT MESSAGE
Browse files Browse the repository at this point in the history
  • Loading branch information
Ómar Högni Guðmarsson committed Jun 18, 2024
1 parent 4faefa3 commit 914de53
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 6 deletions.
94 changes: 91 additions & 3 deletions exes/themis/inc/alarm_database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
namespace tfc::themis {

using enum tfc::snitch::level_e;
using enum tfc::snitch::api::active_e;
using tfc::snitch::api::time_point;

inline auto config_file_name_populate_dir() -> std::string {
auto const file{ base::make_config_file_name(base::get_exe_name(), "db") };
Expand Down Expand Up @@ -48,17 +48,18 @@ CREATE TABLE IF NOT EXISTS AlarmTranslation(
// And because sqlite does not offer a native timestamp type.
db_ << R"(
CREATE TABLE IF NOT EXISTS AlarmActivations(
activation_id INTEGER PRIMARY KEY,
activation_id LONG INTEGER PRIMARY KEY,
alarm_id INTEGER NOT NULL,
activation_time LONG INTEGER NOT NULL,
activation_level INTEGER NOT NULL,
activation_level BOOLEAN NOT NULL,
FOREIGN KEY(alarm_id) REFERENCES Alarms(alarm_id)
);
)";
db_ << R"(
CREATE TABLE IF NOT EXISTS AlarmAcks(
activation_id INTEGER,
ack_timestamp LONG INTEGER NOT NULL,
UNIQUE(activation_id) ON CONFLICT IGNORE,
FOREIGN KEY(activation_id) REFERENCES AlarmActivations(activation_id)
);
)";
Expand Down Expand Up @@ -150,6 +151,77 @@ ON Alarms.sha1sum = AlarmTranslation.sha1sum;
locale, short_msg, msg);
}

auto set_alarm(std::uint64_t alarm_id,
std::unordered_map<std::string_view, std::string_view> variables,
std::optional<tfc::snitch::api::time_point> tp = {}) -> void {
db_ << fmt::format("INSERT INTO AlarmActivations(alarm_id, activation_time, activation_level) VALUES({},{},1)", alarm_id,
milliseconds_since_epoch(tp));
std::int64_t last_insert_rowid = db_.last_insert_rowid();
if (last_insert_rowid < 0) {
throw std::runtime_error("Failed to insert activation into database");
}

for (auto& [key, value] : variables) {
db_ << fmt::format("INSERT INTO AlarmVariables(activation_id, variable_key, variable_value) VALUES({},{},'{}');",
last_insert_rowid, key, value);
}
}
auto reset_alarm(std::uint64_t alarm_id, std::optional<tfc::snitch::api::time_point> tp = {}) -> void {
db_ << fmt::format("INSERT INTO AlarmActivations(alarm_id, activation_time, activation_level) VALUES({},{},0)", alarm_id,
milliseconds_since_epoch(tp));
}

auto ack_alarm(std::uint64_t activation_id, std::optional<tfc::snitch::api::time_point> tp = {}) -> void {
db_ << fmt::format("INSERT INTO AlarmAcks(activation_id, ack_timestamp) VALUES({},{});", activation_id,
milliseconds_since_epoch(tp));
}

auto ack_all_alarms(std::optional<tfc::snitch::api::time_point> tp = {}) -> void {
// TODO: This is not 100% but we should be able to do this in a single query. Very fast.
// Gonna build up some more elaborate test cases and dig into this when that is complete
db_ << fmt::format(
"INSERT INTO AlarmAcks(activation_id, ack_timestamp) SELECT DISTINCT activation_id, {} FROM AlarmActivations;",
milliseconds_since_epoch(tp));
}

[[nodiscard]] auto list_activations(std::string_view locale,
std::uint64_t start_count,
std::uint64_t count,
tfc::snitch::level_e level,
tfc::snitch::api::active_e active,
std::optional<tfc::snitch::api::time_point> start,
std::optional<tfc::snitch::api::time_point> end)
-> std::vector<tfc::snitch::api::activation> {
std::vector<tfc::snitch::api::activation> activations;
std::string populated_query = fmt::format(R"(
SELECT activation_id, Alarms.alarm_id, activation_time, activation_level, Alarms.short_msg, Alarms.msg, AlarmTranslation.short_msg, AlarmTranslation.msg, Alarms.alarm_latching, Alarms.alarm_level
FROM AlarmActivations
JOIN Alarms on (Alarm.alarm_id = AlarmActivations.alarm_id)
LEFT OUTER JOIN AlarmTranslation on (Alarms.sha1sum = AlarmTranslation.sha1sum)
WHERE AlarmTranslation.locale = '{}' AND activation_time >= {} AND activation_time <= {}
)",
locale, milliseconds_since_epoch(start), milliseconds_since_epoch(end));
if (level != tfc::snitch::level_e::unknown) {
populated_query += fmt::format("AND alarm_level = {}", static_cast<std::uint8_t>(level));
}
if (active != tfc::snitch::api::active_e::all) {
populated_query += fmt::format("AND activation_level = {}", static_cast<std::uint8_t>(active));
}
populated_query += fmt::format("LIMIT {} OFFSET {};", count, start_count);
db_ << populated_query >>
[&](std::uint64_t activation_id, std::uint64_t alarm_id, std::int64_t activation_time, bool activation_level,
std::string short_msg_en, std::string msg_en, std::unique_ptr<std::string> translated_short_msg,
std::unique_ptr<std::string> translated_msg, bool alarm_latching, std::uint8_t alarm_level) {
std::string final_short_msg = translated_short_msg == nullptr ? short_msg_en : *translated_short_msg;
std::string final_msg = translated_msg == nullptr ? msg_en : *translated_msg;
tfc::snitch::api::activation temp{ alarm_id, activation_id, final_short_msg, final_msg, activation_level,
static_cast<tfc::snitch::level_e>(alarm_level), alarm_latching,
timepoint_from_milliseconds(activation_time) };
activations.emplace_back(temp);
};
return activations;
}

// Note. Use `echo -n "value" | sha1sum` to not hash the newline character and
// match the results from this function.
[[nodiscard]] static auto get_sha1(std::string_view msg) -> std::string {
Expand All @@ -167,6 +239,22 @@ ON Alarms.sha1sum = AlarmTranslation.sha1sum;
}

private:
static std::int64_t milliseconds_since_epoch(std::optional<tfc::snitch::api::time_point> tp) {
tfc::snitch::api::time_point value =
tp.value_or(std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()));
return milliseconds_since_epoch_base(value);
}

static constexpr std::int64_t milliseconds_since_epoch_base(tfc::snitch::api::time_point tp) {
return std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch()).count();
}

static constexpr tfc::snitch::api::time_point timepoint_from_milliseconds(std::int64_t ms) {
return tfc::snitch::api::time_point(std::chrono::milliseconds(ms));
}

static_assert(milliseconds_since_epoch_base(timepoint_from_milliseconds(1000)) == 1000);

Check failure on line 256 in exes/themis/inc/alarm_database.hpp

View workflow job for this annotation

GitHub Actions / build and run tests (gcc-debug)

non-constant condition for static assertion

Check failure on line 256 in exes/themis/inc/alarm_database.hpp

View workflow job for this annotation

GitHub Actions / build and run tests (gcc-debug)

'static constexpr tfc::snitch::api::time_point tfc::themis::alarm_database::timepoint_from_milliseconds(int64_t)' called in a constant expression before its definition is complete

Check failure on line 256 in exes/themis/inc/alarm_database.hpp

View workflow job for this annotation

GitHub Actions / build and run tests (gcc-release)

non-constant condition for static assertion

Check failure on line 256 in exes/themis/inc/alarm_database.hpp

View workflow job for this annotation

GitHub Actions / build and run tests (gcc-release)

'static constexpr tfc::snitch::api::time_point tfc::themis::alarm_database::timepoint_from_milliseconds(int64_t)' called in a constant expression before its definition is complete

Check failure on line 256 in exes/themis/inc/alarm_database.hpp

View workflow job for this annotation

GitHub Actions / build and run tests (clang-debug)

static assertion expression is not an integral constant expression

Check failure on line 256 in exes/themis/inc/alarm_database.hpp

View workflow job for this annotation

GitHub Actions / build and run tests (clang-release)

static assertion expression is not an integral constant expression

Check failure on line 256 in exes/themis/inc/alarm_database.hpp

View workflow job for this annotation

GitHub Actions / build and run tests (gcc-debug-dynamic)

non-constant condition for static assertion

Check failure on line 256 in exes/themis/inc/alarm_database.hpp

View workflow job for this annotation

GitHub Actions / build and run tests (gcc-debug-dynamic)

'static constexpr tfc::snitch::api::time_point tfc::themis::alarm_database::timepoint_from_milliseconds(int64_t)' called in a constant expression before its definition is complete

Check failure on line 256 in exes/themis/inc/alarm_database.hpp

View workflow job for this annotation

GitHub Actions / build and run tests (clang-debug-dynamic)

static assertion expression is not an integral constant expression

sqlite::database db_;
};
} // namespace tfc::themis
4 changes: 4 additions & 0 deletions exes/themis/tests/themis_database_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,9 @@ auto main(int argc, char** argv) -> int {
expect(iterator != alarms.at(0).translations.end());
expect(iterator->second.description == "Some icelandic really");
expect(iterator->second.details == "This is really some icelandic");

auto activations = alarm_db.list_activations("es", 0, 10, tfc::snitch::level_e::unknown, tfc::snitch::api::active_e::all,
, std::chrono::system_clock::now());

Check failure on line 65 in exes/themis/tests/themis_database_test.cpp

View workflow job for this annotation

GitHub Actions / build and run tests (gcc-debug)

expected primary-expression before ',' token

Check failure on line 65 in exes/themis/tests/themis_database_test.cpp

View workflow job for this annotation

GitHub Actions / build and run tests (gcc-release)

expected primary-expression before ',' token

Check failure on line 65 in exes/themis/tests/themis_database_test.cpp

View workflow job for this annotation

GitHub Actions / build and run tests (clang-debug)

expected expression

Check failure on line 65 in exes/themis/tests/themis_database_test.cpp

View workflow job for this annotation

GitHub Actions / build and run tests (clang-release)

expected expression

Check failure on line 65 in exes/themis/tests/themis_database_test.cpp

View workflow job for this annotation

GitHub Actions / build and run tests (gcc-debug-dynamic)

expected primary-expression before ',' token

Check failure on line 65 in exes/themis/tests/themis_database_test.cpp

View workflow job for this annotation

GitHub Actions / build and run tests (clang-debug-dynamic)

expected expression
expect(activations.size() == 0);
};
}
9 changes: 6 additions & 3 deletions libs/snitch/inc/public/tfc/snitch/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

namespace tfc::snitch {

enum struct level_e : std::uint8_t {
unknown = 0,
enum struct level_e : std::int8_t {
all = -1,
unknown,
info,
warning,
error,
Expand All @@ -18,7 +19,7 @@ namespace api {
using time_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>;
using alarm_id_t = std::int64_t;

enum struct active_e : std::int32_t {
enum struct active_e : std::int8_t {
all = -1,
inactive = 0,
active = 1
Expand All @@ -41,6 +42,8 @@ struct alarm {
};

struct activation {
std::uint64_t alarm_id;
std::uint64_t activation_id;
std::string description;
std::string details;
bool active{};
Expand Down

0 comments on commit 914de53

Please sign in to comment.