diff --git a/CMakeLists.txt b/CMakeLists.txt index f5cb713..a02356a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,10 @@ include_directories(./) #add_library(ActCommon SHARED IMPORTED) #set_target_properties(ActCommon PROPERTIES IMPORTED_LOCATION $ENV{ACT_HOME}/lib/libvlsilib.a) +# Include the cluster librar +add_library(act-cluster-lib SHARED IMPORTED) +set_target_properties(act-cluster-lib PROPERTIES IMPORTED_LOCATION $ENV{ACT_HOME}/lib/libact_cluster.so) + # ATTENTION # The main executable is defined in the CMakeLists.txt in the ./src folder. @@ -75,7 +79,7 @@ add_subdirectory(src) # Link the needed libraries into it target_link_libraries( ${PROJECT_NAME} - actsim-agent-db-lib + act-cluster-lib actsim-agent-lib ) diff --git a/include/actsim_agent/actsim_agent.hpp b/include/actsim_agent/actsim_agent.hpp index 8e2c102..e19945d 100644 --- a/include/actsim_agent/actsim_agent.hpp +++ b/include/actsim_agent/actsim_agent.hpp @@ -26,7 +26,7 @@ #ifndef __ACTSIM_AGENT__ #define __ACTSIM_AGENT__ -#include +#include #define DATABASE_VERSION 2 diff --git a/include/actsim_agent/downloader.hpp b/include/actsim_agent/downloader.hpp index f329ec1..19c6dfd 100644 --- a/include/actsim_agent/downloader.hpp +++ b/include/actsim_agent/downloader.hpp @@ -27,8 +27,8 @@ #define __DOWNLOADER_H__ #include -#include -#include +#include +#include #include "task_interface.hpp" class Downloader { diff --git a/include/actsim_agent/monitor.hpp b/include/actsim_agent/monitor.hpp index 5d70cfe..db0ee7a 100644 --- a/include/actsim_agent/monitor.hpp +++ b/include/actsim_agent/monitor.hpp @@ -31,8 +31,8 @@ #include #include #include -#include -#include +#include +#include #include "task_interface.hpp" #include "worker.hpp" diff --git a/include/actsim_agent/task_interface.hpp b/include/actsim_agent/task_interface.hpp index 86d2489..0d6821d 100644 --- a/include/actsim_agent/task_interface.hpp +++ b/include/actsim_agent/task_interface.hpp @@ -31,7 +31,7 @@ #include #include #include -#include "task.hpp" +#include class TaskInterface { @@ -54,6 +54,10 @@ class TaskInterface { std::unique_ptr pop_finished(bool& empty); size_t get_buffer_space(); + bool search_and_increment(db::uuid_t id, std::string& design); + void decrement(db::uuid_t id); + void store(db::uuid_t, std::string& design); + bool running() { return this->running_.load(std::memory_order_relaxed); }; bool is_stop_immediate() { return !this->immediate_stop.load(std::memory_order_relaxed); }; void stop() { this->running_.store(false, std::memory_order_relaxed); }; diff --git a/include/actsim_agent/uploader.hpp b/include/actsim_agent/uploader.hpp index 672d3f2..7d93522 100644 --- a/include/actsim_agent/uploader.hpp +++ b/include/actsim_agent/uploader.hpp @@ -26,8 +26,8 @@ #ifndef __UPLOADER_H__ #define __UPLOADER_H__ -#include -#include +#include +#include #include #include "task_interface.hpp" diff --git a/include/actsim_agent/worker.hpp b/include/actsim_agent/worker.hpp index 0536202..cf1db4e 100644 --- a/include/actsim_agent/worker.hpp +++ b/include/actsim_agent/worker.hpp @@ -28,7 +28,7 @@ #include #include -#include +#include #include "task_interface.hpp" class Worker { diff --git a/include/cli_util.hpp b/include/cli_util.hpp index defa143..5e2e38f 100644 --- a/include/cli_util.hpp +++ b/include/cli_util.hpp @@ -27,7 +27,7 @@ #include #include -#include "db_client.hpp" +#include #define POSTGRES_DEFAULT_PORT 5432 diff --git a/include/db_lib/db_client.hpp b/include/db_lib/db_client.hpp deleted file mode 100644 index 5e28979..0000000 --- a/include/db_lib/db_client.hpp +++ /dev/null @@ -1,142 +0,0 @@ - -/************************************************************************* - * - * Copyright (c) 2023 Fabian Posch - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - ************************************************************************** - */ - - -#ifndef __DB_CLIENT_H__ -#define __DB_CLIENT_H__ - - -#include -#include -#include -#include "db_types.hpp" -#include "task.hpp" - -namespace db { - -using namespace std; - -// some database constants -#define MAX_CON_RETRIES 5 - -class Connection { - - public: - - Connection( - db_credentials_t& credentials, - std::function setup_function - ); - - Connection( - db_credentials_t& credentials - ); - - ~Connection(); - - pqxx::connection* get_connection() { return c; }; - void setup() { - setup_function(this->c); - } - - bool connect(); - void disconnect(); - bool ensure_connected(); - int find_job(std::string p_name, std::string *f_name); - JobStatusType get_job_status(std::string job); - JobStatusType get_task_status(db::uuid_t); - - bool prepare_statements(vector> statements); - bool prepare_statement(std::string name, std::string statement); - bool unprepare_statement(std::string name); - - // Send request takes an arbitrary request method to the database and wraps error handling - // around it. It takes a function with an arbitrary set of arguments and the arguments to give - // that function and returns whatever the function returns. - // Careful with typing here! C++ doesn't quite do the strictest typing once you go deep like this! - // The function is defined here as it can be accessed from outside this library and is templated. - // This means it must be accessible to the compiler at all times. Failing this will cause a linker error. - template - bool send_request(std::function *db_function, Args... args) { - - retry_send: - - if (!ensure_connected()) { - cerr << "Could contact database. Broken database connection." << endl; - return false; - } - - try { - - pqxx::work txn(*c); - - try { - // we assume the lambda takes a pointer to a transaction object as first argument - // and whatever else was given to us as the rest - (*db_function)(&txn, args...); - - // commit the task to the database - txn.commit(); - } catch (const exception& e) { - - // if something happened during the transaction, we roll it back - txn.abort(); - - cerr << "Could not complete database operation. Error in execution." << endl; - cerr << e.what() << endl; - - return false; - } - - } catch (const pqxx::broken_connection& e) { - cerr << "Pipe broke during database operation... Retrying..." << endl; - cerr << e.what() << endl; - - // using a goto here since it'll gracefully retry connection - goto retry_send; - } - - return true; - }; - - private: - - db_credentials_t db_credentials; - pqxx::connection *c; - std::function setup_function; - bool connected; -}; - -const vector> uplink_statements = { - {"commit_task", "UPDATE tasks SET t_status = DONE, error = $2, sim_log = $3, sim_trace = $4 WHERE id = $1"} -}; - -const vector> downlink_statements = { - {"check_open_tasks", "SELECT id FROM tasks WHERE t_status=OPEN LIMIT 1"}, - // TODO add inner join to grab pipeline depth - {"fetch_task", "SELECT id, job, t_status, t_type, is_reference, reference, max_plf, error, sim_log FROM tasks WHERE id = $1 LIMIT 1"} -}; - -}; - -#endif diff --git a/include/db_lib/db_types.hpp b/include/db_lib/db_types.hpp deleted file mode 100644 index 93a9692..0000000 --- a/include/db_lib/db_types.hpp +++ /dev/null @@ -1,314 +0,0 @@ - -/************************************************************************* - * - * Copyright (c) 2023 Fabian Posch - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - ************************************************************************** - */ - -#ifndef __DB_TYPES_HPP__ -#define __DB_TYPES_HPP__ - -#include -#include - -namespace db { - -// credentials for database access -struct db_credentials_t { - std::string server = ""; - bool server_override = false; - int port = 0; - bool port_override = false; - std::string uname = ""; - bool uname_override = false; - std::string pwd = ""; - bool pwd_override = false; - std::string dbase = ""; - bool dbase_override = false; - int version; -}; - -// create UUID type to store database 128 UUID type -struct uuid_t { - uint64_t uuid_upper, uuid_lower; - - uuid_t& operator=(uint64_t other) { - this->uuid_lower = other; - this->uuid_upper = 0; - return *this; - } -}; - - -// override comparison operator to make our life easier -inline bool operator==(uuid_t const & lhs, uuid_t const & rhs) { - return lhs.uuid_upper == rhs.uuid_upper && lhs.uuid_lower == rhs.uuid_lower; -} -inline bool operator==(uuid_t const & lhs, int const & rhs) { - return rhs >= 0 && lhs.uuid_lower == (uint64_t)rhs; -} -inline bool operator==(int const & lhs, uuid_t const & rhs) { - return lhs >= 0 && (uint64_t)lhs == rhs.uuid_lower; -} -inline bool operator!=(uuid_t const & lhs, uuid_t const & rhs) { - return lhs.uuid_upper != rhs.uuid_upper || lhs.uuid_lower != rhs.uuid_lower; -} -inline bool operator!=(uuid_t const & lhs, int const & rhs) { - return rhs < 0 || lhs.uuid_lower != (uint64_t)rhs; -} -inline bool operator!=(int const & lhs, uuid_t const & rhs) { - return lhs < 0 || (uint64_t)lhs != rhs.uuid_lower; -} - - -// easier conversion to string -inline std::string to_string(uuid_t const &value) { - std::ostringstream uuid_s; - uuid_s << std::hex; - uuid_s << std::setfill('0') << std::setw(16) << value.uuid_upper; - uuid_s << std::setfill('0') << std::setw(16) << value.uuid_lower; - return uuid_s.str(); -} - -// stream operations -inline std::ostream& operator<<(std::ostream& os, uuid_t& value) { - os << to_string(value); - return os; -}; - -// macro for registering enum classes for PQXX - -template -struct is_enum_class { - static constexpr bool value = std::is_enum_v && !std::is_convertible_v; -}; - -template -struct is_unordered_map_string { - static constexpr bool value = false; -}; - -template -struct is_unordered_map_string> { - static constexpr bool value = true; -}; - -template -struct is_map_key_type_same_as_enum { - static constexpr bool value = std::is_same_v && - std::is_same_v; -}; - -}; - -// hash operator to be able use uuid_t as a hashmap key -template<> -struct std::hash { - std::size_t operator()(const db::uuid_t& k) const { - using std::size_t; - using std::hash; - - return hash()(hash()(k.uuid_upper) ^ hash()(k.uuid_lower)); - } -}; - - -/** - * @brief Generate type conversion for enum class macros in the libpqxx library - * - * Calling this macro will generate the code necessary for converting enum class types in yaml-cpp internally. - * For this you additionally need a std::unordered_map, mapping string values to your - * custom enum class type. - * - * For more information see https://libpqxx.readthedocs.io/en/7.4.1/a01360.html - * - * @param T The type you want to generate the translation for - * @param lookup_table the unordered map, mapping string values of your type to the internal representation - * - */ -#define DB_REGISTER_ENUM_CLASS(T, lookup_table, name) \ - namespace pqxx { \ - \ - static_assert(db::is_enum_class::value, "DB_REGISTER_ENUM_TYPE: 'T' must be an enum class"); \ - static_assert(db::is_unordered_map_string::value, "DB_REGISTER_ENUM_TYPE: 'lookup_table' must be std::unordered_map"); \ - static_assert(db::is_map_key_type_same_as_enum::value, "DB_REGISTER_ENUM_TYPE: 'lookup_table' content must be of type T"); \ - \ - \ - template<> \ - std::string const type_name{name}; \ - \ - template<> \ - struct nullness : pqxx::no_null {}; \ - \ - template<> \ - struct string_traits { \ - \ - static T from_string(std::string_view text) { \ - \ - /* turn the string_view into a string */ \ - std::string str(text); \ - \ - /* make sure the enum value exists */ \ - if (lookup_table.find(str) == lookup_table.end()) throw pqxx::conversion_error("Could not convert " + str + " to " + name); \ - \ - return lookup_table[str]; \ - }; \ - \ - static zview to_buf(char *begin, char *end, T const &value) { \ - std::string str = ""; \ - \ - for (auto& it : lookup_table) { \ - if (it.second == value) { \ - str = it.first; \ - break; \ - } \ - } \ - \ - /* make sure we actually have enough space for the enum */ \ - if (std::distance(begin, end) < static_cast(str.size() + 1)) { \ - std::ostringstream str_str; \ - str_str << "Buffer for "; \ - str_str << name; \ - str_str << " to small"; \ - throw conversion_overrun(str_str.str()); \ - }\ - \ - const char* c_str = str.c_str(); \ - \ - std::memcpy(begin, c_str, sizeof(char) * str.length()); \ - \ - return zview(begin, str.length()); \ - }; \ - \ - static char *into_buf(char *begin, char *end, T const &value) { \ - std::string str = ""; \ - \ - for (auto& it : lookup_table) { \ - if (it.second == value) { \ - str = it.first; \ - break; \ - } \ - } \ - \ - /* make sure we actually have enough space for the enum */ \ - if (std::distance(begin, end) < static_cast(str.size() + 1)) { \ - std::ostringstream str_str; \ - str_str << "Buffer for "; \ - str_str << name; \ - str_str << " to small"; \ - throw conversion_overrun(str_str.str()); \ - }\ - \ - const char* c_str = str.c_str(); \ - \ - std::memcpy(begin, c_str, sizeof(char) * str.length()); \ - \ - return begin; \ - }; \ - \ - static std::size_t size_buffer(T const &value) noexcept { \ - \ - std::string str; \ - str = ""; \ - \ - for (auto& it : lookup_table) { \ - if (it.second == value) { \ - str = it.first; \ - break; \ - } \ - } \ - \ - return str.size() + 1; \ - }; \ - }; \ - }; - - -/** - * @brief Conversion extension for uuid_t for the pqxx library - * - * For more information see https://libpqxx.readthedocs.io/en/7.4.1/a01360.html - * - */ -namespace pqxx { - -template<> -std::string const type_name{"uuid_t"}; - -template<> -struct nullness : pqxx::no_null {}; - -template<> -struct string_traits { - - static db::uuid_t from_string(std::string_view text) { - - if (text.size() != 36) { - throw pqxx::conversion_error("Invalid binary string size for uuid_t. Expected: 36; Actual: " + std::to_string(text.size())); - } - - // turn the string_view into a string and remove the '-' - std::string form(text); - form.erase(std::remove(form.begin(), form.end(), '-'), form.end()); - - // then parse into numbers - std::istringstream high_stream(form.substr(0, 16)); - std::istringstream low_stream(form.substr(16, 16)); - - uint64_t low, high; - - high_stream >> std::hex >> high; - low_stream >> std::hex >> low; - - return {high, low}; - }; - - static zview to_buf(char *begin, char *end, db::uuid_t const &value) { - std::string str = db::to_string(value); - - // make sure we actually have enough space for the UUID - if (std::distance(begin, end) < static_cast(str.size() + 1)) throw conversion_overrun("Buffer for UUID to small"); - - const char* c_str = str.c_str(); - - std::memcpy(begin, c_str, sizeof(char) * str.length()); - - return zview(begin, str.length()); - }; - - static char *into_buf(char *begin, char *end, db::uuid_t const &value) { - std::string str = db::to_string(value); - - // make sure we actually have enough space for the UUID - if (std::distance(begin, end) < static_cast(str.size() + 1)) throw conversion_overrun("Buffer for UUID to small"); - - const char* c_str = str.c_str(); - - std::memcpy(begin, c_str, sizeof(char) * str.length()); - - return begin; - }; - - constexpr static std::size_t size_buffer([[maybe_unused]] db::uuid_t const &value) noexcept { return sizeof(char) * 33; }; -}; - -}; - - -#endif \ No newline at end of file diff --git a/include/db_lib/task.hpp b/include/db_lib/task.hpp deleted file mode 100644 index e9896f3..0000000 --- a/include/db_lib/task.hpp +++ /dev/null @@ -1,294 +0,0 @@ -/************************************************************************* - * - * Copyright (c) 2023 Fabian Posch - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - ************************************************************************** - */ - - -#ifndef __TASK_H__ -#define __TASK_H__ - -#include -#include -#include -#include "db_types.hpp" - -/** - * @brief Representation of the current status of a job. - * - */ -enum class JobStatusType {NOT_STARTED, IN_PROGRESS, FINISHED, HALTED, UNKNOWN}; - -// string mapping for job status type enum -static std::unordered_map job_status_type_st { - {JobStatusType::NOT_STARTED, "not_started"}, - {JobStatusType::IN_PROGRESS, "in_progress"}, - {JobStatusType::FINISHED, "finished"}, - {JobStatusType::HALTED, "halted"}, - {JobStatusType::UNKNOWN, "unknown"} -}; - -inline std::string to_string(JobStatusType const &value) { - return job_status_type_st[value]; -}; - -inline std::ostream& operator<<(std::ostream& os, JobStatusType& value) { - os << to_string(value); - return os; -}; - -JobStatusType convert_to_job_status(std::string status_string); - - -/** - * @brief Defines if a simulation task should be executed a single time or - * dependent on a central coverage model. The latter task type can also be - * executed by more than just a single node to hasten progress. - */ -enum class TaskTypeType {UNKNOWN, SINGLE, MULTI_COV}; - -// string mapping for task type enum -static std::unordered_map task_type_type_st { - {TaskTypeType::UNKNOWN, "unknown"}, - {TaskTypeType::SINGLE, "single"}, - {TaskTypeType::MULTI_COV, "multi_cov"} -}; - -inline std::string to_string(TaskTypeType const &value) { - return task_type_type_st[value]; -}; - -inline std::ostream& operator<<(std::ostream& os, TaskTypeType& value) { - os << to_string(value); - return os; -}; - -TaskTypeType convert_to_task_type(std::string type_string); - - -// TODO check if this is complete -/** - * @brief If a task simulation was aborted or completed with an error, - * this type represents the types of error encountered. - */ -enum class TaskErrorType {UNKNOWN, NONE, SYNTAX, VALUE, CODE, METASTABLE, TIMING, DEADLOCK}; - -// string mapping for task error type enum -static std::unordered_map task_error_type_st { - {TaskErrorType::UNKNOWN, "unknown"}, - {TaskErrorType::NONE, "none"}, - {TaskErrorType::SYNTAX, "syntax"}, - {TaskErrorType::VALUE, "value"}, - {TaskErrorType::CODE, "code"}, - {TaskErrorType::METASTABLE, "metastable"}, - {TaskErrorType::TIMING, "timing"}, - {TaskErrorType::DEADLOCK, "deadlock"} -}; - -inline std::string to_string(TaskErrorType const &value) { - return task_error_type_st[value]; -}; - -inline std::ostream& operator<<(std::ostream& os, TaskErrorType& value) { - os << to_string(value); - return os; -}; - -TaskErrorType convert_to_task_error(std::string error_string); - - -/** - * @brief Representation of teh current status of a task. - * - */ -enum class TaskStatusType {UNKNOWN, OPEN, IN_PROGRESS, DONE}; - -// string mapping for task status enum -static std::unordered_map task_status_type_st { - {TaskStatusType::UNKNOWN, "unknown"}, - {TaskStatusType::OPEN, "open"}, - {TaskStatusType::IN_PROGRESS, "in_progress"}, - {TaskStatusType::DONE, "done"} -}; - -inline std::string to_string(TaskStatusType const &value) { - return task_status_type_st[value]; -}; - -inline std::ostream& operator<<(std::ostream& os, TaskStatusType& value) { - os << to_string(value); - return os; -}; - -TaskStatusType convert_to_task_status(std::string status_string); - -/** - * @brief Task class represents one simulation task and its settings. - */ -class Task { - public: - - Task( db::uuid_t task_uuid, - std::string job_id, - TaskStatusType status, - TaskTypeType type, - bool is_reference, - db::uuid_t reference_uuid, - float max_plf, - TaskErrorType error, - std::string sim_log - ); - - Task( db::uuid_t task_uuid, - std::string job_id, - TaskTypeType type, - bool is_reference, - db::uuid_t reference_uuid, - float max_plf - ); - - /** - * @brief Get the UUID of this task - * - * @return db::uuid_t Task UUID - */ - const db::uuid_t& uuid = task_uuid; - - /** - * @brief Get the ID of the job this task belongs to - * - * @return const char* Job ID - */ - const std::string& job_id = job_id_; - - /** - * @brief Get information whether this task is a one shot simulation or contributes - * to a central coverage model. - * - * @return TaskType - */ - const TaskTypeType& task_type = task_type_; - - /** - * @brief Does this simulation task have a reference task to compare to? - * - * @return true It does - * @return false It does not - */ - const bool& is_reference_run = is_reference_; - - /** - * @brief Get the reference object UUID - * - * @return The UUID of the reference simulation task - */ - const db::uuid_t& reference_uuid = reference_uuid_; - - /** - * @brief Get the status of this task - * - * @return TaskStatusType The task status - */ - const TaskStatusType& status = status_; - - /** - * @brief Set the status of the task - * - * @param new_status The new status this task should be set to - */ - void set_status(TaskStatusType new_status) { this->status_ = new_status; }; - - /** - * @brief Get the value of the maximum allowed pipeline load factor - * - * @return float - */ - const float& max_plf = max_plf_; - - /** - * @brief Get the error with which this simulation task was completed - * - * @return TaskErrorType - */ - const TaskErrorType& error = error_; - - /** - * @brief Set the error with which this task was completed - * - * @param error - */ - void set_error(TaskErrorType error) { this->error_ = error; }; - - /** - * @brief Get the simulation log of this task. Empty if not yet simulated. - * - * @return std::string The simulation log in JSON format - */ - const std::string& sim_log = sim_log_; - - /** - * @brief Set the simulation log - * - * @param log - */ - void set_log(std::string log) { this->sim_log_ = log; }; - - /** - * @brief Get the simulation trace of this task. Empty if not yet simulated. - * - * @return std::string The simulation log in TODO format - */ - const std::string& trace = trace_; - - /** - * @brief Set the simulation trace - * - * @param trace - */ - void set_trace(std::string trace) { this->trace_ = trace; }; - - ///////////////////////////////////// - private: - - // UUID of this task in the database - db::uuid_t task_uuid; - - // ID of the job this task belongs to - std::string job_id_; - - // Is this task a single shot or does it depend on central coverage metrics? - TaskTypeType task_type_; - - // Does this task have a reference run which we should compare the trace to? - bool is_reference_; - TaskStatusType status_; - db::uuid_t reference_uuid_; - - // maximum pipeline load factor - float max_plf_; - // error with which this task was completed - TaskErrorType error_; - - // simulation output - std::string sim_log_; - std::string trace_; - -}; - -#endif \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2ff8d25..fe37a69 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,11 +1,9 @@ # Grab necessary libraries from ACT_HOME -#include_directories($ENV{ACT_HOME}/include) +include_directories($ENV{ACT_HOME}/include) include_directories(../include) -include_directories(../include/db_lib) include_directories(../include/actsim_agent) -add_subdirectory(db_lib) add_subdirectory(actsim_agent) file( diff --git a/src/actsim_agent/CMakeLists.txt b/src/actsim_agent/CMakeLists.txt index cad6ba5..a167ac6 100644 --- a/src/actsim_agent/CMakeLists.txt +++ b/src/actsim_agent/CMakeLists.txt @@ -1,6 +1,7 @@ include_directories(../../include) include_directories(../../include/db_lib) include_directories(../../include/actsim_agent) +include_directories($ENV{ACT_HOME}/include) file( GLOB actsim_agent_SRC @@ -15,6 +16,6 @@ add_library( target_link_libraries( actsim-agent-lib - actsim-agent-db-lib + act-cluster-lib -lpqxx -lpq -latomic ) \ No newline at end of file diff --git a/src/actsim_agent/actsim_agent.cpp b/src/actsim_agent/actsim_agent.cpp index 7490e8f..a68d676 100644 --- a/src/actsim_agent/actsim_agent.cpp +++ b/src/actsim_agent/actsim_agent.cpp @@ -27,8 +27,8 @@ #include #include #include -#include -#include +#include +#include #include "task_interface.hpp" #include "worker.hpp" #include "uploader.hpp" diff --git a/src/actsim_agent/downloader.cpp b/src/actsim_agent/downloader.cpp index ae0081b..eafa970 100644 --- a/src/actsim_agent/downloader.cpp +++ b/src/actsim_agent/downloader.cpp @@ -73,10 +73,10 @@ bool Downloader::fetch_tasks(size_t n) { id = 1; auto job_id = "deadbeef"; - for (size_t i = 0; i < n; ++i) { - auto task = std::make_unique(id, job_id, TaskTypeType::SINGLE, false, db::uuid_t(), 2); - this->interface.push_fresh(std::move(task)); - } + //for (size_t i = 0; i < n; ++i) { + // auto task = std::make_unique(id, job_id, TaskTypeType::SINGLE, false, db::uuid_t(), 2); + // this->interface.push_fresh(std::move(task)); + //} return true; } diff --git a/src/actsim_agent/monitor.cpp b/src/actsim_agent/monitor.cpp index 8a12e87..6028165 100644 --- a/src/actsim_agent/monitor.cpp +++ b/src/actsim_agent/monitor.cpp @@ -23,9 +23,9 @@ ************************************************************************** */ -#include -#include -#include +#include +#include +#include #include #include "util.h" #include "monitor.hpp" diff --git a/src/actsim_agent/task_interface.cpp b/src/actsim_agent/task_interface.cpp index d26f8a7..99dd5f4 100644 --- a/src/actsim_agent/task_interface.cpp +++ b/src/actsim_agent/task_interface.cpp @@ -117,6 +117,54 @@ std::unique_ptr TaskInterface::pop_finished(bool& empty) { return task; } +bool TaskInterface::search_and_increment(db::uuid_t id, std::string& design) { + std::lock_guard lock (this->designs_mutex); + + // make sure the requested design is in the list of available designs + if (this->designs.find(id) == this->designs.end()) return false; + + std::pair& design_entry = designs[id]; + + // if so, increment its reference counters + ++design_entry.first; + + // set the design parameter to the actual design information + design = design_entry.second; + return true; +} + +void TaskInterface::decrement(db::uuid_t id) { + std::lock_guard lock (this->designs_mutex); + + // make sure the requested design is in the list of available designs + if (this->designs.find(id) == this->designs.end()) return; + + std::pair& design_entry = designs[id]; + + // if so, decrement its reference counters + --design_entry.first; + + // if the reference counter hit 0, erase the design entry from the list + // of available designs + if (design_entry.first == 0) { + this->designs.erase(id); + } +} + +void TaskInterface::store(db::uuid_t id, std::string& design) { + std::lock_guard lock (this->designs_mutex); + + // make sure the design isn't already in the list of design entries + // if it is, just increment its reference counter + if (this->designs.find(id) != this->designs.end()) { + ++(this->designs[id]).first; + return; + } + + // otherwise, create a new entry for this design + this->designs[id] = {1, design}; +} + size_t TaskInterface::get_buffer_space() { std::lock_guard lock(this->fresh_queue_mutex); return this->buffer_size - this->fresh_queue.size(); diff --git a/src/cli_util.cpp b/src/cli_util.cpp index 6acf542..1309a64 100644 --- a/src/cli_util.cpp +++ b/src/cli_util.cpp @@ -23,7 +23,6 @@ #include #include -#include "db_client.hpp" #include "util.h" #include "cli_util.hpp" diff --git a/src/db_lib/CMakeLists.txt b/src/db_lib/CMakeLists.txt deleted file mode 100644 index d3588eb..0000000 --- a/src/db_lib/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ - -include_directories(../../include) -include_directories(../../include/db_lib) - -file( - GLOB db_lib_SRC - "*.cpp" -) - -add_library( - actsim-agent-db-lib - STATIC - ${db_lib_SRC} -) \ No newline at end of file diff --git a/src/db_lib/db_client.cpp b/src/db_lib/db_client.cpp deleted file mode 100644 index ab0be5f..0000000 --- a/src/db_lib/db_client.cpp +++ /dev/null @@ -1,219 +0,0 @@ - -/************************************************************************* - * - * Copyright (c) 2023 Fabian Posch - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - ************************************************************************** - */ - - -#include -#include "util.h" -#include "db_client.hpp" - -namespace db { - -using namespace std; - -string hostname; - -bool connected = false; - - -Connection::Connection( - db_credentials_t& credentials, - std::function setup -) : setup_function(move(setup)) { - this->db_credentials = credentials; -} - -Connection::Connection(db_credentials_t& credentials) { - this->db_credentials = credentials; -} - -Connection::~Connection() { - if (c != nullptr && c->is_open()) c->close(); -} - -bool Connection::connect() { - bool connection_established = false; - - for (int i = 0; i < MAX_CON_RETRIES; i++) { - try { - // create the connection object - this->c = new pqxx::connection( - "host=" + db_credentials.server + " " - "port=" + std::to_string(db_credentials.port) + " " - "user=" + db_credentials.uname + " " - "password=" + db_credentials.pwd + " " - "dbname=" + db_credentials.dbase - ); - - // make sure the database actually has the version we need - pqxx::work txn(*(this->c)); - - auto db_info = txn.exec1("SELECT * FROM info;"); - txn.commit(); - - if (db_info["db_version"].as() != this->db_credentials.version) { - this->disconnect(); - cerr << "Error: Unsupported database version! Command expects "; - cerr << this->db_credentials.version; - cerr << ", server provides " << db_info["db_version"].as() << "!" << endl; - return false; - } - - if (this->setup_function != nullptr) { - // execute the initialization function - this->setup_function(c); - } - - connection_established = true; - - } catch (const exception &e) { - cerr << "Error: Could not connect to database:" << endl; - cerr << e.what() << endl; - } - } - - return connection_established; -} - -bool Connection::ensure_connected() { - if (c == nullptr || !c->is_open()) { - c->close(); - return connect(); - } - return true; -} - -void Connection::disconnect() { - if (c != nullptr && c->is_open()) c->close(); -} - -bool Connection::prepare_statements(vector> statements) { - - try { - for (auto statement : statements) { - this->c->prepare(statement.first, statement.second); - } - } catch (const exception &e) { - cerr << "Error: Could not prepare statements!" << endl; - return false; - } - - return true; -} - -bool Connection::prepare_statement(std::string name, std::string statement) { - - try { - this->c->prepare(name, statement); - } catch (const exception &e) { - cerr << "Error: Could not prepare statements!" << endl; - return false; - } - - return true; -} - -bool Connection::unprepare_statement(std::string name) { - - auto unprepare_statement_lambda = [] (pqxx::work* txn, std::string statement) { - txn->exec0("DEALLOCATE " + statement + ";"); - }; - - std::function unprepare_statement_func = unprepare_statement_lambda; - - return this->send_request(&unprepare_statement_func, name); -} - -int Connection::find_job(std::string p_name, std::string *f_name) { - auto check_job_ids_lambda = [](pqxx::work *txn, int *ret, std::string p_name, std::string *f_name) { - pqxx::result res {txn->exec("SELECT id FROM jobs;")}; - - *ret = 0; - - for (auto row : res) { - // check if the ID starts with the partial name we've been given - if (row["id"].as().rfind(p_name, 0) == 0) { - // make sure we haven't found it before - if (*ret == 0) { - *ret = 1; - *f_name = row["id"].as(); - } else { - // guess the partial name is ambiguous - *ret = -1; - // we've already seen two, we don't need more - return; - } - } - } - }; - - std::function check_job_ids_func = check_job_ids_lambda; - - DEBUG_PRINT("Sending request..."); - - int ret; - if (!this->send_request(&check_job_ids_func, &ret, p_name, f_name)) { - std::cerr << "Error: Could not fetch job IDs from database!" << std::endl; - return 1; - } - - DEBUG_PRINT("Request complete."); - - return ret; - -} - -JobStatusType Connection::get_job_status(std::string job) { - auto get_jstatus_lambda = [](pqxx::work *txn, std::string job, JobStatusType *status) { - - try { - pqxx::row res {txn->exec1("SELECT job_status FROM jobs WHERE id='" + job + "';")}; - *status = convert_to_job_status(res["job_status"].as()); - } catch (pqxx::unexpected_rows& e) { - std::cerr << "Error: Fetching job returned nothing or too many rows!" << std::endl; - *status = JobStatusType::UNKNOWN; - } - - }; - - std::function get_jstatus_func = get_jstatus_lambda; - - DEBUG_PRINT("Sending request..."); - - JobStatusType status; - if (!this->send_request(&get_jstatus_func, job, &status)) { - std::cerr << "Error: Could not fetch job status from database!" << std::endl; - return JobStatusType::UNKNOWN; - } - - DEBUG_PRINT("Request complete."); - - return status; - -} - -JobStatusType Connection::get_task_status(db::uuid_t) { - std::cout << "JOB STATUS called, implement me pls" << std::endl; - return JobStatusType::IN_PROGRESS; -} - -} diff --git a/src/db_lib/task.cpp b/src/db_lib/task.cpp deleted file mode 100644 index 304e14c..0000000 --- a/src/db_lib/task.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/************************************************************************* - * - * Copyright (c) 2023 Fabian Posch - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - ************************************************************************** - */ - - -#include -#include "task.hpp" - - -Task::Task (db::uuid_t task_uuid, - std::string job_id, - TaskStatusType status, - TaskTypeType type, - bool is_reference, - db::uuid_t reference_uuid, - float max_plf, - TaskErrorType error, - std::string sim_log - ) -{ - this->task_uuid = task_uuid; - this->job_id_ = job_id; - this->status_ = status; - this->task_type_ = type; - this->is_reference_ = is_reference; - this->reference_uuid_ = reference_uuid; - this->max_plf_ = max_plf; - this->error_ = error; - this->sim_log_ = sim_log; -} - -Task::Task (db::uuid_t task_uuid, - std::string job_id, - TaskTypeType type, - bool is_reference, - db::uuid_t reference_uuid, - float max_plf - ) -{ - this->task_uuid = task_uuid; - this->job_id_ = job_id; - this->task_type_ = type; - this->is_reference_ = is_reference; - this->reference_uuid_ = reference_uuid; - this->max_plf_ = max_plf; -} - - -/** - * @brief Convert from pqxx response string to JobStatusType - * - * @param type_string Type returned by pqxx in string form. - * @return JobStatusType - */ -JobStatusType convert_to_job_status(std::string status_string) { - JobStatusType status = JobStatusType::UNKNOWN; - - for (auto pair : job_status_type_st) { - if (pair.second == status_string) { - status = pair.first; - break; - } - } - - if (status == JobStatusType::UNKNOWN) { - std::cerr << "Warning: Job status type unknown or could not be parsed. Given status was " << status_string << std::endl; - } - - return status; -} - - -/** - * @brief Convert from pqxx response string to TaskTypeType - * - * @param type_string Type returned by pqxx in string form. - * @return TaskTypeType - */ -TaskTypeType convert_to_task_type(std::string type_string) { - if (type_string == "SINGLE") { - return TaskTypeType::SINGLE; - } else if (type_string == "MULTI_COV") { - return TaskTypeType::MULTI_COV; - } else { - std::cerr << "Error: Could not parse task type \"" << type_string << "\"" << std::endl; - return TaskTypeType::UNKNOWN; - } -} - - -/** - * @brief Convert from pqxx response string to TaskErrorType - * - * @param error_string Error returned by pqxx in string form. - * @return TaskErrorType - */ -TaskErrorType convert_to_task_error(std::string error_string) { - if (error_string == "NONE") { - return TaskErrorType::NONE; - } else if (error_string == "SYNTAX") { - return TaskErrorType::SYNTAX; - } else if (error_string == "VALUE") { - return TaskErrorType::VALUE; - } else if (error_string == "CODE") { - return TaskErrorType::CODE; - } else if (error_string == "METASTABLE") { - return TaskErrorType::METASTABLE; - } else if (error_string == "TIMING") { - return TaskErrorType::TIMING; - } else if (error_string == "DEADLOCK") { - return TaskErrorType::DEADLOCK; - } else { - std::cerr << "Error: Could not parse task error \"" << error_string << "\"" << std::endl; - return TaskErrorType::UNKNOWN; - } -} - - -/** - * @brief Convert from pqxx response string to TaskStatusType - * - * @param status_string Status returned by pqxx in string form. - * @return TaskStatusType - */ -TaskStatusType convert_to_task_status(std::string status_string) { - if (status_string == "OPEN") { - return TaskStatusType::OPEN; - } else if (status_string == "IN_PROGRESS") { - return TaskStatusType::IN_PROGRESS; - } else if (status_string == "DONE") { - return TaskStatusType::DONE; - } else { - std::cerr << "Error: Could not parse task status \"" << status_string << "\"" << std::endl; - return TaskStatusType::UNKNOWN; - } -} - diff --git a/src/main.cpp b/src/main.cpp index 87e1363..44e60aa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include "cli_util.hpp" #include "util.h" #include "main.hpp"