From c321f17f1f07fa55378e9c4b992a6a5da465e355 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Fri, 29 Aug 2025 16:30:30 +0000 Subject: [PATCH 01/10] refactor --- src/common/capio/env.hpp | 2 + src/common/capio/filesystem.hpp | 2 +- src/common/capio/logger.hpp | 4 +- src/common/capio/shm.hpp | 10 +- src/server/CMakeLists.txt | 2 + .../capio-cl-engine/capio_cl_engine.hpp | 485 ------------------ src/server/capio-cl-engine/json_parser.hpp | 485 ------------------ src/server/capio_server.cpp | 3 + src/server/client-manager/client_manager.hpp | 3 + src/server/client-manager/handlers/write.hpp | 2 +- .../client-manager/request_handler_engine.hpp | 4 +- .../capio-cl-engine/capio_cl_engine.hpp | 92 ++++ .../include/capio-cl-engine/json_parser.hpp | 42 ++ src/server/src/capio_cl_engine.cpp | 434 ++++++++++++++++ src/server/src/json_parser.cpp | 451 ++++++++++++++++ src/server/utils/configuration.hpp | 1 + 16 files changed, 1041 insertions(+), 981 deletions(-) delete mode 100644 src/server/capio-cl-engine/capio_cl_engine.hpp delete mode 100644 src/server/capio-cl-engine/json_parser.hpp create mode 100644 src/server/include/capio-cl-engine/capio_cl_engine.hpp create mode 100644 src/server/include/capio-cl-engine/json_parser.hpp create mode 100644 src/server/src/capio_cl_engine.cpp create mode 100644 src/server/src/json_parser.cpp diff --git a/src/common/capio/env.hpp b/src/common/capio/env.hpp index f04d3c759..6f419da7f 100644 --- a/src/common/capio/env.hpp +++ b/src/common/capio/env.hpp @@ -9,6 +9,8 @@ #include +#include + #include "logger.hpp" #include "syscall.hpp" diff --git a/src/common/capio/filesystem.hpp b/src/common/capio/filesystem.hpp index 3269b21dc..8c28e0baa 100644 --- a/src/common/capio/filesystem.hpp +++ b/src/common/capio/filesystem.hpp @@ -16,7 +16,7 @@ #include -std::filesystem::path get_parent_dir_path(const std::filesystem::path &file_path) { +inline std::filesystem::path get_parent_dir_path(const std::filesystem::path &file_path) { START_LOG(capio_syscall(SYS_gettid), "call(file_path=%s)", file_path.c_str()); if (file_path == file_path.root_path()) { return file_path; diff --git a/src/common/capio/logger.hpp b/src/common/capio/logger.hpp index c9fa8539f..3de480fb7 100644 --- a/src/common/capio/logger.hpp +++ b/src/common/capio/logger.hpp @@ -21,7 +21,7 @@ inline bool continue_on_error = false; // change behaviour of ERR_EXIT to contin #ifndef __CAPIO_POSIX #include -thread_local std::ofstream logfile; // if building for server, self-contained logfile +inline thread_local std::ofstream logfile; // if building for server, self-contained logfile inline std::string log_master_dir_name = CAPIO_DEFAULT_LOG_FOLDER; inline std::string logfile_prefix = CAPIO_SERVER_DEFAULT_LOG_FILE_PREFIX; #else @@ -323,7 +323,7 @@ class Logger { #define ERR_EXIT(message, ...) \ log.log(message, ##__VA_ARGS__); \ if (!continue_on_error) { \ - char tmp_buf[1024]; \ + char tmp_buf[5120]; \ sprintf(tmp_buf, message, ##__VA_ARGS__); \ char node_name[HOST_NAME_MAX]{0}; \ gethostname(node_name, HOST_NAME_MAX); \ diff --git a/src/common/capio/shm.hpp b/src/common/capio/shm.hpp index bef292451..b18097479 100644 --- a/src/common/capio/shm.hpp +++ b/src/common/capio/shm.hpp @@ -93,9 +93,9 @@ class CapioShmCanary { } }; -CapioShmCanary *shm_canary; +inline CapioShmCanary *shm_canary; -void *create_shm(const std::string &shm_name, const long int size) { +inline void *create_shm(const std::string &shm_name, const long int size) { START_LOG(capio_syscall(SYS_gettid), "call(shm_name=%s, size=%ld)", shm_name.c_str(), size); // if we are not creating a new object, mode is equals to 0 @@ -116,7 +116,7 @@ void *create_shm(const std::string &shm_name, const long int size) { return p; } -auto get_shm_size(int shm_fd, const char *shm_name) { +inline auto get_shm_size(int shm_fd, const char *shm_name) { START_LOG(capio_syscall(SYS_gettid), "call(fd=%ld)", shm_fd); struct stat sb = {0}; /* Open existing object */ @@ -141,7 +141,7 @@ auto get_shm_size(int shm_fd, const char *shm_name) { return sb.st_size; } -void *get_shm(const std::string &shm_name) { +inline void *get_shm(const std::string &shm_name) { START_LOG(capio_syscall(SYS_gettid), "call(shm_name=%s)", shm_name.c_str()); // if we are not creating a new object, mode is equals to 0 @@ -167,7 +167,7 @@ void *get_shm(const std::string &shm_name) { return p; } -void *get_shm_if_exist(const std::string &shm_name) { +inline void *get_shm_if_exist(const std::string &shm_name) { START_LOG(capio_syscall(SYS_gettid), "call(shm_name=%s)", shm_name.c_str()); // if we are not creating a new object, mode is equals to 0 diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index ba3ff0e00..f3eb934af 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -5,6 +5,8 @@ set(TARGET_NAME capio_server) set(TARGET_INCLUDE_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}) set(TARGET_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/capio_server.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/capio_cl_engine.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/json_parser.cpp ) ##################################### diff --git a/src/server/capio-cl-engine/capio_cl_engine.hpp b/src/server/capio-cl-engine/capio_cl_engine.hpp deleted file mode 100644 index adab55430..000000000 --- a/src/server/capio-cl-engine/capio_cl_engine.hpp +++ /dev/null @@ -1,485 +0,0 @@ -#ifndef CAPIO_ENGINE_HPP -#define CAPIO_ENGINE_HPP - -#include "client-manager/client_manager.hpp" -#include - -#include "capio/filesystem.hpp" -/** - * @brief Class that stores the parsed configuration of the CAPIO-CL configuration file. - * - */ -class CapioCLEngine { - friend class CapioFileManager; - - std::unordered_map, // Vector for producers [0] - std::vector, // Vector for consumers [1] - std::string, // commit rule [2] - std::string, // fire_rule [3] - bool, // permanent [4] - bool, // exclude [5] - bool, // is_file (false = directory) [6] - int, // commit on close number [7] - long, // directory file count [8] - std::vector, // File dependencies [9] - std::regex, // Regex to match globs [10] - bool>> // Store File on FS. true = memory [11] - _locations; - - static std::string truncateLastN(const std::string &str, const std::size_t n) { - return str.length() > n ? "[..] " + str.substr(str.length() - n) : str; - } - - public: - void print() const { - // First message - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON); - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "Composition of expected CAPIO FS: "); - - // Table header lines - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "|============================================================================" - "==========================================================|"); - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "|" + std::string(134, ' ') + "|"); - - { - std::ostringstream oss; - oss << "| Parsed configuration file for workflow: \033[1;36m" - << capio_global_configuration->workflow_name - << std::setw(94 - capio_global_configuration->workflow_name.length()) - << "\033[0m |"; - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, oss.str()); - } - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "|" + std::string(134, ' ') + "|"); - - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "| File color legend: \033[48;5;034m \033[0m File stored in memory" + - std::string(82, ' ') + "|"); - - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "| \033[48;5;172m \033[0m File stored on file system" + - std::string(77, ' ') + "|"); - - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "|============================================================================" - "==========================================================|"); - - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "|======|===================|===================|====================|========" - "============|============|===========|=========|==========|"); - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "| Kind | Filename | Producer step | Consumer step | " - "Commit Rule | Fire Rule | Permanent | Exclude | n_files |"); - - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "|======|===================|===================|====================|========" - "============|============|===========|=========|==========|"); - - // Iterate over _locations - for (auto &itm : _locations) { - std::string color_preamble = - std::get<11>(itm.second) ? "\033[38;5;034m" : "\033[38;5;172m"; - std::string color_post = "\033[0m"; - - std::string name_trunc = truncateLastN(itm.first, 12); - auto kind = std::get<6>(itm.second) ? "F" : "D"; - - std::ostringstream base_line; - base_line << "| " << color_preamble << kind << color_post << " | " << color_preamble - << name_trunc << color_post << std::setfill(' ') - << std::setw(20 - name_trunc.length()) << "| "; - - auto producers = std::get<0>(itm.second); - auto consumers = std::get<1>(itm.second); - auto rowCount = std::max(producers.size(), consumers.size()); - - std::string n_files = std::to_string(std::get<8>(itm.second)); - if (std::get<8>(itm.second) < 1) { - n_files = "N.A."; - } - - for (std::size_t i = 0; i <= rowCount; i++) { - std::ostringstream line; - - if (i == 0) { - line << base_line.str(); - } else { - line << "| | | "; - } - - if (i < producers.size()) { - auto prod1 = truncateLastN(producers.at(i), 12); - line << prod1 << std::setfill(' ') << std::setw(20 - prod1.length()) << " | "; - } else { - line << std::setfill(' ') << std::setw(20) << " | "; - } - - if (i < consumers.size()) { - auto cons1 = truncateLastN(consumers.at(i), 12); - line << " " << cons1 << std::setfill(' ') << std::setw(20 - cons1.length()) - << " | "; - } else { - line << std::setfill(' ') << std::setw(21) << " | "; - } - - if (i == 0) { - std::string commit_rule = std::get<2>(itm.second), - fire_rule = std::get<3>(itm.second); - bool exclude = std::get<4>(itm.second), permanent = std::get<5>(itm.second); - - line << " " << commit_rule << std::setfill(' ') - << std::setw(20 - commit_rule.length()) << " | " << fire_rule - << std::setfill(' ') << std::setw(13 - fire_rule.length()) << " | " - << " " << (permanent ? "YES" : "NO ") << " | " - << (exclude ? "YES" : "NO ") << " | " << n_files - << std::setw(10 - n_files.length()) << " |"; - } else { - line << std::setfill(' ') << std::setw(20) << "|" << std::setfill(' ') - << std::setw(13) << "|" << std::setfill(' ') << std::setw(12) << "|" - << std::setfill(' ') << std::setw(10) << "|" << std::setw(10) << "|"; - } - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, line.str()); - } - - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - "~~~~~~~~~~~~~~~~~~" - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*"); - } - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, ""); - } - - /** - * Check whether the file is contained inside the location, either by direct name or by glob - * @param file - * @return - */ - bool contains(const std::filesystem::path &file) { - START_LOG(gettid(), "call(file=%s)", file.c_str()); - return std::any_of(_locations.begin(), _locations.end(), [&](auto &itm) { - return std::regex_match(file.c_str(), std::get<10>(itm.second)); - }); - } - - void add(std::string &path, std::vector &producers, - std::vector &consumers, const std::string &commit_rule, - const std::string &fire_rule, bool permanent, bool exclude, - const std::vector &dependencies) { - START_LOG(gettid(), "call(path=%s, commit=%s, fire=%s, permanent=%s, exclude=%s)", - path.c_str(), commit_rule.c_str(), fire_rule.c_str(), permanent ? "YES" : "NO", - exclude ? "YES" : "NO"); - - _locations.emplace(path, std::make_tuple(producers, consumers, commit_rule, fire_rule, - permanent, exclude, true, -1, -1, dependencies, - generateCapioRegex(path), false)); - } - - void newFile(const std::string &path) { - START_LOG(gettid(), "call(path=%s)", path.c_str()); - if (_locations.find(path) == _locations.end()) { - std::string commit = CAPIO_FILE_COMMITTED_ON_TERMINATION; - std::string fire = CAPIO_FILE_MODE_UPDATE; - - /* - * Inherit commit and fire rules from LPM directory - * matchSize is used to compute LPM - */ - size_t matchSize = 0; - for (const auto &[filename, data] : _locations) { - if (std::regex_match(path, std::get<10>(data)) && filename.length() > matchSize) { - LOG("Found match with %s", filename.c_str()); - matchSize = filename.length(); - commit = std::get<2>(data); - fire = std::get<3>(data); - } - } - LOG("Adding file %s to _locations with commit=%s, and fire=%s", path.c_str(), - commit.c_str(), fire.c_str()); - _locations.emplace( - path, std::make_tuple(std::vector(), std::vector(), - commit, fire, false, false, true, -1, -1, - std::vector(), generateCapioRegex(path), false)); - } - } - - long getDirectoryFileCount(const std::string &path) { - if (const auto itm = _locations.find(path); itm != _locations.end()) { - return std::get<8>(itm->second); - } - return 0; - } - - void addProducer(const std::string &path, std::string &producer) { - START_LOG(gettid(), "call(path=%s, producer=%s)", path.c_str(), producer.c_str()); - producer.erase(remove_if(producer.begin(), producer.end(), isspace), producer.end()); - newFile(path); - if (const auto itm = _locations.find(path); itm != _locations.end()) { - std::get<0>(itm->second).emplace_back(producer); - } - } - - void addConsumer(const std::string &path, std::string &consumer) { - START_LOG(gettid(), "call(path=%s, consumer=%s)", path.c_str(), consumer.c_str()); - consumer.erase(remove_if(consumer.begin(), consumer.end(), isspace), consumer.end()); - if (const auto itm = _locations.find(path); itm != _locations.end()) { - std::get<1>(itm->second).emplace_back(consumer); - } - } - - void setCommitRule(const std::string &path, const std::string &commit_rule) { - START_LOG(gettid(), "call(path=%s, commit_rule=%s)", path.c_str(), commit_rule.c_str()); - if (const auto itm = _locations.find(path); itm != _locations.end()) { - std::get<2>(itm->second) = commit_rule; - } - } - - std::string getCommitRule(const std::string &path) { - START_LOG(gettid(), "call(path=%s)", path.c_str()); - if (const auto itm = _locations.find(path); itm != _locations.end()) { - LOG("Commit rule: %s", std::get<2>(_locations.at(path)).c_str()); - return std::get<2>(itm->second); - } - - /* - * For caching purpose, each new file is then added to the map if not found, - * with its data being instantiated from the metadata of the most likely matched glob - * TODO: check overhead of this - */ - LOG("No entry found on map. checking globs. Creating new file from globs"); - this->newFile((path)); - LOG("Returning DEFAULT Fire rule for file %s (update)", path.c_str()); - return std::get<2>(_locations.at((path))); - } - - void setFireRule(const std::string &path, const std::string &fire_rule) { - START_LOG(gettid(), "call(path=%s, fire_rule=%s)", path.c_str(), fire_rule.c_str()); - if (const auto itm = _locations.find(path); itm != _locations.end()) { - std::get<3>(itm->second) = fire_rule; - } - } - - bool isFirable(const std::string &path) { - START_LOG(gettid(), "call(path=%s)", path.c_str()); - if (const auto itm = _locations.find(path); itm != _locations.end()) { - LOG("Fire rule for file %s is %s", path.c_str(), std::get<3>(itm->second).c_str()); - return std::get<3>(itm->second) == CAPIO_FILE_MODE_NO_UPDATE; - } - /* - * For caching purpose, each new file is then added to the map if not found, - * with its data being instantiated from the metadata of the most likely matched glob - * TODO: check overhead of this - */ - LOG("No entry found on map. checking globs. Creating new file from globs"); - this->newFile((path)); - LOG("Fire rule for file %s is %s", path.c_str(), - std::get<3>(_locations.at((path))).c_str()); - return std::get<3>(_locations.at((path))) == CAPIO_FILE_MODE_NO_UPDATE; - } - - void setPermanent(const std::string &path, bool value) { - START_LOG(gettid(), "call(path=%s, value=%s)", path.c_str(), value ? "true" : "false"); - if (const auto itm = _locations.find(path); itm != _locations.end()) { - std::get<4>(itm->second) = value; - } - } - - void setExclude(const std::string &path, const bool value) { - START_LOG(gettid(), "call(path=%s, value=%s)", path.c_str(), value ? "true" : "false"); - if (const auto itm = _locations.find(path); itm != _locations.end()) { - std::get<5>(itm->second) = value; - } - } - - void setDirectory(const std::string &path) { - START_LOG(gettid(), "call(path=%s)", path.c_str()); - if (const auto itm = _locations.find(path); itm != _locations.end()) { - std::get<6>(itm->second) = false; - } - } - - void setFile(const std::string &path) { - START_LOG(gettid(), "call(path=%s)", path.c_str()); - if (const auto itm = _locations.find(path); itm != _locations.end()) { - std::get<6>(itm->second) = true; - } - } - - bool isFile(const std::string &path) const { - if (const auto itm = _locations.find(path); itm != _locations.end()) { - return std::get<6>(itm->second); - } - return false; - } - - bool isDirectory(const std::string &path) const { - START_LOG(gettid(), "call(path=%s)", path.c_str()); - return !isFile(path); - } - - void setCommitedNumber(const std::string &path, const int num) { - START_LOG(gettid(), "call(path=%s, num=%ld)", path.c_str(), num); - if (const auto itm = _locations.find(path); itm != _locations.end()) { - std::get<7>(itm->second) = num; - } - } - - void setDirectoryFileCount(const std::string &path, long num) { - START_LOG(gettid(), "call(path=%s, num=%ld)", path.c_str(), num); - if (const auto itm = _locations.find(path); itm != _locations.end()) { - std::get<8>(itm->second) = num; - } - } - - void remove(const std::string &path) { - START_LOG(gettid(), "call(path=%s)", path.c_str()); - _locations.erase(path); - } - - // TODO: return vector - std::vector producers(const std::string &path) { - START_LOG(gettid(), "call(path=%s)", path.c_str()); - if (const auto itm = _locations.find(path); itm != _locations.end()) { - return std::get<0>(itm->second); - } - return {}; - } - - // TODO: return vector - std::vector consumers(const std::string &path) { - START_LOG(gettid(), "call(path=%s)", path.c_str()); - if (const auto itm = _locations.find(path); itm != _locations.end()) { - return std::get<1>(itm->second); - } - return {}; - } - - bool isProducer(const std::string &path, const pid_t pid) { - START_LOG(gettid(), "call(path=%s, pid=%ld", path.c_str(), pid); - - const auto app_name = client_manager->get_app_name(pid); - LOG("App name for tid %d is %s", pid, app_name.c_str()); - - // check for exact entry - if (const auto itm = _locations.find(path); itm != _locations.end()) { - LOG("Found exact match for path"); - std::vector producers = std::get<0>(itm->second); - DBG(gettid(), [&](const std::vector &arr) { - for (auto elem : arr) { - LOG("producer: %s", elem.c_str()); - } - }(producers)); - return std::find(producers.begin(), producers.end(), app_name) != producers.end(); - } - LOG("No exact match found in locations. checking for globs"); - // check for glob - for (const auto &[k, entry] : _locations) { - if (std::regex_match(path, std::get<10>(entry))) { - LOG("Found possible glob match"); - std::vector producers = std::get<0>(entry); - DBG(gettid(), [&](const std::vector &arr) { - for (auto itm : arr) { - LOG("producer: %s", itm.c_str()); - } - }(producers)); - return std::find(producers.begin(), producers.end(), app_name) != producers.end(); - } - } - LOG("No match has been found"); - return false; - } - - void setFileDeps(const std::filesystem::path &path, - const std::vector &dependencies) { - START_LOG(gettid(), "call()"); - if (dependencies.empty()) { - return; - } - if (_locations.find(path) == _locations.end()) { - this->newFile(path); - } - std::get<9>(_locations.at(path)) = dependencies; - for (const auto &itm : dependencies) { - LOG("Creating new fie (if it exists) for path %s", itm.c_str()); - newFile(itm); - } - } - - int getCommitCloseCount(std::filesystem::path::iterator::reference path) const { - START_LOG(gettid(), "call(path=%s)", path.c_str()); - int count = 0; - if (const auto itm = _locations.find(path); itm != _locations.end()) { - count = std::get<7>(itm->second); - } - LOG("Expected number on close to commit file: %d", count); - return count; - }; - - // todo fix leak - std::vector get_file_deps(const std::filesystem::path &path) { - if (const auto itm = _locations.find(path); itm != _locations.end()) { - return std::get<9>(itm->second); - } - return {}; - } - - void setStoreFileInMemory(const std::filesystem::path &path) { - this->newFile(path); - std::get<11>(_locations.at(path)) = true; - } - - void setStoreFileInFileSystem(const std::filesystem::path &path) { - this->newFile(path); - std::get<11>(_locations.at(path)) = false; - } - - bool storeFileInMemory(const std::filesystem::path &path) { - if (const auto itm = _locations.find(path); itm != _locations.end()) { - return std::get<11>(itm->second); - } - return false; - } - - std::vector getFileToStoreInMemory() { - START_LOG(gettid(), "call()"); - std::vector files; - - for (const auto &[path, file] : _locations) { - if (std::get<11>(file)) { - files.push_back(path); - } - } - - return files; - } - - auto get_home_node(const std::string &path) { - // TODO: understand here how to get the home node policy. - START_LOG(gettid(), "call(path=%s)", path.c_str()); - if (const auto location = _locations.find(path); location == _locations.end()) { - LOG("No rule for home node. Returning create home node"); - return capio_global_configuration->node_name; - } else { - LOG("Found location entry"); - } - return capio_global_configuration->node_name; - } - - protected: - const auto *getLocations() const { return &_locations; } -}; - -inline CapioCLEngine *capio_cl_engine; -#endif // CAPIO_ENGINE_HPP diff --git a/src/server/capio-cl-engine/json_parser.hpp b/src/server/capio-cl-engine/json_parser.hpp deleted file mode 100644 index f343f5871..000000000 --- a/src/server/capio-cl-engine/json_parser.hpp +++ /dev/null @@ -1,485 +0,0 @@ -#ifndef JSON_PARSER_HPP -#define JSON_PARSER_HPP -#include "capio/constants.hpp" - -#include - -/** - * @brief Contains the code to parse a JSON based CAPIO-CL configuration file - * - */ -class JsonParser { - /** - * @brief Check if a string is a representation of a integer number - * - * @param s - * @return true - * @return false - */ - static inline bool is_int(const std::string &s) { - START_LOG(gettid(), "call(%s)", s.c_str()); - bool res = false; - if (!s.empty()) { - char *p; - strtol(s.c_str(), &p, 10); - res = *p == 0; - } - return res; - } - - /** - * @brief compare two paths - * - * @param path - * @param base - * @return true if path is a subdirectory of base - * @return false otherwise - */ - static inline bool first_is_subpath_of_second(const std::filesystem::path &path, - const std::filesystem::path &base) { - const auto mismatch_pair = - std::mismatch(path.begin(), path.end(), base.begin(), base.end()); - return mismatch_pair.second == base.end(); - } - - public: - /** - * @brief Perform the parsing of the capio_server configuration file - * - * @param source - * @return CapioCLEngine instance with the information provided by the config file - */ - static CapioCLEngine *parse(const std::filesystem::path &source, - const std::filesystem::path resolve_prexix) { - auto locations = new CapioCLEngine(); - START_LOG(gettid(), "call(config_file='%s')", source.c_str()); - - /* - * Before here a call to get_capio_dir() was issued. However, to support multiple CAPIO_DIRs - * there is no difference to use the wildcard * instead of CAPIO_DIR. This is true as only - * paths relative to the capio_dir directory are forwarded to the server, and as such, there - * is no difference that to create a ROOT dir equal to CAPIO_DIR compared to the wildcard *. - */ - locations->newFile("*"); - locations->setDirectory("*"); - if (capio_global_configuration->StoreOnlyInMemory) { - locations->setStoreFileInMemory("*"); - } - - if (source.empty()) { - return locations; - } - - simdjson::ondemand::parser parser; - simdjson::padded_string json; - simdjson::ondemand::document entries; - simdjson::ondemand::array input_stream, output_stream, streaming, permanent_files, - exclude_files, storage_memory, storage_fs; - simdjson::ondemand::object storage_section; - simdjson::error_code error; - - try { - json = simdjson::padded_string::load(source.c_str()); - } catch (const simdjson::simdjson_error &e) { - std::cerr << CAPIO_LOG_SERVER_CLI_LEVEL_ERROR << " [ " - << capio_global_configuration->node_name << " ] " - << "Exception thrown while opening config file: " << e.what() << std::endl; - LOG("Exception thrown while opening config file: %s", e.what()); - ERR_EXIT("Exception thrown while opening config file: %s", e.what()); - } - - entries = parser.iterate(json); - std::string_view wf_name; - error = entries["name"].get_string().get(wf_name); - if (error) { - ERR_EXIT("Error: workflow name is mandatory"); - } - capio_global_configuration->workflow_name = std::string(wf_name); - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "Parsing configuration for workflow: " + - capio_global_configuration->workflow_name); - - LOG("Parsing configuration for workflow: %s", - std::string(capio_global_configuration->workflow_name).c_str()); - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, ""); - - auto io_graph = entries["IO_Graph"]; - - for (auto app : io_graph) { - std::string_view app_name; - error = app["name"].get_string().get(app_name); - if (error) { - ERR_EXIT("Error: app name is mandatory"); - } - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "Parsing config for app " + std::string(app_name)); - LOG("Parsing config for app %s", std::string(app_name).c_str()); - - if (app["input_stream"].get_array().get(input_stream)) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, - "No input_stream section found for app " + std::string(app_name)); - ERR_EXIT("No input_stream section found for app %s", std::string(app_name).c_str()); - } else { - for (auto itm : input_stream) { - std::filesystem::path file(itm.get_string().take_value()); - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "Found file " + std::string(file)); - - if (file.is_relative()) { - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "Path : " + std::string(file) + - " IS RELATIVE! using cwd() of server to compute abs path."); - file = resolve_prexix / file; - } - std::string appname(app_name); - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "Path : " + std::string(file) + - " added to app: " + std::string(app_name)); - - locations->newFile(file.c_str()); - locations->addConsumer(file, appname); - } - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "Completed input_stream parsing for app: " + std::string(app_name)); - - LOG("Completed input_stream parsing for app: %s", std::string(app_name).c_str()); - } - - if (app["output_stream"].get_array().get(output_stream)) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, - "No output_stream section found for app " + std::string(app_name)); - ERR_EXIT("No output_stream section found for app %s", - std::string(app_name).c_str()); - } else { - for (auto itm : output_stream) { - std::filesystem::path file(itm.get_string().take_value()); - if (file.is_relative()) { - if (file.is_relative()) { - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "Path : " + std::string(file) + - " IS RELATIVE! using cwd() of server to compute abs path."); - file = resolve_prexix / file; - } - } - std::string appname(app_name); - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "Adding file: " + std::string(file) + " to app: " + appname); - - locations->newFile(file); - locations->addProducer(file, appname); - } - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "Completed output_stream parsing for app: " + std::string(app_name)); - LOG("Completed output_stream parsing for app: %s", std::string(app_name).c_str()); - } - - // PARSING STREAMING FILES - if (app["streaming"].get_array().get(streaming)) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "No Streaming section found for app " + std::string(app_name)); - LOG("No streaming section found for app: %s", std::string(app_name).c_str()); - } else { - LOG("Began parsing streaming section for app %s", std::string(app_name).c_str()); - for (auto file : streaming) { - std::string_view committed, mode, commit_rule; - std::vector streaming_names; - std::vector file_deps; - long int n_close = -1; - long n_files = -1, batch_size; - bool is_file = true; - - simdjson::ondemand::array name; - error = file["name"].get_array().get(name); - if (error || name.is_empty()) { - error = file["dirname"].get_array().get(name); - if (error || name.is_empty()) { - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, - "error: either name or dirname in streaming section is required"); - ERR_EXIT( - "error: either name or dirname in streaming section is required"); - } - is_file = false; - } - - for (auto item : name) { - std::string_view elem = item.get_string().value(); - LOG("Found name: %s", std::string(elem).c_str()); - std::filesystem::path file_fs(elem); - if (file_fs.is_relative()) { - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "Path : " + std::string(file_fs) + - " IS RELATIVE! using cwd() of server to compute abs path."); - file_fs = resolve_prexix / file_fs; - } - LOG("Saving file %s to locations", std::string(elem).c_str()); - streaming_names.emplace_back(elem); - } - - // PARSING COMMITTED - error = file["committed"].get_string().get(committed); - if (error) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, - "commit rule is mandatory in streaming section"); - ERR_EXIT("error commit rule is mandatory in streaming section"); - } else { - auto pos = committed.find(':'); - if (pos != std::string::npos) { - commit_rule = committed.substr(0, pos); - std::string count_str(committed.substr(pos + 1, committed.length())); - if (!is_int(count_str)) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, - "commit rule on_close/n_files invalid number"); - ERR_EXIT("error commit rule on_close invalid number: !is_int()"); - } - - if (commit_rule == CAPIO_FILE_COMMITTED_ON_CLOSE) { - n_close = std::stol(count_str); - } else if (commit_rule == CAPIO_FILE_COMMITTED_N_FILES) { - n_files = std::stol(count_str); - // TODO: use internally n_files. for now, we use on_close as default - commit_rule = CAPIO_FILE_COMMITTED_ON_CLOSE; - } else { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, - "Invalid commit rule: " + std::string(commit_rule)); - ERR_EXIT("error commit rule: %s", std::string(commit_rule).c_str()); - } - } else { - commit_rule = committed; - } - } - - // check for committed on file: - if (commit_rule == CAPIO_FILE_COMMITTED_ON_FILE) { - simdjson::ondemand::array file_deps_tmp; - error = file["file_deps"].get_array().get(file_deps_tmp); - - if (error) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, - "commit rule is on_file but no file_deps section found"); - ERR_EXIT("commit rule is on_file but no file_deps section found"); - } - - std::string_view name_tmp; - for (auto itm : file_deps_tmp) { - name_tmp = itm.get_string().value(); - std::filesystem::path computed_path(name_tmp); - if (computed_path.is_relative()) { - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "Path : " + std::string(computed_path) + - " IS RELATIVE! using cwd() of server to compute abs path."); - computed_path = resolve_prexix / computed_path; - } - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "Adding file: " + std::string(computed_path) + - " to file dependencies: "); - - file_deps.emplace_back(computed_path); - } - } - - LOG("Committed: %s", std::string(committed).c_str()); - // END PARSING COMMITTED - - error = file["mode"].get_string().get(mode); - if (error) { - mode = CAPIO_FILE_MODE_UPDATE; - } - LOG("Mode: %s", std::string(mode).c_str()); - - if (n_files == -1) { - error = file["n_files"].get_int64().get(n_files); - if (error && n_files != -1) { - n_files = -1; - } - } - LOG("n_files: %d", n_files); - - error = file["batch_size"].get_int64().get(batch_size); - if (error) { - batch_size = 0; - } - LOG("batch_size: %d", batch_size); - for (auto path : streaming_names) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "Updating metadata for path: " + std::string(path)); - - if (path.is_relative()) { - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "Path : " + std::string(path) + - " IS RELATIVE! using cwd() of server to compute abs path."); - path = resolve_prexix / path; - } - LOG("path: %s", path.c_str()); - - // TODO: check for globs - std::string commit(commit_rule), firerule(mode); - if (n_files != -1) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "Setting path: " + std::string(path) + " n_files to " + - std::to_string(n_files)); - locations->setDirectoryFileCount(path, n_files); - } - - is_file ? locations->setFile(path) : locations->setDirectory(path); - locations->setCommitRule(path, commit); - locations->setFireRule(path, firerule); - locations->setCommitedNumber(path, n_close); - locations->setFileDeps(path, file_deps); - } - } - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "completed parsing of streaming section for app: " + - std::string(app_name)); - LOG("completed parsing of streaming section for app: %s", - std::string(app_name).c_str()); - } // END PARSING STREAMING FILES - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, ""); - } // END OF APP MAIN LOOPS - LOG("Completed parsing of io_graph app main loops"); - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "Completed parsing of io_graph"); - LOG("Completed parsing of io_graph"); - - if (entries["permanent"].get_array().get(permanent_files)) { - // PARSING PERMANENT FILES - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "No permanent section found for workflow: " + - capio_global_configuration->workflow_name); - LOG("No permanent section found for workflow: %s", - capio_global_configuration->workflow_name.c_str()); - } else { - for (auto file : permanent_files) { - std::string_view name; - error = file.get_string().get(name); - if (error) { - ERR_EXIT("error name for permanent section is mandatory"); - } - LOG("Permanent name: %s", std::string(name).c_str()); - - std::filesystem::path path(name); - - if (path.is_relative()) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "Path : " + std::string(path) + - " IS RELATIVE! using cwd() of server to compute abs path."); - path = resolve_prexix / path; - } - - // TODO: check for globs - // TODO: improve this - locations->setPermanent(name.data(), true); - } - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "Completed parsing of permanent files"); - LOG("Completed parsing of permanent files"); - } // END PARSING PERMANENT FILES - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, ""); - - if (entries["exclude"].get_array().get(exclude_files)) { - // PARSING PERMANENT FILES - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "No exclude section found for workflow: " + - capio_global_configuration->workflow_name); - LOG("No exclude section found for workflow: %s", - std::string(capio_global_configuration->workflow_name).c_str()); - } else { - for (auto file : exclude_files) { - std::string_view name; - error = file.get_string().get(name); - if (error) { - ERR_EXIT("error name for exclude section is mandatory"); - } - LOG("exclude name: %s", std::string(name).c_str()); - - std::filesystem::path path(name); - - if (path.is_relative()) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "Path : " + std::string(path) + - " IS RELATIVE! using cwd() of server to compute abs path."); - path = resolve_prexix / path; - } - // TODO: check for globs - locations->setExclude(path, true); - } - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "Completed parsing of exclude files"); - LOG("Completed parsing of exclude files"); - } // END PARSING PERMANENT FILES - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, ""); - - auto home_node_policies = entries["home_node_policy"].error(); - if (!home_node_policies) { - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "Warning: capio does not support home node policies yet! skipping section "); - } - - if (entries["storage"].get_object().get(storage_section)) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "No storage section found for workflow: " + - capio_global_configuration->workflow_name); - LOG("No storage section found for workflow: %s", - std::string(capio_global_configuration->workflow_name).c_str()); - } else { - if (storage_section["memory"].get_array().get(storage_memory)) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "No files listed in memory storage section for workflow: " + - capio_global_configuration->workflow_name); - LOG("No files listed in memory storage section for workflow: %s", - std::string(capio_global_configuration->workflow_name).c_str()); - } else { - for (auto file : storage_memory) { - std::string_view file_str; - [[maybe_unused]] const auto error = file.get_string().get(file_str); - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "Setting file " + - std::string(file_str) + - " to be stored in memory"); - locations->setStoreFileInMemory(file_str); - } - } - - if (storage_section["fs"].get_array().get(storage_fs)) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "No files listed in fs storage section for workflow: " + - capio_global_configuration->workflow_name); - LOG("No files listed in fs storage section for workflow: %s", - std::string(capio_global_configuration->workflow_name).c_str()); - } else { - for (auto file : storage_fs) { - std::string_view file_str; - [[maybe_unused]] const auto error = file.get_string().get(file_str); - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "Setting file " + std::string(file_str) + - " to be stored on file system"); - locations->setStoreFileInFileSystem(file_str); - } - } - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, - "Completed parsing of memory storage directives"); - } - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, ""); - - return locations; - } -}; - -#endif // JSON_PARSER_HPP \ No newline at end of file diff --git a/src/server/capio_server.cpp b/src/server/capio_server.cpp index 3162239dd..564fe54dc 100644 --- a/src/server/capio_server.cpp +++ b/src/server/capio_server.cpp @@ -39,6 +39,9 @@ #include +#include "include/capio-cl-engine/json_parser.hpp" +#include "include/capio-cl-engine/capio_cl_engine.hpp" + int main(int argc, char **argv) { std::cout << CAPIO_LOG_SERVER_BANNER; diff --git a/src/server/client-manager/client_manager.hpp b/src/server/client-manager/client_manager.hpp index 10dac6a22..be4214186 100644 --- a/src/server/client-manager/client_manager.hpp +++ b/src/server/client-manager/client_manager.hpp @@ -1,6 +1,9 @@ #ifndef CLIENT_MANAGER_HPP #define CLIENT_MANAGER_HPP #include +#include +#include +#include /** * @brief Class to handle libcapio_posix clients applications diff --git a/src/server/client-manager/handlers/write.hpp b/src/server/client-manager/handlers/write.hpp index 608a0fdf8..1c1d965dc 100644 --- a/src/server/client-manager/handlers/write.hpp +++ b/src/server/client-manager/handlers/write.hpp @@ -1,6 +1,6 @@ #ifndef WRITE_HPP #define WRITE_HPP -#include "capio-cl-engine/capio_cl_engine.hpp" +#include "include/capio-cl-engine/capio_cl_engine.hpp" /** * @brief Handle the write systemcall diff --git a/src/server/client-manager/request_handler_engine.hpp b/src/server/client-manager/request_handler_engine.hpp index e1cacbffe..61f4b7c57 100644 --- a/src/server/client-manager/request_handler_engine.hpp +++ b/src/server/client-manager/request_handler_engine.hpp @@ -1,8 +1,8 @@ #ifndef CAPIO_CL_ENGINE_MAIN_HPP #define CAPIO_CL_ENGINE_MAIN_HPP -#include "capio-cl-engine/capio_cl_engine.hpp" -#include "capio-cl-engine/json_parser.hpp" +#include "include/capio-cl-engine/capio_cl_engine.hpp" +#include "include/capio-cl-engine/json_parser.hpp" #include "capio/requests.hpp" #include "client_manager.hpp" #include "file-manager/file_manager.hpp" diff --git a/src/server/include/capio-cl-engine/capio_cl_engine.hpp b/src/server/include/capio-cl-engine/capio_cl_engine.hpp new file mode 100644 index 000000000..db3101bf9 --- /dev/null +++ b/src/server/include/capio-cl-engine/capio_cl_engine.hpp @@ -0,0 +1,92 @@ +#ifndef CAPIO_ENGINE_HPP +#define CAPIO_ENGINE_HPP + +#include "client-manager/client_manager.hpp" +#include +#include + +#include "capio/filesystem.hpp" +/** + * @brief Class that stores the parsed configuration of the CAPIO-CL configuration file. + * + */ + +class CapioCLEngine { + friend class CapioFileManager; + std::unordered_map, // Vector for producers [0] + std::vector, // Vector for consumers [1] + std::string, // commit rule [2] + std::string, // fire_rule [3] + bool, // permanent [4] + bool, // exclude [5] + bool, // is_file (false = directory) [6] + int, // commit on close number [7] + long, // directory file count [8] + std::vector, // File dependencies [9] + std::regex, // Regex to match globs [10] + bool>> // Store File on FS. true = memory [11] + _locations; + + static std::string truncateLastN(const std::string &str, const std::size_t n) { + return str.length() > n ? "[..] " + str.substr(str.length() - n) : str; + } + + protected: + const auto *getLocations() const { return &_locations; } + + public: + void print() const; + + /** + * Check whether the file is contained inside the location, either by direct name or by glob + * @param file + * @return + */ + bool contains(const std::filesystem::path &file); + + /** + * Check whether the file is contained inside the location, either by direct name or by glob + * @param file + * @return + */ + + void add(std::string &path, std::vector &producers, + std::vector &consumers, const std::string &commit_rule, + const std::string &fire_rule, bool permanent, bool exclude, + const std::vector &dependencies); + + void newFile(const std::string &path); + long getDirectoryFileCount(const std::string &path); + void addProducer(const std::string &path, std::string &producer); + void addConsumer(const std::string &path, std::string &consumer); + void setCommitRule(const std::string &path, const std::string &commit_rule); + std::string getCommitRule(const std::string &path); + void setFireRule(const std::string &path, const std::string &fire_rule); + bool isFirable(const std::string &path); + void setPermanent(const std::string &path, bool value); + void setExclude(const std::string &path, bool value); + void setDirectory(const std::string &path); + void setFile(const std::string &path); + bool isFile(const std::string &path) const; + bool isDirectory(const std::string &path) const; + void setCommitedNumber(const std::string &path, int num); + void setDirectoryFileCount(const std::string &path, long num); + void remove(const std::string &path); + std::vector producers(const std::string &path); + std::vector consumers(const std::string &path); + bool isProducer(const std::string &path, pid_t pid); + void setFileDeps(const std::filesystem::path &path, + const std::vector &dependencies); + int getCommitCloseCount(std::filesystem::path::iterator::reference path) const; + std::vector get_file_deps(const std::filesystem::path &path); + void setStoreFileInMemory(const std::filesystem::path &path); + void setStoreFileInFileSystem(const std::filesystem::path &path); + bool storeFileInMemory(const std::filesystem::path &path); + std::vector getFileToStoreInMemory(); + auto get_home_node(const std::string &path); +}; + +inline CapioCLEngine *capio_cl_engine; + +#endif // CAPIO_ENGINE_HPP diff --git a/src/server/include/capio-cl-engine/json_parser.hpp b/src/server/include/capio-cl-engine/json_parser.hpp new file mode 100644 index 000000000..b71ac0228 --- /dev/null +++ b/src/server/include/capio-cl-engine/json_parser.hpp @@ -0,0 +1,42 @@ +#ifndef JSON_PARSER_HPP +#define JSON_PARSER_HPP +#include "capio/constants.hpp" + +/** + * @brief Contains the code to parse a JSON based CAPIO-CL configuration file + * + */ +class JsonParser { + + /** + * @brief Check if a string is a representation of a integer number + * + * @param s + * @return true + * @return false + */ + static bool is_int(const std::string &s); + + /** + * @brief compare two paths + * + * @param path + * @param base + * @return true if path is a subdirectory of base + * @return false otherwise + */ + static inline bool first_is_subpath_of_second(const std::filesystem::path &path, + const std::filesystem::path &base); + + public: + /** + * @brief Perform the parsing of the capio_server configuration file + * + * @param source + * @return CapioCLEngine instance with the information provided by the config file + */ + static CapioCLEngine *parse(const std::filesystem::path &source, + const std::filesystem::path resolve_prexix); +}; + +#endif // JSON_PARSER_HPP diff --git a/src/server/src/capio_cl_engine.cpp b/src/server/src/capio_cl_engine.cpp new file mode 100644 index 000000000..e37557a3f --- /dev/null +++ b/src/server/src/capio_cl_engine.cpp @@ -0,0 +1,434 @@ + +#include +#include "utils/configuration.hpp" + +void CapioCLEngine::print() const { + // First message + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, ""); + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "Composition of expected CAPIO FS: "); + + // Table header lines + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "|============================================================================" + "==========================================================|"); + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "|" + std::string(134, ' ') + "|"); + + { + std::ostringstream oss; + oss << "| Parsed configuration file for workflow: \033[1;36m" + << capio_global_configuration->workflow_name + << std::setw(94 - capio_global_configuration->workflow_name.length()) << "\033[0m |"; + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, oss.str()); + } + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "|" + std::string(134, ' ') + "|"); + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "| File color legend: \033[48;5;034m \033[0m File stored in memory" + + std::string(82, ' ') + "|"); + + server_println( + CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "| \033[48;5;172m \033[0m File stored on file system" + + std::string(77, ' ') + "|"); + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "|============================================================================" + "==========================================================|"); + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "|======|===================|===================|====================|========" + "============|============|===========|=========|==========|"); + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "| Kind | Filename | Producer step | Consumer step | " + "Commit Rule | Fire Rule | Permanent | Exclude | n_files |"); + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "|======|===================|===================|====================|========" + "============|============|===========|=========|==========|"); + + // Iterate over _locations + for (auto &itm : _locations) { + std::string color_preamble = std::get<11>(itm.second) ? "\033[38;5;034m" : "\033[38;5;172m"; + std::string color_post = "\033[0m"; + + std::string name_trunc = truncateLastN(itm.first, 12); + auto kind = std::get<6>(itm.second) ? "F" : "D"; + + std::ostringstream base_line; + base_line << "| " << color_preamble << kind << color_post << " | " << color_preamble + << name_trunc << color_post << std::setfill(' ') + << std::setw(20 - name_trunc.length()) << "| "; + + auto producers = std::get<0>(itm.second); + auto consumers = std::get<1>(itm.second); + auto rowCount = std::max(producers.size(), consumers.size()); + + std::string n_files = std::to_string(std::get<8>(itm.second)); + if (std::get<8>(itm.second) < 1) { + n_files = "N.A."; + } + + for (std::size_t i = 0; i <= rowCount; i++) { + std::ostringstream line; + + if (i == 0) { + line << base_line.str(); + } else { + line << "| | | "; + } + + if (i < producers.size()) { + auto prod1 = truncateLastN(producers.at(i), 12); + line << prod1 << std::setfill(' ') << std::setw(20 - prod1.length()) << " | "; + } else { + line << std::setfill(' ') << std::setw(20) << " | "; + } + + if (i < consumers.size()) { + auto cons1 = truncateLastN(consumers.at(i), 12); + line << " " << cons1 << std::setfill(' ') << std::setw(20 - cons1.length()) + << " | "; + } else { + line << std::setfill(' ') << std::setw(21) << " | "; + } + + if (i == 0) { + std::string commit_rule = std::get<2>(itm.second), + fire_rule = std::get<3>(itm.second); + bool exclude = std::get<4>(itm.second), permanent = std::get<5>(itm.second); + + line << " " << commit_rule << std::setfill(' ') + << std::setw(20 - commit_rule.length()) << " | " << fire_rule + << std::setfill(' ') << std::setw(13 - fire_rule.length()) << " | " + << " " << (permanent ? "YES" : "NO ") << " | " + << (exclude ? "YES" : "NO ") << " | " << n_files + << std::setw(10 - n_files.length()) << " |"; + } else { + line << std::setfill(' ') << std::setw(20) << "|" << std::setfill(' ') + << std::setw(13) << "|" << std::setfill(' ') << std::setw(12) << "|" + << std::setfill(' ') << std::setw(10) << "|" << std::setw(10) << "|"; + } + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, line.str()); + } + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + "~~~~~~~~~~~~~~~~~~" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*"); + } + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, ""); +} + +bool CapioCLEngine::contains(const std::filesystem::path &file) { + START_LOG(gettid(), "call(file=%s)", file.c_str()); + return std::any_of(_locations.begin(), _locations.end(), [&](auto &itm) { + return std::regex_match(file.c_str(), std::get<10>(itm.second)); + }); +} + +void CapioCLEngine::add(std::string &path, std::vector &producers, + std::vector &consumers, const std::string &commit_rule, + const std::string &fire_rule, bool permanent, bool exclude, + const std::vector &dependencies) { + START_LOG(gettid(), "call(path=%s, commit=%s, fire=%s, permanent=%s, exclude=%s)", path.c_str(), + commit_rule.c_str(), fire_rule.c_str(), permanent ? "YES" : "NO", + exclude ? "YES" : "NO"); + + _locations.emplace(path, std::make_tuple(producers, consumers, commit_rule, fire_rule, + permanent, exclude, true, -1, -1, dependencies, + generateCapioRegex(path), false)); +} + +void CapioCLEngine::newFile(const std::string &path) { + START_LOG(gettid(), "call(path=%s)", path.c_str()); + if (_locations.find(path) == _locations.end()) { + std::string commit = CAPIO_FILE_COMMITTED_ON_TERMINATION; + std::string fire = CAPIO_FILE_MODE_UPDATE; + + /* + * Inherit commit and fire rules from LPM directory + * matchSize is used to compute LPM + */ + size_t matchSize = 0; + for (const auto &[filename, data] : _locations) { + if (std::regex_match(path, std::get<10>(data)) && filename.length() > matchSize) { + LOG("Found match with %s", filename.c_str()); + matchSize = filename.length(); + commit = std::get<2>(data); + fire = std::get<3>(data); + } + } + LOG("Adding file %s to _locations with commit=%s, and fire=%s", path.c_str(), + commit.c_str(), fire.c_str()); + _locations.emplace(path, std::make_tuple(std::vector(), + std::vector(), commit, fire, false, + false, true, -1, -1, std::vector(), + generateCapioRegex(path), false)); + } +} + +long CapioCLEngine::getDirectoryFileCount(const std::string &path) { + if (const auto itm = _locations.find(path); itm != _locations.end()) { + return std::get<8>(itm->second); + } + return 0; +} + +void CapioCLEngine::addProducer(const std::string &path, std::string &producer) { + START_LOG(gettid(), "call(path=%s, producer=%s)", path.c_str(), producer.c_str()); + producer.erase(remove_if(producer.begin(), producer.end(), isspace), producer.end()); + newFile(path); + if (const auto itm = _locations.find(path); itm != _locations.end()) { + std::get<0>(itm->second).emplace_back(producer); + } +} + +void CapioCLEngine::addConsumer(const std::string &path, std::string &consumer) { + START_LOG(gettid(), "call(path=%s, consumer=%s)", path.c_str(), consumer.c_str()); + consumer.erase(remove_if(consumer.begin(), consumer.end(), isspace), consumer.end()); + if (const auto itm = _locations.find(path); itm != _locations.end()) { + std::get<1>(itm->second).emplace_back(consumer); + } +} + +void CapioCLEngine::setCommitRule(const std::string &path, const std::string &commit_rule) { + START_LOG(gettid(), "call(path=%s, commit_rule=%s)", path.c_str(), commit_rule.c_str()); + if (const auto itm = _locations.find(path); itm != _locations.end()) { + std::get<2>(itm->second) = commit_rule; + } +} + +std::string CapioCLEngine::getCommitRule(const std::string &path) { + START_LOG(gettid(), "call(path=%s)", path.c_str()); + if (const auto itm = _locations.find(path); itm != _locations.end()) { + LOG("Commit rule: %s", std::get<2>(_locations.at(path)).c_str()); + return std::get<2>(itm->second); + } + + /* + * For caching purpose, each new file is then added to the map if not found, + * with its data being instantiated from the metadata of the most likely matched glob + * TODO: check overhead of this + */ + LOG("No entry found on map. checking globs. Creating new file from globs"); + this->newFile((path)); + LOG("Returning DEFAULT Fire rule for file %s (update)", path.c_str()); + return std::get<2>(_locations.at((path))); +} + +void CapioCLEngine::setFireRule(const std::string &path, const std::string &fire_rule) { + START_LOG(gettid(), "call(path=%s, fire_rule=%s)", path.c_str(), fire_rule.c_str()); + if (const auto itm = _locations.find(path); itm != _locations.end()) { + std::get<3>(itm->second) = fire_rule; + } +} + +bool CapioCLEngine::isFirable(const std::string &path) { + START_LOG(gettid(), "call(path=%s)", path.c_str()); + if (const auto itm = _locations.find(path); itm != _locations.end()) { + LOG("Fire rule for file %s is %s", path.c_str(), std::get<3>(itm->second).c_str()); + return std::get<3>(itm->second) == CAPIO_FILE_MODE_NO_UPDATE; + } + /* + * For caching purpose, each new file is then added to the map if not found, + * with its data being instantiated from the metadata of the most likely matched glob + * TODO: check overhead of this + */ + LOG("No entry found on map. checking globs. Creating new file from globs"); + this->newFile((path)); + LOG("Fire rule for file %s is %s", path.c_str(), std::get<3>(_locations.at((path))).c_str()); + return std::get<3>(_locations.at((path))) == CAPIO_FILE_MODE_NO_UPDATE; +} + +void CapioCLEngine::setPermanent(const std::string &path, bool value) { + START_LOG(gettid(), "call(path=%s, value=%s)", path.c_str(), value ? "true" : "false"); + if (const auto itm = _locations.find(path); itm != _locations.end()) { + std::get<4>(itm->second) = value; + } +} + +void CapioCLEngine::setExclude(const std::string &path, const bool value) { + START_LOG(gettid(), "call(path=%s, value=%s)", path.c_str(), value ? "true" : "false"); + if (const auto itm = _locations.find(path); itm != _locations.end()) { + std::get<5>(itm->second) = value; + } +} + +void CapioCLEngine::setDirectory(const std::string &path) { + START_LOG(gettid(), "call(path=%s)", path.c_str()); + if (const auto itm = _locations.find(path); itm != _locations.end()) { + std::get<6>(itm->second) = false; + } +} + +void CapioCLEngine::setFile(const std::string &path) { + START_LOG(gettid(), "call(path=%s)", path.c_str()); + if (const auto itm = _locations.find(path); itm != _locations.end()) { + std::get<6>(itm->second) = true; + } +} + +bool CapioCLEngine::isFile(const std::string &path) const { + if (const auto itm = _locations.find(path); itm != _locations.end()) { + return std::get<6>(itm->second); + } + return false; +} + +bool CapioCLEngine::isDirectory(const std::string &path) const { + START_LOG(gettid(), "call(path=%s)", path.c_str()); + return !isFile(path); +} + +void CapioCLEngine::setCommitedNumber(const std::string &path, const int num) { + START_LOG(gettid(), "call(path=%s, num=%ld)", path.c_str(), num); + if (const auto itm = _locations.find(path); itm != _locations.end()) { + std::get<7>(itm->second) = num; + } +} + +void CapioCLEngine::setDirectoryFileCount(const std::string &path, long num) { + START_LOG(gettid(), "call(path=%s, num=%ld)", path.c_str(), num); + if (const auto itm = _locations.find(path); itm != _locations.end()) { + std::get<8>(itm->second) = num; + } +} + +void CapioCLEngine::remove(const std::string &path) { + START_LOG(gettid(), "call(path=%s)", path.c_str()); + _locations.erase(path); +} + +// TODO: return vector +std::vector CapioCLEngine::producers(const std::string &path) { + START_LOG(gettid(), "call(path=%s)", path.c_str()); + if (const auto itm = _locations.find(path); itm != _locations.end()) { + return std::get<0>(itm->second); + } + return {}; +} + +// TODO: return vector +std::vector CapioCLEngine::consumers(const std::string &path) { + START_LOG(gettid(), "call(path=%s)", path.c_str()); + if (const auto itm = _locations.find(path); itm != _locations.end()) { + return std::get<1>(itm->second); + } + return {}; +} + +bool CapioCLEngine::isProducer(const std::string &path, const pid_t pid) { + START_LOG(gettid(), "call(path=%s, pid=%ld", path.c_str(), pid); + + const auto app_name = client_manager->get_app_name(pid); + LOG("App name for tid %d is %s", pid, app_name.c_str()); + + // check for exact entry + if (const auto itm = _locations.find(path); itm != _locations.end()) { + LOG("Found exact match for path"); + std::vector producers = std::get<0>(itm->second); + DBG(gettid(), [&](const std::vector &arr) { + for (auto elem : arr) { + LOG("producer: %s", elem.c_str()); + } + }(producers)); + return std::find(producers.begin(), producers.end(), app_name) != producers.end(); + } + LOG("No exact match found in locations. checking for globs"); + // check for glob + for (const auto &[k, entry] : _locations) { + if (std::regex_match(path, std::get<10>(entry))) { + LOG("Found possible glob match"); + std::vector producers = std::get<0>(entry); + DBG(gettid(), [&](const std::vector &arr) { + for (auto itm : arr) { + LOG("producer: %s", itm.c_str()); + } + }(producers)); + return std::find(producers.begin(), producers.end(), app_name) != producers.end(); + } + } + LOG("No match has been found"); + return false; +} + +void CapioCLEngine::setFileDeps(const std::filesystem::path &path, + const std::vector &dependencies) { + START_LOG(gettid(), "call()"); + if (dependencies.empty()) { + return; + } + if (_locations.find(path) == _locations.end()) { + this->newFile(path); + } + std::get<9>(_locations.at(path)) = dependencies; + for (const auto &itm : dependencies) { + LOG("Creating new fie (if it exists) for path %s", itm.c_str()); + newFile(itm); + } +} + +int CapioCLEngine::getCommitCloseCount(std::filesystem::path::iterator::reference path) const { + START_LOG(gettid(), "call(path=%s)", path.c_str()); + int count = 0; + if (const auto itm = _locations.find(path); itm != _locations.end()) { + count = std::get<7>(itm->second); + } + LOG("Expected number on close to commit file: %d", count); + return count; +}; + +// todo fix leak +std::vector CapioCLEngine::get_file_deps(const std::filesystem::path &path) { + if (const auto itm = _locations.find(path); itm != _locations.end()) { + return std::get<9>(itm->second); + } + return {}; +} + +void CapioCLEngine::setStoreFileInMemory(const std::filesystem::path &path) { + this->newFile(path); + std::get<11>(_locations.at(path)) = true; +} + +void CapioCLEngine::setStoreFileInFileSystem(const std::filesystem::path &path) { + this->newFile(path); + std::get<11>(_locations.at(path)) = false; +} + +bool CapioCLEngine::storeFileInMemory(const std::filesystem::path &path) { + if (const auto itm = _locations.find(path); itm != _locations.end()) { + return std::get<11>(itm->second); + } + return false; +} + +std::vector CapioCLEngine::getFileToStoreInMemory() { + START_LOG(gettid(), "call()"); + std::vector files; + + for (const auto &[path, file] : _locations) { + if (std::get<11>(file)) { + files.push_back(path); + } + } + + return files; +} + +auto CapioCLEngine::get_home_node(const std::string &path) { + // TODO: understand here how to get the home node policy. + START_LOG(gettid(), "call(path=%s)", path.c_str()); + if (const auto location = _locations.find(path); location == _locations.end()) { + LOG("No rule for home node. Returning create home node"); + return capio_global_configuration->node_name; + } else { + LOG("Found location entry"); + } + return capio_global_configuration->node_name; +} diff --git a/src/server/src/json_parser.cpp b/src/server/src/json_parser.cpp new file mode 100644 index 000000000..e3b35083f --- /dev/null +++ b/src/server/src/json_parser.cpp @@ -0,0 +1,451 @@ +#include +#include +#include +#include +#include + +bool JsonParser::is_int(const std::string &s) { + START_LOG(gettid(), "call(%s)", s.c_str()); + bool res = false; + if (!s.empty()) { + char *p; + strtol(s.c_str(), &p, 10); + res = *p == 0; + } + return res; +} + +bool JsonParser::first_is_subpath_of_second(const std::filesystem::path &path, + const std::filesystem::path &base) { + const auto mismatch_pair = std::mismatch(path.begin(), path.end(), base.begin(), base.end()); + return mismatch_pair.second == base.end(); +} + +CapioCLEngine *JsonParser::parse(const std::filesystem::path &source, + const std::filesystem::path resolve_prexix) { + auto locations = new CapioCLEngine(); + START_LOG(gettid(), "call(config_file='%s')", source.c_str()); + + /* + * Before here a call to get_capio_dir() was issued. However, to support multiple CAPIO_DIRs + * there is no difference to use the wildcard * instead of CAPIO_DIR. This is true as only + * paths relative to the capio_dir directory are forwarded to the server, and as such, there + * is no difference that to create a ROOT dir equal to CAPIO_DIR compared to the wildcard *. + */ + locations->newFile("*"); + locations->setDirectory("*"); + if (capio_global_configuration->StoreOnlyInMemory) { + locations->setStoreFileInMemory("*"); + } + + if (source.empty()) { + return locations; + } + + simdjson::ondemand::parser parser; + simdjson::padded_string json; + simdjson::ondemand::document entries; + simdjson::ondemand::array input_stream, output_stream, streaming, permanent_files, + exclude_files, storage_memory, storage_fs; + simdjson::ondemand::object storage_section; + simdjson::error_code error; + + try { + json = simdjson::padded_string::load(source.c_str()); + } catch (const simdjson::simdjson_error &e) { + std::cerr << CAPIO_LOG_SERVER_CLI_LEVEL_ERROR << " [ " + << capio_global_configuration->node_name << " ] " + << "Exception thrown while opening config file: " << e.what() << std::endl; + LOG("Exception thrown while opening config file: %s", e.what()); + ERR_EXIT("Exception thrown while opening config file: %s", e.what()); + } + + entries = parser.iterate(json); + std::string_view wf_name; + error = entries["name"].get_string().get(wf_name); + if (error) { + ERR_EXIT("Error: workflow name is mandatory"); + } + capio_global_configuration->workflow_name = std::string(wf_name); + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "Parsing configuration for workflow: " + + capio_global_configuration->workflow_name); + + LOG("Parsing configuration for workflow: %s", + std::string(capio_global_configuration->workflow_name).c_str()); + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, ""); + + auto io_graph = entries["IO_Graph"]; + + for (auto app : io_graph) { + std::string_view app_name; + error = app["name"].get_string().get(app_name); + if (error) { + ERR_EXIT("Error: app name is mandatory"); + } + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "Parsing config for app " + std::string(app_name)); + LOG("Parsing config for app %s", std::string(app_name).c_str()); + + if (app["input_stream"].get_array().get(input_stream)) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, + "No input_stream section found for app " + std::string(app_name)); + ERR_EXIT("No input_stream section found for app %s", std::string(app_name).c_str()); + } else { + for (auto itm : input_stream) { + std::filesystem::path file(itm.get_string().take_value()); + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "Found file " + std::string(file)); + + if (file.is_relative()) { + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "Path : " + std::string(file) + + " IS RELATIVE! using cwd() of server to compute abs path."); + file = resolve_prexix / file; + } + std::string appname(app_name); + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "Path : " + std::string(file) + + " added to app: " + std::string(app_name)); + + locations->newFile(file.c_str()); + locations->addConsumer(file, appname); + } + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "Completed input_stream parsing for app: " + std::string(app_name)); + + LOG("Completed input_stream parsing for app: %s", std::string(app_name).c_str()); + } + + if (app["output_stream"].get_array().get(output_stream)) { + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, + "No output_stream section found for app " + std::string(app_name)); + ERR_EXIT("No output_stream section found for app %s", std::string(app_name).c_str()); + } else { + for (auto itm : output_stream) { + std::filesystem::path file(itm.get_string().take_value()); + if (file.is_relative()) { + if (file.is_relative()) { + server_println( + CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "Path : " + std::string(file) + + " IS RELATIVE! using cwd() of server to compute abs path."); + file = resolve_prexix / file; + } + } + std::string appname(app_name); + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "Adding file: " + std::string(file) + " to app: " + appname); + + locations->newFile(file); + locations->addProducer(file, appname); + } + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "Completed output_stream parsing for app: " + std::string(app_name)); + LOG("Completed output_stream parsing for app: %s", std::string(app_name).c_str()); + } + + // PARSING STREAMING FILES + if (app["streaming"].get_array().get(streaming)) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "No Streaming section found for app " + std::string(app_name)); + LOG("No streaming section found for app: %s", std::string(app_name).c_str()); + } else { + LOG("Began parsing streaming section for app %s", std::string(app_name).c_str()); + for (auto file : streaming) { + std::string_view committed, mode, commit_rule; + std::vector streaming_names; + std::vector file_deps; + long int n_close = -1; + long n_files = -1, batch_size; + bool is_file = true; + + simdjson::ondemand::array name; + error = file["name"].get_array().get(name); + if (error || name.is_empty()) { + error = file["dirname"].get_array().get(name); + if (error || name.is_empty()) { + server_println( + CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, + "error: either name or dirname in streaming section is required"); + ERR_EXIT("error: either name or dirname in streaming section is required"); + } + is_file = false; + } + + for (auto item : name) { + std::string_view elem = item.get_string().value(); + LOG("Found name: %s", std::string(elem).c_str()); + std::filesystem::path file_fs(elem); + if (file_fs.is_relative()) { + server_println( + CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "Path : " + std::string(file_fs) + + " IS RELATIVE! using cwd() of server to compute abs path."); + file_fs = resolve_prexix / file_fs; + } + LOG("Saving file %s to locations", std::string(elem).c_str()); + streaming_names.emplace_back(elem); + } + + // PARSING COMMITTED + error = file["committed"].get_string().get(committed); + if (error) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, + "commit rule is mandatory in streaming section"); + ERR_EXIT("error commit rule is mandatory in streaming section"); + } else { + auto pos = committed.find(':'); + if (pos != std::string::npos) { + commit_rule = committed.substr(0, pos); + std::string count_str(committed.substr(pos + 1, committed.length())); + if (!JsonParser::is_int(count_str)) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, + "commit rule on_close/n_files invalid number"); + ERR_EXIT("error commit rule on_close invalid number: !is_int()"); + } + + if (commit_rule == CAPIO_FILE_COMMITTED_ON_CLOSE) { + n_close = std::stol(count_str); + } else if (commit_rule == CAPIO_FILE_COMMITTED_N_FILES) { + n_files = std::stol(count_str); + // TODO: use internally n_files. for now, we use on_close as default + commit_rule = CAPIO_FILE_COMMITTED_ON_CLOSE; + } else { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, + "Invalid commit rule: " + std::string(commit_rule)); + ERR_EXIT("error commit rule: %s", std::string(commit_rule).c_str()); + } + + } else { + commit_rule = committed; + } + } + + // check for committed on file: + if (commit_rule == CAPIO_FILE_COMMITTED_ON_FILE) { + simdjson::ondemand::array file_deps_tmp; + error = file["file_deps"].get_array().get(file_deps_tmp); + + if (error) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, + "commit rule is on_file but no file_deps section found"); + ERR_EXIT("commit rule is on_file but no file_deps section found"); + } + + std::string_view name_tmp; + for (auto itm : file_deps_tmp) { + name_tmp = itm.get_string().value(); + std::filesystem::path computed_path(name_tmp); + if (computed_path.is_relative()) { + server_println( + CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "Path : " + std::string(computed_path) + + " IS RELATIVE! using cwd() of server to compute abs path."); + computed_path = resolve_prexix / computed_path; + } + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "Adding file: " + std::string(computed_path) + + " to file dependencies: "); + + file_deps.emplace_back(computed_path); + } + } + + LOG("Committed: %s", std::string(committed).c_str()); + // END PARSING COMMITTED + + error = file["mode"].get_string().get(mode); + if (error) { + mode = CAPIO_FILE_MODE_UPDATE; + } + LOG("Mode: %s", std::string(mode).c_str()); + + if (n_files == -1) { + error = file["n_files"].get_int64().get(n_files); + if (error && n_files != -1) { + n_files = -1; + } + } + LOG("n_files: %d", n_files); + + error = file["batch_size"].get_int64().get(batch_size); + if (error) { + batch_size = 0; + } + LOG("batch_size: %d", batch_size); + for (auto path : streaming_names) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "Updating metadata for path: " + std::string(path)); + + if (path.is_relative()) { + server_println( + CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "Path : " + std::string(path) + + " IS RELATIVE! using cwd() of server to compute abs path."); + path = resolve_prexix / path; + } + LOG("path: %s", path.c_str()); + + // TODO: check for globs + std::string commit(commit_rule), firerule(mode); + if (n_files != -1) { + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "Setting path: " + std::string(path) + " n_files to " + + std::to_string(n_files)); + locations->setDirectoryFileCount(path, n_files); + } + + is_file ? locations->setFile(path) : locations->setDirectory(path); + locations->setCommitRule(path, commit); + locations->setFireRule(path, firerule); + locations->setCommitedNumber(path, n_close); + locations->setFileDeps(path, file_deps); + } + } + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "completed parsing of streaming section for app: " + + std::string(app_name)); + LOG("completed parsing of streaming section for app: %s", + std::string(app_name).c_str()); + } // END PARSING STREAMING FILES + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, ""); + } // END OF APP MAIN LOOPS + LOG("Completed parsing of io_graph app main loops"); + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "Completed parsing of io_graph"); + LOG("Completed parsing of io_graph"); + + if (entries["permanent"].get_array().get(permanent_files)) { + // PARSING PERMANENT FILES + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "No permanent section found for workflow: " + + capio_global_configuration->workflow_name); + LOG("No permanent section found for workflow: %s", + capio_global_configuration->workflow_name.c_str()); + } else { + for (auto file : permanent_files) { + std::string_view name; + error = file.get_string().get(name); + if (error) { + ERR_EXIT("error name for permanent section is mandatory"); + } + LOG("Permanent name: %s", std::string(name).c_str()); + + std::filesystem::path path(name); + + if (path.is_relative()) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "Path : " + std::string(path) + + " IS RELATIVE! using cwd() of server to compute abs path."); + path = resolve_prexix / path; + } + + // TODO: check for globs + // TODO: improve this + locations->setPermanent(name.data(), true); + } + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "Completed parsing of permanent files"); + LOG("Completed parsing of permanent files"); + } // END PARSING PERMANENT FILES + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, ""); + + if (entries["exclude"].get_array().get(exclude_files)) { + // PARSING PERMANENT FILES + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "No exclude section found for workflow: " + + capio_global_configuration->workflow_name); + LOG("No exclude section found for workflow: %s", + std::string(capio_global_configuration->workflow_name).c_str()); + } else { + for (auto file : exclude_files) { + std::string_view name; + error = file.get_string().get(name); + if (error) { + ERR_EXIT("error name for exclude section is mandatory"); + } + LOG("exclude name: %s", std::string(name).c_str()); + + std::filesystem::path path(name); + + if (path.is_relative()) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "Path : " + std::string(path) + + " IS RELATIVE! using cwd() of server to compute abs path."); + path = resolve_prexix / path; + } + // TODO: check for globs + locations->setExclude(path, true); + } + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "Completed parsing of exclude files"); + LOG("Completed parsing of exclude files"); + } // END PARSING PERMANENT FILES + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, ""); + + auto home_node_policies = entries["home_node_policy"].error(); + if (!home_node_policies) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "Warning: capio does not support home node policies yet! skipping section "); + } + + if (entries["storage"].get_object().get(storage_section)) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "No storage section found for workflow: " + + capio_global_configuration->workflow_name); + LOG("No storage section found for workflow: %s", + std::string(capio_global_configuration->workflow_name).c_str()); + } else { + if (storage_section["memory"].get_array().get(storage_memory)) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "No files listed in memory storage section for workflow: " + + capio_global_configuration->workflow_name); + LOG("No files listed in memory storage section for workflow: %s", + std::string(capio_global_configuration->workflow_name).c_str()); + } else { + for (auto file : storage_memory) { + std::string_view file_str; + [[maybe_unused]] const auto error = file.get_string().get(file_str); + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "Setting file " + std::string(file_str) + " to be stored in memory"); + locations->setStoreFileInMemory(file_str); + } + } + + if (storage_section["fs"].get_array().get(storage_fs)) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "No files listed in fs storage section for workflow: " + + capio_global_configuration->workflow_name); + LOG("No files listed in fs storage section for workflow: %s", + std::string(capio_global_configuration->workflow_name).c_str()); + } else { + for (auto file : storage_fs) { + std::string_view file_str; + [[maybe_unused]] const auto error = file.get_string().get(file_str); + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, "Setting file " + + std::string(file_str) + + " to be stored on file system"); + locations->setStoreFileInFileSystem(file_str); + } + } + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, + "Completed parsing of memory storage directives"); + } + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_JSON, ""); + + return locations; +} \ No newline at end of file diff --git a/src/server/utils/configuration.hpp b/src/server/utils/configuration.hpp index f26e15045..16ec95e2c 100644 --- a/src/server/utils/configuration.hpp +++ b/src/server/utils/configuration.hpp @@ -5,6 +5,7 @@ #include #include +#include /* * Variables required to be globally available From 69c128c3114fb6734d53f460e7d9cebe4773e755 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Fri, 29 Aug 2025 19:26:39 +0000 Subject: [PATCH 02/10] Refactor of project Split definition of classes and implementation to avoid recursive include issues that were rising when defining the capio_server backend --- CMakeLists.txt | 8 +- .../capio/constants.hpp | 0 {src/common => capio-common}/capio/env.hpp | 39 ++ .../capio/filesystem.hpp | 0 {src/common => capio-common}/capio/logger.hpp | 0 {src/common => capio-common}/capio/queue.hpp | 0 .../capio/requests.hpp | 0 .../capio/response_queue.hpp | 0 .../capio/semaphore.hpp | 0 {src/common => capio-common}/capio/shm.hpp | 0 .../common => capio-common}/capio/syscall.hpp | 0 {src/posix => capio-posix}/CMakeLists.txt | 0 {src/posix => capio-posix}/handlers.hpp | 0 .../posix => capio-posix}/handlers/access.hpp | 0 {src/posix => capio-posix}/handlers/chdir.hpp | 0 {src/posix => capio-posix}/handlers/close.hpp | 0 .../handlers/copy_file_range.hpp | 0 {src/posix => capio-posix}/handlers/dup.hpp | 0 .../posix => capio-posix}/handlers/execve.hpp | 0 {src/posix => capio-posix}/handlers/exit.hpp | 0 .../posix => capio-posix}/handlers/fchmod.hpp | 0 .../posix => capio-posix}/handlers/fchown.hpp | 0 {src/posix => capio-posix}/handlers/fcntl.hpp | 0 .../handlers/fgetxattr.hpp | 0 {src/posix => capio-posix}/handlers/fork.hpp | 0 .../posix => capio-posix}/handlers/getcwd.hpp | 0 {src/posix => capio-posix}/handlers/ioctl.hpp | 0 {src/posix => capio-posix}/handlers/lseek.hpp | 0 {src/posix => capio-posix}/handlers/mkdir.hpp | 0 {src/posix => capio-posix}/handlers/open.hpp | 0 .../handlers/posix_readdir.hpp | 0 {src/posix => capio-posix}/handlers/read.hpp | 0 .../posix => capio-posix}/handlers/rename.hpp | 0 {src/posix => capio-posix}/handlers/stat.hpp | 0 .../posix => capio-posix}/handlers/statfs.hpp | 0 {src/posix => capio-posix}/handlers/statx.hpp | 0 .../posix => capio-posix}/handlers/unlink.hpp | 0 {src/posix => capio-posix}/handlers/write.hpp | 0 {src/posix => capio-posix}/libcapio_posix.cpp | 0 {src/posix => capio-posix}/readme.md | 0 .../syscall_intercept/CMakeLists.txt | 0 {src/posix => capio-posix}/utils/cache.hpp | 0 .../utils/cache/consent_request_cache.hpp | 0 .../utils/cache/read_request_cache_fs.hpp | 0 .../utils/cache/read_request_cache_mem.hpp | 0 .../utils/cache/write_request_cache_fs.hpp | 0 .../utils/cache/write_request_cache_mem.hpp | 0 {src/posix => capio-posix}/utils/clone.hpp | 0 {src/posix => capio-posix}/utils/common.hpp | 0 {src/posix => capio-posix}/utils/env.hpp | 35 -- .../utils/filesystem.hpp | 0 {src/posix => capio-posix}/utils/requests.hpp | 0 {src/posix => capio-posix}/utils/snapshot.hpp | 0 {src/posix => capio-posix}/utils/storage.hpp | 0 {src/posix => capio-posix}/utils/types.hpp | 0 {src/server => capio-server}/CMakeLists.txt | 28 +- {src/server => capio-server}/capio_server.cpp | 32 +- .../capio-cl-engine/capio_cl_engine.hpp | 2 +- .../include/capio-cl-engine/json_parser.hpp | 2 + .../include/client-manager/client_manager.hpp | 77 ++++ .../include/client-manager/handlers.hpp | 97 +++++ .../client-manager/request_handler_engine.hpp | 41 ++ .../capio_communication_service.hpp | 17 + .../control-plane}/capio_control_plane.hpp | 5 +- .../control-plane/fs_control_plane.hpp | 37 ++ .../control-plane/multicast_control_plane.hpp | 32 ++ .../data-plane/backend_interface.hpp | 11 +- .../data-plane/mtcl_backend.hpp | 64 +++ .../data-plane/transport_unit.hpp | 23 ++ .../include/file-manager/file_manager.hpp | 141 +++++++ .../include/file-manager/fs_monitor.hpp | 37 ++ .../include/storage-service/capio_file.hpp | 180 +++++++++ .../storage-service/capio_storage_service.hpp | 115 ++++++ .../src/capio-cl-engine}/capio_cl_engine.cpp | 0 .../src/capio-cl-engine}/json_parser.cpp | 0 .../src/client-manager/client_manager.cpp | 86 +--- .../src/client-manager/handlers/close.cpp | 18 +- .../src/client-manager/handlers/consent.cpp | 21 +- .../src/client-manager/handlers/create.cpp | 21 +- .../src/client-manager/handlers/exit.cpp | 15 +- .../handlers/files_in_memory.cpp | 18 +- .../src/client-manager/handlers/handshake.cpp | 18 +- .../src/client-manager/handlers/open.cpp | 19 +- .../client-manager/handlers/posix_readdir.cpp | 11 +- .../src/client-manager/handlers/read.cpp | 21 +- .../src/client-manager/handlers/rename.cpp | 15 +- .../src/client-manager/handlers/write.cpp | 19 +- .../client-manager/request_handler_engine.cpp | 114 ++++++ .../capio_communication_service.cpp | 33 +- .../control-plane/fs_control_plane.cpp | 35 +- .../control-plane/multicast_control_plane.cpp | 26 +- .../control-plane}/multicast_utils.hpp | 2 + .../data-plane/mtcl_backend.cpp | 318 +++++++++++++++ .../src/file-manager/file_manager.cpp | 116 +----- capio-server/src/file-manager/fs_monitor.cpp | 76 ++++ .../src/storage-service/capio_memory_file.cpp | 88 +---- .../src/storage-service/capio_remote_file.cpp | 27 ++ .../storage-service/capio_storage_service.cpp | 136 ++----- .../utils/configuration.hpp | 1 + .../utils/distributed_semaphore.hpp | 0 {src/server => capio-server}/utils/parser.hpp | 2 + .../server => capio-server}/utils/signals.hpp | 4 +- {src/server => capio-server}/utils/types.hpp | 0 .../docker-development}/build-and-startup.sh | 4 +- .../docker-development}/docker-compose.yml | 0 .../client-manager/request_handler_engine.hpp | 166 -------- .../data_plane/MTCL_backend.hpp | 368 ------------------ src/server/file-manager/file_manager.hpp | 55 --- src/server/file-manager/fs_monitor.hpp | 98 ----- .../storage-service/CapioFile/CapioFile.hpp | 58 --- .../CapioFile/CapioRemoteFile.hpp | 58 --- tests/multinode/backend/CMakeLists.txt | 2 +- tests/multinode/backend/src/main.cpp | 2 +- tests/unit/MemoryFiles/CMakeLists.txt | 2 +- tests/unit/posix/CMakeLists.txt | 2 +- tests/unit/server/CMakeLists.txt | 2 +- .../server/src/CapioCacheSPSCQueueTests.hpp | 12 +- tests/unit/server/src/CapioFileTests.hpp | 2 +- 118 files changed, 1683 insertions(+), 1431 deletions(-) rename {src/common => capio-common}/capio/constants.hpp (100%) rename {src/common => capio-common}/capio/env.hpp (72%) rename {src/common => capio-common}/capio/filesystem.hpp (100%) rename {src/common => capio-common}/capio/logger.hpp (100%) rename {src/common => capio-common}/capio/queue.hpp (100%) rename {src/common => capio-common}/capio/requests.hpp (100%) rename {src/common => capio-common}/capio/response_queue.hpp (100%) rename {src/common => capio-common}/capio/semaphore.hpp (100%) rename {src/common => capio-common}/capio/shm.hpp (100%) rename {src/common => capio-common}/capio/syscall.hpp (100%) rename {src/posix => capio-posix}/CMakeLists.txt (100%) rename {src/posix => capio-posix}/handlers.hpp (100%) rename {src/posix => capio-posix}/handlers/access.hpp (100%) rename {src/posix => capio-posix}/handlers/chdir.hpp (100%) rename {src/posix => capio-posix}/handlers/close.hpp (100%) rename {src/posix => capio-posix}/handlers/copy_file_range.hpp (100%) rename {src/posix => capio-posix}/handlers/dup.hpp (100%) rename {src/posix => capio-posix}/handlers/execve.hpp (100%) rename {src/posix => capio-posix}/handlers/exit.hpp (100%) rename {src/posix => capio-posix}/handlers/fchmod.hpp (100%) rename {src/posix => capio-posix}/handlers/fchown.hpp (100%) rename {src/posix => capio-posix}/handlers/fcntl.hpp (100%) rename {src/posix => capio-posix}/handlers/fgetxattr.hpp (100%) rename {src/posix => capio-posix}/handlers/fork.hpp (100%) rename {src/posix => capio-posix}/handlers/getcwd.hpp (100%) rename {src/posix => capio-posix}/handlers/ioctl.hpp (100%) rename {src/posix => capio-posix}/handlers/lseek.hpp (100%) rename {src/posix => capio-posix}/handlers/mkdir.hpp (100%) rename {src/posix => capio-posix}/handlers/open.hpp (100%) rename {src/posix => capio-posix}/handlers/posix_readdir.hpp (100%) rename {src/posix => capio-posix}/handlers/read.hpp (100%) rename {src/posix => capio-posix}/handlers/rename.hpp (100%) rename {src/posix => capio-posix}/handlers/stat.hpp (100%) rename {src/posix => capio-posix}/handlers/statfs.hpp (100%) rename {src/posix => capio-posix}/handlers/statx.hpp (100%) rename {src/posix => capio-posix}/handlers/unlink.hpp (100%) rename {src/posix => capio-posix}/handlers/write.hpp (100%) rename {src/posix => capio-posix}/libcapio_posix.cpp (100%) rename {src/posix => capio-posix}/readme.md (100%) rename {src/posix => capio-posix}/syscall_intercept/CMakeLists.txt (100%) rename {src/posix => capio-posix}/utils/cache.hpp (100%) rename {src/posix => capio-posix}/utils/cache/consent_request_cache.hpp (100%) rename {src/posix => capio-posix}/utils/cache/read_request_cache_fs.hpp (100%) rename {src/posix => capio-posix}/utils/cache/read_request_cache_mem.hpp (100%) rename {src/posix => capio-posix}/utils/cache/write_request_cache_fs.hpp (100%) rename {src/posix => capio-posix}/utils/cache/write_request_cache_mem.hpp (100%) rename {src/posix => capio-posix}/utils/clone.hpp (100%) rename {src/posix => capio-posix}/utils/common.hpp (100%) rename {src/posix => capio-posix}/utils/env.hpp (61%) rename {src/posix => capio-posix}/utils/filesystem.hpp (100%) rename {src/posix => capio-posix}/utils/requests.hpp (100%) rename {src/posix => capio-posix}/utils/snapshot.hpp (100%) rename {src/posix => capio-posix}/utils/storage.hpp (100%) rename {src/posix => capio-posix}/utils/types.hpp (100%) rename {src/server => capio-server}/CMakeLists.txt (74%) rename {src/server => capio-server}/capio_server.cpp (79%) rename {src/server => capio-server}/include/capio-cl-engine/capio_cl_engine.hpp (98%) rename {src/server => capio-server}/include/capio-cl-engine/json_parser.hpp (95%) create mode 100644 capio-server/include/client-manager/client_manager.hpp create mode 100644 capio-server/include/client-manager/handlers.hpp create mode 100644 capio-server/include/client-manager/request_handler_engine.hpp create mode 100644 capio-server/include/communication-service/capio_communication_service.hpp rename {src/server/communication-service/control_plane => capio-server/include/communication-service/control-plane}/capio_control_plane.hpp (94%) create mode 100644 capio-server/include/communication-service/control-plane/fs_control_plane.hpp create mode 100644 capio-server/include/communication-service/control-plane/multicast_control_plane.hpp rename src/server/communication-service/data_plane/BackendInterface.hpp => capio-server/include/communication-service/data-plane/backend_interface.hpp (93%) create mode 100644 capio-server/include/communication-service/data-plane/mtcl_backend.hpp create mode 100644 capio-server/include/communication-service/data-plane/transport_unit.hpp create mode 100644 capio-server/include/file-manager/file_manager.hpp create mode 100644 capio-server/include/file-manager/fs_monitor.hpp create mode 100644 capio-server/include/storage-service/capio_file.hpp create mode 100644 capio-server/include/storage-service/capio_storage_service.hpp rename {src/server/src => capio-server/src/capio-cl-engine}/capio_cl_engine.cpp (100%) rename {src/server/src => capio-server/src/capio-cl-engine}/json_parser.cpp (100%) rename src/server/client-manager/client_manager.hpp => capio-server/src/client-manager/client_manager.cpp (56%) rename src/server/client-manager/handlers/close.hpp => capio-server/src/client-manager/handlers/close.cpp (80%) rename src/server/client-manager/handlers/consent.hpp => capio-server/src/client-manager/handlers/consent.cpp (76%) rename src/server/client-manager/handlers/create.hpp => capio-server/src/client-manager/handlers/create.cpp (59%) rename src/server/client-manager/handlers/exit.hpp => capio-server/src/client-manager/handlers/exit.cpp (62%) rename src/server/client-manager/handlers/files_in_memory.hpp => capio-server/src/client-manager/handlers/files_in_memory.cpp (50%) rename src/server/client-manager/handlers/handshake.hpp => capio-server/src/client-manager/handlers/handshake.cpp (70%) rename src/server/client-manager/handlers/open.hpp => capio-server/src/client-manager/handlers/open.cpp (77%) rename src/server/client-manager/handlers/posix_readdir.hpp => capio-server/src/client-manager/handlers/posix_readdir.cpp (62%) rename src/server/client-manager/handlers/read.hpp => capio-server/src/client-manager/handlers/read.cpp (90%) rename src/server/client-manager/handlers/rename.hpp => capio-server/src/client-manager/handlers/rename.cpp (58%) rename src/server/client-manager/handlers/write.hpp => capio-server/src/client-manager/handlers/write.cpp (73%) create mode 100644 capio-server/src/client-manager/request_handler_engine.cpp rename src/server/communication-service/CapioCommunicationService.hpp => capio-server/src/communication-service/capio_communication_service.cpp (75%) rename src/server/communication-service/control_plane/fs_control_plane.hpp => capio-server/src/communication-service/control-plane/fs_control_plane.cpp (81%) rename src/server/communication-service/control_plane/multicast_control_plane.hpp => capio-server/src/communication-service/control-plane/multicast_control_plane.cpp (90%) rename {src/server/communication-service/control_plane => capio-server/src/communication-service/control-plane}/multicast_utils.hpp (99%) create mode 100644 capio-server/src/communication-service/data-plane/mtcl_backend.cpp rename src/server/file-manager/file_manager_impl.hpp => capio-server/src/file-manager/file_manager.cpp (81%) create mode 100644 capio-server/src/file-manager/fs_monitor.cpp rename src/server/storage-service/CapioFile/CapioMemoryFile.hpp => capio-server/src/storage-service/capio_memory_file.cpp (68%) create mode 100644 capio-server/src/storage-service/capio_remote_file.cpp rename src/server/storage-service/capio_storage_service.hpp => capio-server/src/storage-service/capio_storage_service.cpp (58%) rename {src/server => capio-server}/utils/configuration.hpp (98%) rename {src/server => capio-server}/utils/distributed_semaphore.hpp (100%) rename {src/server => capio-server}/utils/parser.hpp (98%) rename {src/server => capio-server}/utils/signals.hpp (94%) rename {src/server => capio-server}/utils/types.hpp (100%) rename {docker-development => scripts/docker-development}/build-and-startup.sh (77%) rename {docker-development => scripts/docker-development}/docker-compose.yml (100%) delete mode 100644 src/server/client-manager/request_handler_engine.hpp delete mode 100644 src/server/communication-service/data_plane/MTCL_backend.hpp delete mode 100644 src/server/file-manager/file_manager.hpp delete mode 100644 src/server/file-manager/fs_monitor.hpp delete mode 100644 src/server/storage-service/CapioFile/CapioFile.hpp delete mode 100644 src/server/storage-service/CapioFile/CapioRemoteFile.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 98e25d167..6e78276fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,8 +78,8 @@ ENDIF (CAPIO_LOG) ##################################### # Include files and directories ##################################### -file(GLOB_RECURSE CAPIO_COMMON_HEADERS "src/common/capio/*.hpp") -include_directories(src/common) +file(GLOB_RECURSE CAPIO_COMMON_HEADERS "capio-common/capio/*.hpp") +include_directories(${PROJECT_SOURCE_DIR}/capio-common) IF (CAPIO_LOG AND CMAKE_BUILD_TYPE STREQUAL "Debug") include_directories("${PROJECT_BINARY_DIR}/include/syscall") @@ -88,8 +88,8 @@ ENDIF (CAPIO_LOG AND CMAKE_BUILD_TYPE STREQUAL "Debug") ##################################### # Targets ##################################### -add_subdirectory(src/posix) -add_subdirectory(src/server) +add_subdirectory(capio-posix) +add_subdirectory(capio-server) ##################################### # Install capiorun diff --git a/src/common/capio/constants.hpp b/capio-common/capio/constants.hpp similarity index 100% rename from src/common/capio/constants.hpp rename to capio-common/capio/constants.hpp diff --git a/src/common/capio/env.hpp b/capio-common/capio/env.hpp similarity index 72% rename from src/common/capio/env.hpp rename to capio-common/capio/env.hpp index 6f419da7f..e4f509ef5 100644 --- a/src/common/capio/env.hpp +++ b/capio-common/capio/env.hpp @@ -9,7 +9,9 @@ #include +#ifndef __CAPIO_POSIX #include +#endif #include "logger.hpp" #include "syscall.hpp" @@ -111,4 +113,41 @@ inline std::string get_capio_workflow_name() { return name; } + + +inline long get_cache_lines() { + START_LOG(capio_syscall(SYS_gettid), "call()"); + static long data_bufs_size = -1; + if (data_bufs_size == -1) { + LOG("Value not set. getting value"); + char *value = std::getenv("CAPIO_CACHE_LINES"); + if (value != nullptr) { + LOG("Getting value from environment variable"); + data_bufs_size = strtol(value, nullptr, 10); + } else { + LOG("Getting default value"); + data_bufs_size = CAPIO_CACHE_LINES_DEFAULT; + } + } + LOG("data_bufs_size=%ld", data_bufs_size); + return data_bufs_size; +} + +inline long get_cache_line_size() { + START_LOG(capio_syscall(SYS_gettid), "call()"); + static long data_bufs_count = -1; + if (data_bufs_count == -1) { + LOG("Value not set. getting value"); + char *value = std::getenv("CAPIO_CACHE_LINE_SIZE"); + if (value != nullptr) { + LOG("Getting value from environment variable"); + data_bufs_count = strtol(value, nullptr, 10); + } else { + LOG("Getting default value"); + data_bufs_count = CAPIO_CACHE_LINE_SIZE_DEFAULT; + } + } + LOG("data_bufs_count=%ld", data_bufs_count); + return data_bufs_count; +} #endif // CAPIO_COMMON_ENV_HPP \ No newline at end of file diff --git a/src/common/capio/filesystem.hpp b/capio-common/capio/filesystem.hpp similarity index 100% rename from src/common/capio/filesystem.hpp rename to capio-common/capio/filesystem.hpp diff --git a/src/common/capio/logger.hpp b/capio-common/capio/logger.hpp similarity index 100% rename from src/common/capio/logger.hpp rename to capio-common/capio/logger.hpp diff --git a/src/common/capio/queue.hpp b/capio-common/capio/queue.hpp similarity index 100% rename from src/common/capio/queue.hpp rename to capio-common/capio/queue.hpp diff --git a/src/common/capio/requests.hpp b/capio-common/capio/requests.hpp similarity index 100% rename from src/common/capio/requests.hpp rename to capio-common/capio/requests.hpp diff --git a/src/common/capio/response_queue.hpp b/capio-common/capio/response_queue.hpp similarity index 100% rename from src/common/capio/response_queue.hpp rename to capio-common/capio/response_queue.hpp diff --git a/src/common/capio/semaphore.hpp b/capio-common/capio/semaphore.hpp similarity index 100% rename from src/common/capio/semaphore.hpp rename to capio-common/capio/semaphore.hpp diff --git a/src/common/capio/shm.hpp b/capio-common/capio/shm.hpp similarity index 100% rename from src/common/capio/shm.hpp rename to capio-common/capio/shm.hpp diff --git a/src/common/capio/syscall.hpp b/capio-common/capio/syscall.hpp similarity index 100% rename from src/common/capio/syscall.hpp rename to capio-common/capio/syscall.hpp diff --git a/src/posix/CMakeLists.txt b/capio-posix/CMakeLists.txt similarity index 100% rename from src/posix/CMakeLists.txt rename to capio-posix/CMakeLists.txt diff --git a/src/posix/handlers.hpp b/capio-posix/handlers.hpp similarity index 100% rename from src/posix/handlers.hpp rename to capio-posix/handlers.hpp diff --git a/src/posix/handlers/access.hpp b/capio-posix/handlers/access.hpp similarity index 100% rename from src/posix/handlers/access.hpp rename to capio-posix/handlers/access.hpp diff --git a/src/posix/handlers/chdir.hpp b/capio-posix/handlers/chdir.hpp similarity index 100% rename from src/posix/handlers/chdir.hpp rename to capio-posix/handlers/chdir.hpp diff --git a/src/posix/handlers/close.hpp b/capio-posix/handlers/close.hpp similarity index 100% rename from src/posix/handlers/close.hpp rename to capio-posix/handlers/close.hpp diff --git a/src/posix/handlers/copy_file_range.hpp b/capio-posix/handlers/copy_file_range.hpp similarity index 100% rename from src/posix/handlers/copy_file_range.hpp rename to capio-posix/handlers/copy_file_range.hpp diff --git a/src/posix/handlers/dup.hpp b/capio-posix/handlers/dup.hpp similarity index 100% rename from src/posix/handlers/dup.hpp rename to capio-posix/handlers/dup.hpp diff --git a/src/posix/handlers/execve.hpp b/capio-posix/handlers/execve.hpp similarity index 100% rename from src/posix/handlers/execve.hpp rename to capio-posix/handlers/execve.hpp diff --git a/src/posix/handlers/exit.hpp b/capio-posix/handlers/exit.hpp similarity index 100% rename from src/posix/handlers/exit.hpp rename to capio-posix/handlers/exit.hpp diff --git a/src/posix/handlers/fchmod.hpp b/capio-posix/handlers/fchmod.hpp similarity index 100% rename from src/posix/handlers/fchmod.hpp rename to capio-posix/handlers/fchmod.hpp diff --git a/src/posix/handlers/fchown.hpp b/capio-posix/handlers/fchown.hpp similarity index 100% rename from src/posix/handlers/fchown.hpp rename to capio-posix/handlers/fchown.hpp diff --git a/src/posix/handlers/fcntl.hpp b/capio-posix/handlers/fcntl.hpp similarity index 100% rename from src/posix/handlers/fcntl.hpp rename to capio-posix/handlers/fcntl.hpp diff --git a/src/posix/handlers/fgetxattr.hpp b/capio-posix/handlers/fgetxattr.hpp similarity index 100% rename from src/posix/handlers/fgetxattr.hpp rename to capio-posix/handlers/fgetxattr.hpp diff --git a/src/posix/handlers/fork.hpp b/capio-posix/handlers/fork.hpp similarity index 100% rename from src/posix/handlers/fork.hpp rename to capio-posix/handlers/fork.hpp diff --git a/src/posix/handlers/getcwd.hpp b/capio-posix/handlers/getcwd.hpp similarity index 100% rename from src/posix/handlers/getcwd.hpp rename to capio-posix/handlers/getcwd.hpp diff --git a/src/posix/handlers/ioctl.hpp b/capio-posix/handlers/ioctl.hpp similarity index 100% rename from src/posix/handlers/ioctl.hpp rename to capio-posix/handlers/ioctl.hpp diff --git a/src/posix/handlers/lseek.hpp b/capio-posix/handlers/lseek.hpp similarity index 100% rename from src/posix/handlers/lseek.hpp rename to capio-posix/handlers/lseek.hpp diff --git a/src/posix/handlers/mkdir.hpp b/capio-posix/handlers/mkdir.hpp similarity index 100% rename from src/posix/handlers/mkdir.hpp rename to capio-posix/handlers/mkdir.hpp diff --git a/src/posix/handlers/open.hpp b/capio-posix/handlers/open.hpp similarity index 100% rename from src/posix/handlers/open.hpp rename to capio-posix/handlers/open.hpp diff --git a/src/posix/handlers/posix_readdir.hpp b/capio-posix/handlers/posix_readdir.hpp similarity index 100% rename from src/posix/handlers/posix_readdir.hpp rename to capio-posix/handlers/posix_readdir.hpp diff --git a/src/posix/handlers/read.hpp b/capio-posix/handlers/read.hpp similarity index 100% rename from src/posix/handlers/read.hpp rename to capio-posix/handlers/read.hpp diff --git a/src/posix/handlers/rename.hpp b/capio-posix/handlers/rename.hpp similarity index 100% rename from src/posix/handlers/rename.hpp rename to capio-posix/handlers/rename.hpp diff --git a/src/posix/handlers/stat.hpp b/capio-posix/handlers/stat.hpp similarity index 100% rename from src/posix/handlers/stat.hpp rename to capio-posix/handlers/stat.hpp diff --git a/src/posix/handlers/statfs.hpp b/capio-posix/handlers/statfs.hpp similarity index 100% rename from src/posix/handlers/statfs.hpp rename to capio-posix/handlers/statfs.hpp diff --git a/src/posix/handlers/statx.hpp b/capio-posix/handlers/statx.hpp similarity index 100% rename from src/posix/handlers/statx.hpp rename to capio-posix/handlers/statx.hpp diff --git a/src/posix/handlers/unlink.hpp b/capio-posix/handlers/unlink.hpp similarity index 100% rename from src/posix/handlers/unlink.hpp rename to capio-posix/handlers/unlink.hpp diff --git a/src/posix/handlers/write.hpp b/capio-posix/handlers/write.hpp similarity index 100% rename from src/posix/handlers/write.hpp rename to capio-posix/handlers/write.hpp diff --git a/src/posix/libcapio_posix.cpp b/capio-posix/libcapio_posix.cpp similarity index 100% rename from src/posix/libcapio_posix.cpp rename to capio-posix/libcapio_posix.cpp diff --git a/src/posix/readme.md b/capio-posix/readme.md similarity index 100% rename from src/posix/readme.md rename to capio-posix/readme.md diff --git a/src/posix/syscall_intercept/CMakeLists.txt b/capio-posix/syscall_intercept/CMakeLists.txt similarity index 100% rename from src/posix/syscall_intercept/CMakeLists.txt rename to capio-posix/syscall_intercept/CMakeLists.txt diff --git a/src/posix/utils/cache.hpp b/capio-posix/utils/cache.hpp similarity index 100% rename from src/posix/utils/cache.hpp rename to capio-posix/utils/cache.hpp diff --git a/src/posix/utils/cache/consent_request_cache.hpp b/capio-posix/utils/cache/consent_request_cache.hpp similarity index 100% rename from src/posix/utils/cache/consent_request_cache.hpp rename to capio-posix/utils/cache/consent_request_cache.hpp diff --git a/src/posix/utils/cache/read_request_cache_fs.hpp b/capio-posix/utils/cache/read_request_cache_fs.hpp similarity index 100% rename from src/posix/utils/cache/read_request_cache_fs.hpp rename to capio-posix/utils/cache/read_request_cache_fs.hpp diff --git a/src/posix/utils/cache/read_request_cache_mem.hpp b/capio-posix/utils/cache/read_request_cache_mem.hpp similarity index 100% rename from src/posix/utils/cache/read_request_cache_mem.hpp rename to capio-posix/utils/cache/read_request_cache_mem.hpp diff --git a/src/posix/utils/cache/write_request_cache_fs.hpp b/capio-posix/utils/cache/write_request_cache_fs.hpp similarity index 100% rename from src/posix/utils/cache/write_request_cache_fs.hpp rename to capio-posix/utils/cache/write_request_cache_fs.hpp diff --git a/src/posix/utils/cache/write_request_cache_mem.hpp b/capio-posix/utils/cache/write_request_cache_mem.hpp similarity index 100% rename from src/posix/utils/cache/write_request_cache_mem.hpp rename to capio-posix/utils/cache/write_request_cache_mem.hpp diff --git a/src/posix/utils/clone.hpp b/capio-posix/utils/clone.hpp similarity index 100% rename from src/posix/utils/clone.hpp rename to capio-posix/utils/clone.hpp diff --git a/src/posix/utils/common.hpp b/capio-posix/utils/common.hpp similarity index 100% rename from src/posix/utils/common.hpp rename to capio-posix/utils/common.hpp diff --git a/src/posix/utils/env.hpp b/capio-posix/utils/env.hpp similarity index 61% rename from src/posix/utils/env.hpp rename to capio-posix/utils/env.hpp index 5bfa2891e..4c5711979 100644 --- a/src/posix/utils/env.hpp +++ b/capio-posix/utils/env.hpp @@ -24,41 +24,6 @@ inline capio_off64_t get_capio_write_cache_size() { return cache_size; } -inline long get_cache_lines() { - START_LOG(capio_syscall(SYS_gettid), "call()"); - static long data_bufs_size = -1; - if (data_bufs_size == -1) { - LOG("Value not set. getting value"); - char *value = std::getenv("CAPIO_CACHE_LINES"); - if (value != nullptr) { - LOG("Getting value from environment variable"); - data_bufs_size = strtol(value, nullptr, 10); - } else { - LOG("Getting default value"); - data_bufs_size = CAPIO_CACHE_LINES_DEFAULT; - } - } - LOG("data_bufs_size=%ld", data_bufs_size); - return data_bufs_size; -} - -inline long get_cache_line_size() { - START_LOG(capio_syscall(SYS_gettid), "call()"); - static long data_bufs_count = -1; - if (data_bufs_count == -1) { - LOG("Value not set. getting value"); - char *value = std::getenv("CAPIO_CACHE_LINE_SIZE"); - if (value != nullptr) { - LOG("Getting value from environment variable"); - data_bufs_count = strtol(value, nullptr, 10); - } else { - LOG("Getting default value"); - data_bufs_count = CAPIO_CACHE_LINE_SIZE_DEFAULT; - } - } - LOG("data_bufs_count=%ld", data_bufs_count); - return data_bufs_count; -} inline long get_posix_read_cache_line_size() { START_LOG(capio_syscall(SYS_gettid), "call()"); diff --git a/src/posix/utils/filesystem.hpp b/capio-posix/utils/filesystem.hpp similarity index 100% rename from src/posix/utils/filesystem.hpp rename to capio-posix/utils/filesystem.hpp diff --git a/src/posix/utils/requests.hpp b/capio-posix/utils/requests.hpp similarity index 100% rename from src/posix/utils/requests.hpp rename to capio-posix/utils/requests.hpp diff --git a/src/posix/utils/snapshot.hpp b/capio-posix/utils/snapshot.hpp similarity index 100% rename from src/posix/utils/snapshot.hpp rename to capio-posix/utils/snapshot.hpp diff --git a/src/posix/utils/storage.hpp b/capio-posix/utils/storage.hpp similarity index 100% rename from src/posix/utils/storage.hpp rename to capio-posix/utils/storage.hpp diff --git a/src/posix/utils/types.hpp b/capio-posix/utils/types.hpp similarity index 100% rename from src/posix/utils/types.hpp rename to capio-posix/utils/types.hpp diff --git a/src/server/CMakeLists.txt b/capio-server/CMakeLists.txt similarity index 74% rename from src/server/CMakeLists.txt rename to capio-server/CMakeLists.txt index f3eb934af..a5cc2e6ec 100644 --- a/src/server/CMakeLists.txt +++ b/capio-server/CMakeLists.txt @@ -2,11 +2,9 @@ # Target information ##################################### set(TARGET_NAME capio_server) -set(TARGET_INCLUDE_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}) -set(TARGET_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/capio_server.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/capio_cl_engine.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/json_parser.cpp +set(TARGET_INCLUDE_FOLDER .) +file(GLOB_RECURSE TARGET_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" ) ##################################### @@ -31,26 +29,6 @@ FetchContent_Declare( GIT_TAG fbd8aa924b916c6578963af315fdb5f10c3969ad ) -##################################### -# Add MTCL dependencies -##################################### -#find_package(UCX) - -#if (ucx_FOUND) -# message(STATUS "Enabling UCX for MTCL backend") -# target_compile_definitions(mtcl ENABLE_UCX) -#else () -# message(STATUS "Warning: UCX has not been found, and as such it will not be an available MTCL backend.") -#endif () - - -#find_package(MPI) -#if (MPI_FOUND) -# message(STATUS "Enabling MPI for MTCL backend") -# target_compile_definitions(mtcl ENABLE_MPI) -#else () -# message(STATUS "Warning: MPI has not been found, and as such it will not be an available MTCL backend.") -#endif () FetchContent_MakeAvailable(args simdjson mtcl) diff --git a/src/server/capio_server.cpp b/capio-server/capio_server.cpp similarity index 79% rename from src/server/capio_server.cpp rename to capio-server/capio_server.cpp index 564fe54dc..e9faef1dd 100644 --- a/src/server/capio_server.cpp +++ b/capio-server/capio_server.cpp @@ -1,21 +1,20 @@ -#include -#include -#include -#include -#include - #include #include #include #include #include +#include +#include #include #include #include #include +#include +#include #include #include #include +#include #include #include #include @@ -28,19 +27,21 @@ #include "capio/logger.hpp" #include "capio/semaphore.hpp" -#include "client-manager/request_handler_engine.hpp" -#include "utils/signals.hpp" -#include "storage-service/capio_storage_service.hpp" -#include "file-manager/file_manager.hpp" -#include "communication-service/CapioCommunicationService.hpp" -#include +#include +#include +#include +#include +#include +#include +#include + -#include "include/capio-cl-engine/json_parser.hpp" -#include "include/capio-cl-engine/capio_cl_engine.hpp" +#include +#include "utils/signals.hpp" int main(int argc, char **argv) { std::cout << CAPIO_LOG_SERVER_BANNER; @@ -59,6 +60,7 @@ int main(int argc, char **argv) { shm_canary = new CapioShmCanary(capio_global_configuration->workflow_name); file_manager = new CapioFileManager(); fs_monitor = new FileSystemMonitor(); + client_manager = new ClientManager(); request_handlers_engine = new RequestHandlerEngine(); storage_service = new CapioStorageService(); @@ -70,5 +72,5 @@ int main(int argc, char **argv) { sig_term_handler(SIGTERM, nullptr, nullptr); - return 0; + exit(EXIT_SUCCESS); } \ No newline at end of file diff --git a/src/server/include/capio-cl-engine/capio_cl_engine.hpp b/capio-server/include/capio-cl-engine/capio_cl_engine.hpp similarity index 98% rename from src/server/include/capio-cl-engine/capio_cl_engine.hpp rename to capio-server/include/capio-cl-engine/capio_cl_engine.hpp index db3101bf9..6337c5dde 100644 --- a/src/server/include/capio-cl-engine/capio_cl_engine.hpp +++ b/capio-server/include/capio-cl-engine/capio_cl_engine.hpp @@ -1,7 +1,7 @@ #ifndef CAPIO_ENGINE_HPP #define CAPIO_ENGINE_HPP -#include "client-manager/client_manager.hpp" +#include #include #include diff --git a/src/server/include/capio-cl-engine/json_parser.hpp b/capio-server/include/capio-cl-engine/json_parser.hpp similarity index 95% rename from src/server/include/capio-cl-engine/json_parser.hpp rename to capio-server/include/capio-cl-engine/json_parser.hpp index b71ac0228..5262056b5 100644 --- a/src/server/include/capio-cl-engine/json_parser.hpp +++ b/capio-server/include/capio-cl-engine/json_parser.hpp @@ -2,6 +2,8 @@ #define JSON_PARSER_HPP #include "capio/constants.hpp" +#include + /** * @brief Contains the code to parse a JSON based CAPIO-CL configuration file * diff --git a/capio-server/include/client-manager/client_manager.hpp b/capio-server/include/client-manager/client_manager.hpp new file mode 100644 index 000000000..60c70878b --- /dev/null +++ b/capio-server/include/client-manager/client_manager.hpp @@ -0,0 +1,77 @@ +#ifndef CLIENT_MANAGER_HPP +#define CLIENT_MANAGER_HPP +#include +#include +#include +#include + +/** + * @brief Class to handle libcapio_posix clients applications + */ +class ClientManager { + std::unordered_map *bufs_response; + std::unordered_map *app_names; + + /** + * Files that are produced by a given pid. Used for Commit On Termination fallback rule + */ + std::unordered_map *> *files_created_by_producer; + + public: + ClientManager(); + + ~ClientManager(); + + /** + * Add a new response buffer for thread @param tid + * @param tid + * @return + */ + void register_client(const std::string &app_name, pid_t tid) const; + + /** + * Delete the response buffer associated with thread @param tid + * @param tid + * @return + */ + void remove_client(pid_t tid) const; + + /** + * Write offset to response buffer of process @param tid + * @param tid + * @param offset + * @return + */ + void reply_to_client(const pid_t tid, const capio_off64_t offset) const; + + /** + * @brief Add a file that is not yet ready to be consumed by a process to a list of files + * waiting to be ready + * + * @param tid + * @param path + */ + void register_produced_file(pid_t tid, std::string &path) const; + + /** + * @brief Get the files that a given pid is waiting to be produced + * + * @param tid + * @return auto + */ + [[nodiscard]] std::vector *get_produced_files(pid_t tid) const; + + /** + * @brief Get the app name given a process pid + * + * @param tid + * @return std::string + */ + [[nodiscard]] std::string get_app_name(pid_t tid) const; + + size_t get_connected_posix_client(); +}; + +inline ClientManager *client_manager; + +#endif // CLIENT_MANAGER_HPP \ No newline at end of file diff --git a/capio-server/include/client-manager/handlers.hpp b/capio-server/include/client-manager/handlers.hpp new file mode 100644 index 000000000..5c0f08073 --- /dev/null +++ b/capio-server/include/client-manager/handlers.hpp @@ -0,0 +1,97 @@ +#ifndef HANDLERS_HPP +#define HANDLERS_HPP + +/** + * @brief Handle the close systemcall + * + * @param str raw request as read from the shared memory interface stripped of the request number + * (first parameter of the request) + */ +void close_handler(const char *const str); + +/** + * @brief Handle the consent to proceed request. This handler only checks whether the conditions for + * a systemcall to continue are met. + * + * @param str raw request as read from the shared memory interface stripped of the request number + * (first parameter of the request) + */ +void consent_to_proceed_handler(const char *const str); + +/** + * @brief Handle the create systemcall + * + * @param str raw request as read from the shared memory interface stripped of the request number + * (first parameter of the request) + */ +void create_handler(const char *const str); + +/** + * @brief Handle the exit systemcall + * + * @param str raw request as read from the shared memory interface stripped of the request number + * (first parameter of the request) + */ +void exit_handler(const char *const str); + +/** + * @brief Handle the exit systemcall + * + * @param str raw request as read from the shared memory interface stripped of the request number + * (first parameter of the request) + */ +void files_to_store_in_memory_handler(const char *const str); + +/** + * @brief Perform handshake while providing the posix application name + * + * @param str raw request as read from the shared memory interface stripped of the request number + * (first parameter of the request) + */ +void handshake_handler(const char *const str); + +/** + * @brief Handle the open systemcall + * + * @param str raw request as read from the shared memory interface stripped of the request number + * (first parameter of the request) + */ +void open_handler(const char *const str); + +/** +* +*/ +void posix_readdir_handler(const char *const str); + +/** + * @brief Handle the read systemcall + * + * @param str raw request as read from the shared memory interface stripped of the request number + * (first parameter of the request) + */ +void read_handler(const char *const str); + +void read_mem_handler(const char *const str); + + +/** + * @brief Handle the rename systemcall + * + * @param str raw request as read from the shared memory interface stripped of the request number + * (first parameter of the request) + */ +void rename_handler(const char *const str); + +/** + * @brief Handle the write systemcall + * + * @param str raw request as read from the shared memory interface stripped of the request number + * (first parameter of the request) + */ +void write_handler(const char *const str); + +void write_mem_handler(const char *const str); + + + +#endif //HANDLERS_HPP diff --git a/capio-server/include/client-manager/request_handler_engine.hpp b/capio-server/include/client-manager/request_handler_engine.hpp new file mode 100644 index 000000000..ec9e26b5b --- /dev/null +++ b/capio-server/include/client-manager/request_handler_engine.hpp @@ -0,0 +1,41 @@ +#ifndef CAPIO_CL_ENGINE_MAIN_HPP +#define CAPIO_CL_ENGINE_MAIN_HPP + +#include "capio/requests.hpp" + +#include +#include + +/** + * @brief Class that handles the system calls received from the posix client application + * + */ +class RequestHandlerEngine { + std::array request_handlers{}; + CSBufRequest_t *buf_requests; + + static constexpr std::array build_request_handlers_table(); + + /** + * Read next incoming request into @param str and returns the request code + * @param str + * @return request code + */ + inline auto read_next_request(char *str) const; + + public: + explicit RequestHandlerEngine(); + + ~RequestHandlerEngine(); + + /** + * @brief Start the main loop on the main thread that will read each request one by one from all + * the posix clients (aggregated) and handle the response + * + */ + void start() const; +}; + +inline RequestHandlerEngine *request_handlers_engine; + +#endif // CAPIO_CL_ENGINE_MAIN_HPP \ No newline at end of file diff --git a/capio-server/include/communication-service/capio_communication_service.hpp b/capio-server/include/communication-service/capio_communication_service.hpp new file mode 100644 index 000000000..75dbb4d88 --- /dev/null +++ b/capio-server/include/communication-service/capio_communication_service.hpp @@ -0,0 +1,17 @@ +#ifndef CAPIOCOMMUNICATIONSERVICE_HPP +#define CAPIOCOMMUNICATIONSERVICE_HPP + +#include + +class CapioCommunicationService { + + public: + ~CapioCommunicationService(); + + CapioCommunicationService(std::string &backend_name, const int port, + const std::string &control_backend_name); +}; + +inline CapioCommunicationService *capio_communication_service; + +#endif // CAPIOCOMMUNICATIONSERVICE_HPP diff --git a/src/server/communication-service/control_plane/capio_control_plane.hpp b/capio-server/include/communication-service/control-plane/capio_control_plane.hpp similarity index 94% rename from src/server/communication-service/control_plane/capio_control_plane.hpp rename to capio-server/include/communication-service/control-plane/capio_control_plane.hpp index 6375593e5..4a74581aa 100644 --- a/src/server/communication-service/control_plane/capio_control_plane.hpp +++ b/capio-server/include/communication-service/control-plane/capio_control_plane.hpp @@ -1,10 +1,9 @@ #ifndef CAPIO_CONTROL_PLANE_HPP #define CAPIO_CONTROL_PLANE_HPP - #include class CapioControlPlane { - public: +public: typedef enum { CREATE, DELETE, WRITE } event_type; virtual ~CapioControlPlane() = default; @@ -28,4 +27,4 @@ class CapioControlPlane { inline CapioControlPlane *capio_control_plane; -#endif // CAPIO_CONTROL_PLANE_HPP \ No newline at end of file +#endif //CAPIO_CONTROL_PLANE_HPP diff --git a/capio-server/include/communication-service/control-plane/fs_control_plane.hpp b/capio-server/include/communication-service/control-plane/fs_control_plane.hpp new file mode 100644 index 000000000..a5a73c784 --- /dev/null +++ b/capio-server/include/communication-service/control-plane/fs_control_plane.hpp @@ -0,0 +1,37 @@ +#ifndef FS_CONTROL_PLANE_HPP +#define FS_CONTROL_PLANE_HPP + +#include +#include +#include +#include +#include + +class FSControlPlane : public CapioControlPlane { + char ownHostname[HOST_NAME_MAX] = {0}; + int _backend_port; + bool *continue_execution; + std::thread *thread; + std::vector token_used_to_connect; + std::mutex *token_used_to_connect_mutex; + + void generate_aliveness_token(const int port) const ; + + void delete_aliveness_token(); + + /* + * Monitor the file system for the presence of tokens. + */ + static void fs_server_aliveness_detector_thread(const bool *continue_execution, + std::vector *token_used_to_connect, + std::mutex *token_used_to_connect_mutex); + + public: + explicit FSControlPlane(int backend_port) ; + + ~FSControlPlane() ; + + void notify_all(event_type event, const std::filesystem::path &path) ; +}; + +#endif //FS_CONTROL_PLANE_HPP diff --git a/capio-server/include/communication-service/control-plane/multicast_control_plane.hpp b/capio-server/include/communication-service/control-plane/multicast_control_plane.hpp new file mode 100644 index 000000000..ade6e4eb6 --- /dev/null +++ b/capio-server/include/communication-service/control-plane/multicast_control_plane.hpp @@ -0,0 +1,32 @@ +#ifndef MULTICAST_CONTROL_PLANE_HPP +#define MULTICAST_CONTROL_PLANE_HPP +#include +#include +#include +#include +#include + +class MulticastControlPlane : public CapioControlPlane { + bool *continue_execution; + std::thread *discovery_thread, *controlpl_incoming; + std::vector token_used_to_connect; + std::mutex *token_used_to_connect_mutex; + char ownHostname[HOST_NAME_MAX] = {0}; + + static void multicast_server_aliveness_thread(const bool *continue_execution, + std::vector *token_used_to_connect, + std::mutex *token_used_to_connect_mutex, + int dataplane_backend_port); + + + static void multicast_control_plane_incoming_thread(const bool *continue_execution) ; + + public: + explicit MulticastControlPlane(int dataplane_backend_port) ; + + ~MulticastControlPlane() override ; + + void notify_all(const event_type event, const std::filesystem::path &path) override; +}; + +#endif //MULTICAST_CONTROL_PLANE_HPP diff --git a/src/server/communication-service/data_plane/BackendInterface.hpp b/capio-server/include/communication-service/data-plane/backend_interface.hpp similarity index 93% rename from src/server/communication-service/data_plane/BackendInterface.hpp rename to capio-server/include/communication-service/data-plane/backend_interface.hpp index c0676ca7f..375fa93bb 100644 --- a/src/server/communication-service/data_plane/BackendInterface.hpp +++ b/capio-server/include/communication-service/data-plane/backend_interface.hpp @@ -1,7 +1,11 @@ -#ifndef CAPIOBACKEND_HPP -#define CAPIOBACKEND_HPP +#ifndef BACKEND_INTERFACE_HPP +#define BACKEND_INTERFACE_HPP #include "capio/constants.hpp" +#include +#include +#include +#include class NotImplementedBackendMethod : public std::exception { public: @@ -75,5 +79,4 @@ class NoBackend final : public BackendInterface { }; inline BackendInterface *capio_backend; - -#endif // CAPIOBACKEND_HPP \ No newline at end of file +#endif //BACKEND_INTERFACE_HPP diff --git a/capio-server/include/communication-service/data-plane/mtcl_backend.hpp b/capio-server/include/communication-service/data-plane/mtcl_backend.hpp new file mode 100644 index 000000000..96ef6eba8 --- /dev/null +++ b/capio-server/include/communication-service/data-plane/mtcl_backend.hpp @@ -0,0 +1,64 @@ +#ifndef MTCL_BACKEND_HPP +#define MTCL_BACKEND_HPP + +#include +#include +#include +#include + +/** + * This avoid to include the MTCL librari here as it is a header only library. + * this is equivalent to use extern in C but for class + */ +namespace MTCL { +class HandleUser; +} + +class MTCLBackend : public BackendInterface { + typedef enum { FROM_REMOTE, TO_REMOTE } CONN_HANDLER_ORIGIN; + + typedef std::tuple *, std::queue *, std::mutex *> + TransportUnitInterface; + std::unordered_map connected_hostnames_map; + std::string selfToken, connectedHostname, ownPort, usedProtocol; + char ownHostname[HOST_NAME_MAX] = {0}; + int thread_sleep_times = 0; + bool *continue_execution = new bool; + std::mutex *_guard; + std::thread *th; + std::vector connection_threads; + bool *terminate; + + static TransportUnit *receive_unit(MTCL::HandleUser *HandlerPointer); + + static void send_unit(MTCL::HandleUser *HandlerPointer, const TransportUnit *unit); + + /** + * This thread will handle connections towards a single target. + */ + void static server_connection_handler(MTCL::HandleUser HandlerPointer, + const std::string remote_hostname, const int sleep_time, + TransportUnitInterface interface, const bool *terminate, + CONN_HANDLER_ORIGIN source); + + void static incoming_connection_listener( + const bool *continue_execution, int sleep_time, + std::unordered_map *open_connections, + std::mutex *guard, std::vector *_connection_threads, bool *terminate); + + public: + void connect_to(std::string hostname_port) override; + + explicit MTCLBackend(const std::string &proto, const std::string &port, int sleep_time); + + ~MTCLBackend() override; + + std::string receive(char *buf, capio_off64_t *buf_size, capio_off64_t *start_offset) override; + + void send(const std::string &target, char *buf, uint64_t buf_size, const std::string &filepath, + const capio_off64_t start_offset) override; + + std::vector get_open_connections() override; +}; + +#endif // MTCL_BACKEND_HPP diff --git a/capio-server/include/communication-service/data-plane/transport_unit.hpp b/capio-server/include/communication-service/data-plane/transport_unit.hpp new file mode 100644 index 000000000..4e1e877fc --- /dev/null +++ b/capio-server/include/communication-service/data-plane/transport_unit.hpp @@ -0,0 +1,23 @@ +#ifndef TRANSPORT_UNIT_HPP +#define TRANSPORT_UNIT_HPP + +#include +#include + +class TransportUnit { +protected: + std::string _filepath; + char *_bytes{}; + capio_off64_t _buffer_size{}; + capio_off64_t _start_write_offset{}; + +public: + TransportUnit() = default; + + ~TransportUnit() { delete[] _bytes; } + + friend class MTCLBackend; +}; + + +#endif //TRANSPORT_UNIT_HPP diff --git a/capio-server/include/file-manager/file_manager.hpp b/capio-server/include/file-manager/file_manager.hpp new file mode 100644 index 000000000..13387664a --- /dev/null +++ b/capio-server/include/file-manager/file_manager.hpp @@ -0,0 +1,141 @@ +#ifndef FILE_MANAGER_HEADER_HPP +#define FILE_MANAGER_HEADER_HPP + +#include +#include +#include +#include + +inline std::mutex creation_mutex; +inline std::mutex data_mutex; +/** + * @brief Class that handle all the information related to the files handled by capio, as well + * metadata for such files. + * + */ +class CapioFileManager { + std::unordered_map> thread_awaiting_file_creation; + std::unordered_map> thread_awaiting_data; + + /** + * @brief Creates the directory structure for the metadata file and proceed to return the path + * pointing to the metadata token file. For improvements in performances, a hash map is included + * to cache the computed paths. For thread safety concerns, see + * https://en.cppreference.com/w/cpp/container#Thread_safety + * + * @param path real path of the file + * @return std::string with the translated capio token metadata path + */ + static std::string getAndCreateMetadataPath(const std::string &path); + + /** + * @brief Awakes all threads waiting for the creation of a file + * + * @param path file that has just been created + * @param pids + */ + static void _unlockThreadAwaitingCreation(const std::string &path, + const std::vector &pids); + + /** + * @brief Loop between all thread registered on the file path, and check for each + * one if enough data has been produced. If so, unlock and remove the thread + * + * @param path + * @param pids_awaiting + */ + static void _unlockThreadAwaitingData(const std::string &path, + std::unordered_map &pids_awaiting); + + public: + CapioFileManager() { + START_LOG(gettid(), "call()"); + server_println(CAPIO_SERVER_CLI_LOG_SERVER, "CapioFileManager initialization completed."); + } + + ~CapioFileManager() { + START_LOG(gettid(), "call()"); + server_println(CAPIO_SERVER_CLI_LOG_SERVER, "CapioFileManager cleanup completed."); + } + + /** + * @brief Get the file size + * + * @param path + * @return uintmax_t file size if file exists, 0 otherwise + */ + static uintmax_t get_file_size_if_exists(const std::filesystem::path &path); + static std::string getMetadataPath(const std::string &path); + + /** + * @brief Update the CAPIO metadata n_close option by adding one to the current value + * + * @param path + */ + static void increaseCloseCount(const std::filesystem::path &path); + + /** + * @brief Returns whether the file is committed or not + * + * @param path + * @return true if is committed + * @return false if it is not + */ + static bool isCommitted(const std::filesystem::path &path); + + /** + * @brief Set a CAPIO handled file to be committed + * + * @param path + */ + static void setCommitted(const std::filesystem::path &path); + + /** + * @brief Set all the files that are currently open, or have been open by a given process to be + * committed + * + * @param tid + */ + static void setCommitted(pid_t tid); + + /** + * @brief Register a process waiting on a file to exist and with a file size of at least the + * expected_size parameter. + * + * @param path + * @param tid + * @param expected_size + */ + void addThreadAwaitingData(const std::string &path, int tid, size_t expected_size); + + /** + * @brief Register a thread to the threads waiting for a file to exists (inside the + * CapioFSMonitor) for a given file path to exists + * + * @param path + * @param tid + */ + void addThreadAwaitingCreation(const std::string &path, pid_t tid); + + /** + * @brief Check for threads awaiting file creation and unlock threads waiting on them + * + */ + void checkFilesAwaitingCreation(); + + /** + * @brief check if there are threads waiting for data, and for each one of them check if the + * file has enough data + * + */ + void checkFileAwaitingData(); + + /** + * @brief commit directories that have NFILES inside them if their commit rule is n_files + */ + void checkDirectoriesNFiles() const; +}; + +inline CapioFileManager *file_manager; + +#endif // FILE_MANAGER_HEADER_HPP \ No newline at end of file diff --git a/capio-server/include/file-manager/fs_monitor.hpp b/capio-server/include/file-manager/fs_monitor.hpp new file mode 100644 index 000000000..fcdc44542 --- /dev/null +++ b/capio-server/include/file-manager/fs_monitor.hpp @@ -0,0 +1,37 @@ +#ifndef CAPIO_FS_FILE_SYSTEM_MONITOR_HPP +#define CAPIO_FS_FILE_SYSTEM_MONITOR_HPP +#include +#include +#include +/** + * @brief Class that monitors the composition of the CAPIO_DIR directory. + * + */ +class FileSystemMonitor { + std::thread *th; + + bool *continue_execution = new bool; + + static void print_message_error(const std::string &func, const std::exception &exception); + + public: + /** + * @brief Main thread execution loop. Main idea is to check + * whether the files exists on the file system. Then if they exists, wake both thread waiting + * for file existence and files waiting for data, as the check on the file size (ie. if there is + * enough data) is carried out by the CapioFileManager class and not by the file_system monitor + * component itself. At creation a thread is spawned that will continue until a process signals + * it to stop by setting the continue_execution parameter to false. + * + * @param continue_execution + */ + static void _main(const bool *continue_execution); + + explicit FileSystemMonitor() ; + + ~FileSystemMonitor(); +}; + +inline FileSystemMonitor *fs_monitor; + +#endif // CAPIO_FS_FILE_SYSTEM_MONITOR_HPP \ No newline at end of file diff --git a/capio-server/include/storage-service/capio_file.hpp b/capio-server/include/storage-service/capio_file.hpp new file mode 100644 index 000000000..3432fc918 --- /dev/null +++ b/capio-server/include/storage-service/capio_file.hpp @@ -0,0 +1,180 @@ +#ifndef CAPIO_FILE_HPP +#define CAPIO_FILE_HPP + +#include +#include +#include +#include +#include +#include + + +class CapioFile { +protected: + const std::string fileName; + std::size_t totalSize; + +public: + explicit CapioFile(const std::string &filePath) : fileName(filePath), totalSize(0) {}; + virtual ~CapioFile() = default; + + [[nodiscard]] std::size_t getSize() const { + START_LOG(gettid(), "call()"); + return totalSize; + } + + [[nodiscard]] const std::string &getFileName() const { return fileName; } + + /** + * Write data to a file stored inside the memory + * @param buffer buffer to store inside memory (i.e. content of the file) + * @param file_offset offset internal to the file + * @param buffer_length Size of the buffer. + */ + virtual std::size_t writeData(const char *buffer, std::size_t file_offset, + std::size_t buffer_length) = 0; + /** + * Read from Capio File + * @param buffer Buffer to read to + * @param file_offset Starting offset of read operation from CapioMemFile + * @param buffer_size Length of buffer + * @return number of bytes read from CapioMemoryFile + */ + virtual std::size_t readData(char *buffer, std::size_t file_offset, + std::size_t buffer_size) = 0; + + /** + * Store data inside the CapioMemoryFile by reading it from a SPSCQueue object. Behaves just + * like the writeData method + * @param queue + * @param offset + * @param length + */ + virtual void readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) = 0; + + /** + * Write the content of the capioFile to a SPSCQueue object + * @param queue + * @param offset + * @param length + * @return + */ + virtual std::size_t writeToQueue(SPSCQueue &queue, std::size_t offset, + std::size_t length) const = 0; +}; + + + +class CapioMemoryFile : public CapioFile { + std::map> memoryBlocks; + + // Static file sizes of file pages + static constexpr u_int32_t _pageSizeMB = 4; + static constexpr u_int64_t _pageSizeBytes = _pageSizeMB * 1024 * 1024; + + char *cross_page_buffer_view; + + /** + * Compute the offsets required to handle write operations onto CapioMemoryFile + * @param offset Offset from the start of the file, on which the write operation will begin + * @param length Size of the buffer that will be written into memory + * @return tuple + */ + static auto compute_offsets(const std::size_t offset, std::size_t length); + + /** + * Retrieve a block with memory already reserved at a given offset + * @param id + * @return + */ + std::vector &get_block(u_int64_t id) ; + + public: + explicit CapioMemoryFile(const std::string &filePath); + + ~CapioMemoryFile() ; + + /** + * Write data to a file stored inside the memory + * @param buffer buffer to store inside memory (i.e. content of the file) + * @param file_offset offset internal to the file + * @param buffer_length Size of the buffer. + */ + std::size_t writeData(const char *buffer, const std::size_t file_offset, + std::size_t buffer_length) override ; + + /** + * Read from Capio File + * @param buffer Buffer to read to + * @param file_offset Starting offset of read operation from CapioMemFile + * @param buffer_size Length of buffer + * @return number of bytes read from CapioMemoryFile + */ + std::size_t readData(char *buffer, std::size_t file_offset, std::size_t buffer_size) ; + + /** + * Store data inside the CapioMemoryFile by reading it from a SPSCQueue object. Behaves just + * like the writeData method + * @param queue + * @param offset + * @param length + */ + void readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) override ; + + /** + * Write the content of the capioFile to a SPSCQueue object + * @param queue + * @param offset + * @param length + * @return + */ + std::size_t writeToQueue(SPSCQueue &queue, std::size_t offset, + std::size_t length) const override ; +}; + + +class CapioRemoteFile : public CapioFile { +public: + explicit CapioRemoteFile(const std::string &filePath); + + ~CapioRemoteFile() override ; + + /** + * Write data to a file stored inside the memory + * @param buffer buffer to store inside memory (i.e. content of the file) + * @param file_offset offset internal to the file + * @param buffer_length Size of the buffer. + */ + std::size_t writeData(const char *buffer, const std::size_t file_offset, + std::size_t buffer_length) override ; + + /** + * Read from Capio File + * @param buffer Buffer to read to + * @param file_offset Starting offset of read operation from CapioMemFile + * @param buffer_size Length of buffer + * @return number of bytes read from CapioMemoryFile + */ + std::size_t readData(char *buffer, std::size_t file_offset, std::size_t buffer_size) ; + + /** + * Store data inside the CapioMemoryFile by reading it from a SPSCQueue object. Behaves just + * like the writeData method + * @param queue + * @param offset + * @param length + */ + void readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) override ; + + /** + * Write the content of the capioFile to a SPSCQueue object + * @param queue + * @param offset + * @param length + * @return + */ + std::size_t writeToQueue(SPSCQueue &queue, std::size_t offset, + std::size_t length) const override ; +}; + +#endif //CAPIO_FILE_HPP diff --git a/capio-server/include/storage-service/capio_storage_service.hpp b/capio-server/include/storage-service/capio_storage_service.hpp new file mode 100644 index 000000000..7da5dd8e5 --- /dev/null +++ b/capio-server/include/storage-service/capio_storage_service.hpp @@ -0,0 +1,115 @@ +#ifndef CAPIO_STORAGE_SERVICE_H +#define CAPIO_STORAGE_SERVICE_H + +#include +#include +#include + +class CapioStorageService { + // TODO: put all of this conde on a different thread + + std::unordered_map *_client_to_server_queue; + std::unordered_map *_server_to_client_queue; + std::unordered_map *_stored_files; + + std::unordered_map>> + *_threads_waiting_for_memory_data; + + /** + * Return a file if exists. if not, create it and then return it + * @param file_name + * @return + */ + [[nodiscard]] auto getFile(const std::string &file_name) const ; + + public: + CapioStorageService() ; + + ~CapioStorageService() ; + + void createMemoryFile(const std::string &file_name) const ; + + /** + * Create a CapioRemoteFile, after checking that an instance of CapioMemoryFile (meaning a local + * file) is not present + * @param file_name file path + */ + void createRemoteFile(const std::string &file_name) const ; + + void deleteFile(const std::string &file_name) const ; + + /** + * Notify the occurrence of an operation on a given file, for which other servers running at a + * certain point might be required to know. This function is used to allow CAPIO to function in + * the event that a distributed file system (or at least a shared directory) is not available + */ + void notifyEvent(const std::string &event_name, const std::filesystem::path &filename) const ; + + /** + * Add a new thread in the list of thhreads awaiting for expected_size to be available + * @param tid + * @param path + * @param offset + * @param size + */ + void addThreadWaitingForData(pid_t tid, const std::string &path, capio_off64_t offset, + capio_off64_t size) const ; + + void check_and_unlock_thread_awaiting_data(const std::string &path) ; + + /** + * Return size of given path as contained inside memory + * @param path + * @return + */ + size_t sizeOf(const std::string &path) const ; + + /** + * Initialize a new client data structure + * @param app_name + * @param pid + */ + void register_client(const std::string &app_name, const pid_t pid) const ; + + /** + * Send the file content to a client application + * @param pid + * @param file + * @param offset + * @param size + */ + void reply_to_client(pid_t pid, const std::string &file, capio_off64_t offset, + capio_off64_t size) const ; + + /** + * Send raw data to client without fetching from the storage manager itself + * @param pid + * @param data + * @param len + */ + void reply_to_client_raw(pid_t pid, const char *data, const capio_off64_t len) const; + + /** + * Receive the file content from the client application + * @param tid + * @param file + * @param offset + * @param size + */ + void recive_from_client(pid_t tid, const std::string &file, capio_off64_t offset, + off64_t size) const; + + /** + * Return a list of regex used to match files that need to be stored inside memory first + * to a posix application + * @param pid + * @return + */ + [[nodiscard]] size_t sendFilesToStoreInMemory(const long pid) const; + + void remove_client(const pid_t pid) const; +}; + +inline CapioStorageService *storage_service; + +#endif // CAPIO_STORAGE_SERVICE_H \ No newline at end of file diff --git a/src/server/src/capio_cl_engine.cpp b/capio-server/src/capio-cl-engine/capio_cl_engine.cpp similarity index 100% rename from src/server/src/capio_cl_engine.cpp rename to capio-server/src/capio-cl-engine/capio_cl_engine.cpp diff --git a/src/server/src/json_parser.cpp b/capio-server/src/capio-cl-engine/json_parser.cpp similarity index 100% rename from src/server/src/json_parser.cpp rename to capio-server/src/capio-cl-engine/json_parser.cpp diff --git a/src/server/client-manager/client_manager.hpp b/capio-server/src/client-manager/client_manager.cpp similarity index 56% rename from src/server/client-manager/client_manager.hpp rename to capio-server/src/client-manager/client_manager.cpp index be4214186..79b964e6b 100644 --- a/src/server/client-manager/client_manager.hpp +++ b/capio-server/src/client-manager/client_manager.cpp @@ -1,24 +1,6 @@ -#ifndef CLIENT_MANAGER_HPP -#define CLIENT_MANAGER_HPP -#include -#include -#include -#include - -/** - * @brief Class to handle libcapio_posix clients applications - */ -class ClientManager { - std::unordered_map *bufs_response; - std::unordered_map *app_names; - - /** - * Files that are produced by a given pid. Used for Commit On Termination fallback rule - */ - std::unordered_map *> *files_created_by_producer; - - public: - ClientManager() { +#include + + ClientManager::ClientManager() { START_LOG(gettid(), "call()"); bufs_response = new std::unordered_map(); app_names = new std::unordered_map; @@ -26,7 +8,7 @@ class ClientManager { server_println(CAPIO_SERVER_CLI_LOG_SERVER, "ClientManager initialization completed."); } - ~ClientManager() { + ClientManager::~ClientManager() { START_LOG(gettid(), "call()"); delete bufs_response; delete app_names; @@ -34,12 +16,8 @@ class ClientManager { server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, "ClientManager cleanup completed."); } - /** - * Add a new response buffer for thread @param tid - * @param tid - * @return - */ - inline void register_client(const std::string &app_name, pid_t tid) const { + + void ClientManager::register_client(const std::string &app_name, pid_t tid) const { START_LOG(gettid(), "call(tid=%ld, app_name=%s)", tid, app_name.c_str()); // TODO: replace numbers with constexpr auto *p_buf_response = @@ -50,12 +28,8 @@ class ClientManager { files_created_by_producer->emplace(tid, new std::vector); } - /** - * Delete the response buffer associated with thread @param tid - * @param tid - * @return - */ - inline void remove_client(pid_t tid) const { + + void ClientManager::remove_client(pid_t tid) const { START_LOG(gettid(), "call(tid=%ld)", tid); if (const auto it_resp = bufs_response->find(tid); it_resp != bufs_response->end()) { delete it_resp->second; @@ -64,13 +38,8 @@ class ClientManager { files_created_by_producer->erase(tid); } - /** - * Write offset to response buffer of process @param tid - * @param tid - * @param offset - * @return - */ - void reply_to_client(const pid_t tid, const capio_off64_t offset) const { + + void ClientManager::reply_to_client(const pid_t tid, const capio_off64_t offset) const { START_LOG(gettid(), "call(tid=%ld, offset=%llu)", tid, offset); if (const auto out = bufs_response->find(tid); out != bufs_response->end()) { out->second->write(offset); @@ -79,14 +48,8 @@ class ClientManager { LOG("Err: no such buffer for provided tid"); } - /** - * @brief Add a file that is not yet ready to be consumed by a process to a list of files - * waiting to be ready - * - * @param tid - * @param path - */ - void register_produced_file(pid_t tid, std::string &path) const { + + void ClientManager::register_produced_file(pid_t tid, std::string &path) const { START_LOG(gettid(), "call(tid=%ld, path=%s)", tid, path.c_str()); if (const auto itm = files_created_by_producer->find(tid); itm != files_created_by_producer->end()) { @@ -96,13 +59,8 @@ class ClientManager { LOG("Error: tis is not present in files_created_by_producers map"); } - /** - * @brief Get the files that a given pid is waiting to be produced - * - * @param tid - * @return auto - */ - [[nodiscard]] auto get_produced_files(pid_t tid) const { + + std::vector * ClientManager::get_produced_files(pid_t tid) const { START_LOG(gettid(), "call(tid=%ld)", tid); if (const auto itm = files_created_by_producer->find(tid); itm == files_created_by_producer->end()) { @@ -111,13 +69,8 @@ class ClientManager { return files_created_by_producer->at(tid); } - /** - * @brief Get the app name given a process pid - * - * @param tid - * @return std::string - */ - [[nodiscard]] std::string get_app_name(pid_t tid) const { + + std::string ClientManager::get_app_name(pid_t tid) const { START_LOG(gettid(), "call(tid=%ld)", tid); if (const auto itm = app_names->find(tid); itm != app_names->end()) { return itm->second; @@ -125,9 +78,4 @@ class ClientManager { return CAPIO_DEFAULT_APP_NAME; } - inline auto get_connected_posix_client() { return bufs_response->size(); } -}; - -inline ClientManager *client_manager; - -#endif // CLIENT_MANAGER_HPP \ No newline at end of file + size_t ClientManager::get_connected_posix_client() { return bufs_response->size(); } \ No newline at end of file diff --git a/src/server/client-manager/handlers/close.hpp b/capio-server/src/client-manager/handlers/close.cpp similarity index 80% rename from src/server/client-manager/handlers/close.hpp rename to capio-server/src/client-manager/handlers/close.cpp index 34132a76a..154c2fb77 100644 --- a/src/server/client-manager/handlers/close.hpp +++ b/capio-server/src/client-manager/handlers/close.cpp @@ -1,13 +1,11 @@ -#ifndef CAPIO_CLOSE_HPP -#define CAPIO_CLOSE_HPP +#include +#include +#include +#include +#include -/** - * @brief Handle the close systemcall - * - * @param str raw request as read from the shared memory interface stripped of the request number - * (first parameter of the request) - */ -inline void close_handler(const char *const str) { + +void close_handler(const char *const str) { pid_t tid; char path[PATH_MAX]; sscanf(str, "%d %s", &tid, path); @@ -36,5 +34,3 @@ inline void close_handler(const char *const str) { } } } - -#endif // CAPIO_CLOSE_HPP \ No newline at end of file diff --git a/src/server/client-manager/handlers/consent.hpp b/capio-server/src/client-manager/handlers/consent.cpp similarity index 76% rename from src/server/client-manager/handlers/consent.hpp rename to capio-server/src/client-manager/handlers/consent.cpp index b8cc17d4c..37f6f8184 100644 --- a/src/server/client-manager/handlers/consent.hpp +++ b/capio-server/src/client-manager/handlers/consent.cpp @@ -1,14 +1,11 @@ -#ifndef CONSENT_HPP -#define CONSENT_HPP - -/** - * @brief Handle the consent to proceed request. This handler only checks whether the conditions for - * a systemcall to continue are met. - * - * @param str raw request as read from the shared memory interface stripped of the request number - * (first parameter of the request) - */ -inline void consent_to_proceed_handler(const char *const str) { +#include +#include +#include +#include +#include + + +void consent_to_proceed_handler(const char *const str) { pid_t tid; char path[1024], source_func[1024]; sscanf(str, "%d %s %s", &tid, path, source_func); @@ -49,5 +46,3 @@ inline void consent_to_proceed_handler(const char *const str) { path); file_manager->addThreadAwaitingData(path, tid, ULLONG_MAX); } - -#endif // CONSENT_HPP \ No newline at end of file diff --git a/src/server/client-manager/handlers/create.hpp b/capio-server/src/client-manager/handlers/create.cpp similarity index 59% rename from src/server/client-manager/handlers/create.hpp rename to capio-server/src/client-manager/handlers/create.cpp index 930a5bb02..087a0b8ad 100644 --- a/src/server/client-manager/handlers/create.hpp +++ b/capio-server/src/client-manager/handlers/create.cpp @@ -1,15 +1,12 @@ -#ifndef CAPIO_CREATE_HPP -#define CAPIO_CREATE_HPP -#include "communication-service/control_plane/capio_control_plane.hpp" -#include "storage-service/capio_storage_service.hpp" +#include +#include +#include +#include +#include +#include +#include -/** - * @brief Handle the create systemcall - * - * @param str raw request as read from the shared memory interface stripped of the request number - * (first parameter of the request) - */ -inline void create_handler(const char *const str) { +void create_handler(const char *const str) { pid_t tid, fd; char path[PATH_MAX]; sscanf(str, "%d %d %s", &tid, &fd, path); @@ -27,5 +24,3 @@ inline void create_handler(const char *const str) { storage_service->createMemoryFile(path); capio_control_plane->notify_all(CapioControlPlane::CREATE, path_str); } - -#endif // CAPIO_CREATE_HPP \ No newline at end of file diff --git a/src/server/client-manager/handlers/exit.hpp b/capio-server/src/client-manager/handlers/exit.cpp similarity index 62% rename from src/server/client-manager/handlers/exit.hpp rename to capio-server/src/client-manager/handlers/exit.cpp index 8bb55d11b..f6df212ff 100644 --- a/src/server/client-manager/handlers/exit.hpp +++ b/capio-server/src/client-manager/handlers/exit.cpp @@ -1,14 +1,7 @@ -#ifndef CAPIO_EXIT_HPP -#define CAPIO_EXIT_HPP -#include +#include +#include -/** - * @brief Handle the exit systemcall - * - * @param str raw request as read from the shared memory interface stripped of the request number - * (first parameter of the request) - */ -inline void exit_handler(const char *const str) { +void exit_handler(const char *const str) { // TODO: register files open for each tid ti register a close pid_t tid; sscanf(str, "%d", &tid); @@ -24,5 +17,3 @@ inline void exit_handler(const char *const str) { storage_service->remove_client(tid); client_manager->remove_client(tid); } - -#endif // CAPIO_EXIT_HPP \ No newline at end of file diff --git a/src/server/client-manager/handlers/files_in_memory.hpp b/capio-server/src/client-manager/handlers/files_in_memory.cpp similarity index 50% rename from src/server/client-manager/handlers/files_in_memory.hpp rename to capio-server/src/client-manager/handlers/files_in_memory.cpp index 802dc84d4..e09dba0e7 100644 --- a/src/server/client-manager/handlers/files_in_memory.hpp +++ b/capio-server/src/client-manager/handlers/files_in_memory.cpp @@ -1,13 +1,9 @@ -#ifndef FILES_IN_MEMORY_HPP -#define FILES_IN_MEMORY_HPP +#include +#include +#include +#include -/** - * @brief Handle the exit systemcall - * - * @param str raw request as read from the shared memory interface stripped of the request number - * (first parameter of the request) - */ -inline void files_to_store_in_memory_handler(const char *const str) { +void files_to_store_in_memory_handler(const char *const str) { // TODO: register files open for each tid ti register a close pid_t tid; sscanf(str, "%d", &tid); @@ -17,6 +13,4 @@ inline void files_to_store_in_memory_handler(const char *const str) { LOG("Need to tell client to read %llu files from data queue", count); client_manager->reply_to_client(tid, count); -} - -#endif // FILES_IN_MEMORY_HPP \ No newline at end of file +} \ No newline at end of file diff --git a/src/server/client-manager/handlers/handshake.hpp b/capio-server/src/client-manager/handlers/handshake.cpp similarity index 70% rename from src/server/client-manager/handlers/handshake.hpp rename to capio-server/src/client-manager/handlers/handshake.cpp index ddbb4c0a6..c6e72594e 100644 --- a/src/server/client-manager/handlers/handshake.hpp +++ b/capio-server/src/client-manager/handlers/handshake.cpp @@ -1,17 +1,7 @@ -#ifndef HANDSHAKE_HPP -#define HANDSHAKE_HPP - #include "capio/constants.hpp" +#include -#include - -/** - * @brief Perform handshake while providing the posix application name - * - * @param str raw request as read from the shared memory interface stripped of the request number - * (first parameter of the request) - */ -inline void handshake_handler(const char *const str) { +void handshake_handler(const char *const str) { pid_t tid, pid; char app_name[1024]; sscanf(str, "%d %d %s", &tid, &pid, app_name); @@ -32,6 +22,4 @@ inline void handshake_handler(const char *const str) { server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, "Termination phase is in progress. Ignoring further handshakes."); } -} - -#endif // HANDSHAKE_HPP \ No newline at end of file +} \ No newline at end of file diff --git a/src/server/client-manager/handlers/open.hpp b/capio-server/src/client-manager/handlers/open.cpp similarity index 77% rename from src/server/client-manager/handlers/open.hpp rename to capio-server/src/client-manager/handlers/open.cpp index 8c9a742cb..a66d79425 100644 --- a/src/server/client-manager/handlers/open.hpp +++ b/capio-server/src/client-manager/handlers/open.cpp @@ -1,13 +1,11 @@ -#ifndef OPEN_HPP -#define OPEN_HPP +#include +#include +#include +#include +#include +#include -/** - * @brief Handle the open systemcall - * - * @param str raw request as read from the shared memory interface stripped of the request number - * (first parameter of the request) - */ -inline void open_handler(const char *const str) { +void open_handler(const char *const str) { pid_t tid; int fd; char path[PATH_MAX]; @@ -35,5 +33,4 @@ inline void open_handler(const char *const str) { LOG("File does not yet exists. halting operation and adding it to queue"); file_manager->addThreadAwaitingCreation(path, tid); -} -#endif // OPEN_HPP \ No newline at end of file +} \ No newline at end of file diff --git a/src/server/client-manager/handlers/posix_readdir.hpp b/capio-server/src/client-manager/handlers/posix_readdir.cpp similarity index 62% rename from src/server/client-manager/handlers/posix_readdir.hpp rename to capio-server/src/client-manager/handlers/posix_readdir.cpp index 99ec35f03..4ebc58a4a 100644 --- a/src/server/client-manager/handlers/posix_readdir.hpp +++ b/capio-server/src/client-manager/handlers/posix_readdir.cpp @@ -1,7 +1,10 @@ -#ifndef POSIX_READDIR_HPP -#define POSIX_READDIR_HPP +#include +#include +#include +#include +#include -inline void posix_readdir_handler(const char *const str) { +void posix_readdir_handler(const char *const str) { pid_t pid; char path[PATH_MAX]; sscanf(str, "%d %s", &pid, path); @@ -13,5 +16,3 @@ inline void posix_readdir_handler(const char *const str) { client_manager->reply_to_client(pid, metadata_token.length()); storage_service->reply_to_client_raw(pid, metadata_token.c_str(), metadata_token.length()); } - -#endif // POSIX_READDIR_HPP \ No newline at end of file diff --git a/src/server/client-manager/handlers/read.hpp b/capio-server/src/client-manager/handlers/read.cpp similarity index 90% rename from src/server/client-manager/handlers/read.hpp rename to capio-server/src/client-manager/handlers/read.cpp index e510d6611..6dfe34b57 100644 --- a/src/server/client-manager/handlers/read.hpp +++ b/capio-server/src/client-manager/handlers/read.cpp @@ -1,14 +1,11 @@ -#ifndef READ_HPP -#define READ_HPP -#include "file-manager/file_manager_impl.hpp" +#include +#include +#include +#include +#include +#include -/** - * @brief Handle the read systemcall - * - * @param str raw request as read from the shared memory interface stripped of the request number - * (first parameter of the request) - */ -inline void read_handler(const char *const str) { +void read_handler(const char *const str) { long tid; int fd; capio_off64_t end_of_read; @@ -48,7 +45,7 @@ inline void read_handler(const char *const str) { file_manager->addThreadAwaitingData(path, tid, end_of_read); } -inline void read_mem_handler(const char *const str) { +void read_mem_handler(const char *const str) { long int tid; capio_off64_t read_size, client_cache_line_size, read_begin_offset; int use_cache; @@ -93,5 +90,3 @@ inline void read_mem_handler(const char *const str) { LOG("Need to sent to client %llu bytes, asking storage service to send data", size_to_send); storage_service->reply_to_client(tid, path, read_begin_offset, size_to_send); } - -#endif // READ_HPP \ No newline at end of file diff --git a/src/server/client-manager/handlers/rename.hpp b/capio-server/src/client-manager/handlers/rename.cpp similarity index 58% rename from src/server/client-manager/handlers/rename.hpp rename to capio-server/src/client-manager/handlers/rename.cpp index da7b58579..074959670 100644 --- a/src/server/client-manager/handlers/rename.hpp +++ b/capio-server/src/client-manager/handlers/rename.cpp @@ -1,13 +1,8 @@ -#ifndef CAPIO_RENAME_HPP -#define CAPIO_RENAME_HPP +#include +#include +#include -/** - * @brief Handle the rename systemcall - * - * @param str raw request as read from the shared memory interface stripped of the request number - * (first parameter of the request) - */ -inline void rename_handler(const char *const str) { +void rename_handler(const char *const str) { pid_t tid; char old_path[PATH_MAX], new_path[PATH_MAX]; sscanf(str, "%d %s %s", &tid, old_path, new_path); @@ -19,5 +14,3 @@ inline void rename_handler(const char *const str) { // TODO: check what happen when old or new is to be handled in memory } - -#endif // CAPIO_RENAME_HPP \ No newline at end of file diff --git a/src/server/client-manager/handlers/write.hpp b/capio-server/src/client-manager/handlers/write.cpp similarity index 73% rename from src/server/client-manager/handlers/write.hpp rename to capio-server/src/client-manager/handlers/write.cpp index 1c1d965dc..b7a7ad1b3 100644 --- a/src/server/client-manager/handlers/write.hpp +++ b/capio-server/src/client-manager/handlers/write.cpp @@ -1,14 +1,9 @@ -#ifndef WRITE_HPP -#define WRITE_HPP -#include "include/capio-cl-engine/capio_cl_engine.hpp" +#include +#include +#include +#include -/** - * @brief Handle the write systemcall - * - * @param str raw request as read from the shared memory interface stripped of the request number - * (first parameter of the request) - */ -inline void write_handler(const char *const str) { +void write_handler(const char *const str) { pid_t tid; int fd; capio_off64_t write_size; @@ -28,7 +23,7 @@ inline void write_handler(const char *const str) { // file_manager->checkAndUnlockThreadAwaitingData(path); } -inline void write_mem_handler(const char *const str) { +void write_mem_handler(const char *const str) { long int tid; char path[PATH_MAX]; off64_t write_size; @@ -39,5 +34,3 @@ inline void write_mem_handler(const char *const str) { storage_service->recive_from_client(tid, path, offset, write_size); } - -#endif // WRITE_HPP \ No newline at end of file diff --git a/capio-server/src/client-manager/request_handler_engine.cpp b/capio-server/src/client-manager/request_handler_engine.cpp new file mode 100644 index 000000000..42faccefb --- /dev/null +++ b/capio-server/src/client-manager/request_handler_engine.cpp @@ -0,0 +1,114 @@ +#include +#include +#include + +constexpr std::array +RequestHandlerEngine::build_request_handlers_table() { + std::array _request_handlers{0}; + + _request_handlers[CAPIO_REQUEST_CONSENT] = consent_to_proceed_handler; + _request_handlers[CAPIO_REQUEST_CLOSE] = close_handler; + _request_handlers[CAPIO_REQUEST_CREATE] = create_handler; + _request_handlers[CAPIO_REQUEST_EXIT_GROUP] = exit_handler; + _request_handlers[CAPIO_REQUEST_HANDSHAKE] = handshake_handler; + _request_handlers[CAPIO_REQUEST_MKDIR] = create_handler; + _request_handlers[CAPIO_REQUEST_OPEN] = open_handler; + _request_handlers[CAPIO_REQUEST_READ] = read_handler; + _request_handlers[CAPIO_REQUEST_RENAME] = rename_handler; + _request_handlers[CAPIO_REQUEST_WRITE] = write_handler; + _request_handlers[CAPIO_REQUEST_QUERY_MEM_FILE] = files_to_store_in_memory_handler; + _request_handlers[CAPIO_REQUEST_READ_MEM] = read_mem_handler; + _request_handlers[CAPIO_REQUEST_WRITE_MEM] = write_mem_handler; + _request_handlers[CAPIO_REQUEST_POSIX_DIR_COMMITTED] = posix_readdir_handler; + + return _request_handlers; +} + +auto RequestHandlerEngine::read_next_request(char *str) const { + char req[CAPIO_REQ_MAX_SIZE]; + START_LOG(gettid(), "call()"); + buf_requests->read(req); + LOG("req=%s", req); + int code = -1; + auto [ptr, ec] = std::from_chars(req, req + 4, code); + if (ec == std::errc()) { + strcpy(str, ptr + 1); + } else { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, + "Received invalid code: " + std::to_string(code)); + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, + "Offending request: " + std::string(ptr) + " / " + req); + ERR_EXIT("Invalid request %d:%s", code, ptr); + } + return code; +} + +RequestHandlerEngine::RequestHandlerEngine() { + START_LOG(gettid(), "call()"); + request_handlers = build_request_handlers_table(); + buf_requests = new CSBufRequest_t(SHM_COMM_CHAN_NAME, CAPIO_REQ_BUFF_CNT, CAPIO_REQ_MAX_SIZE, + capio_global_configuration->workflow_name); + + server_println(CAPIO_SERVER_CLI_LOG_SERVER, "RequestHandlerEngine initialization completed."); +} + +RequestHandlerEngine::~RequestHandlerEngine() { + START_LOG(gettid(), "call()"); + delete buf_requests; + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "RequestHandlerEngine cleanup completed."); +} + +void RequestHandlerEngine::start() const { + START_LOG(gettid(), "call()\n\n"); + + const auto str = std::unique_ptr(new char[CAPIO_REQ_MAX_SIZE]); + int code; + + /* When in termination_phase, we empty all requests while clients are connected. as soon + * as queues are empty and the server ha removed all requests, it calls the termination + * handler to stop the server execution + */ + while (!capio_global_configuration->termination_phase || + client_manager->get_connected_posix_client() > 0) { + LOG(CAPIO_LOG_SERVER_REQUEST_START); + try { + code = read_next_request(str.get()); + } catch (const std::exception &e) { + if (capio_global_configuration->termination_phase) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "Termination phase is in progress... " + "Ignoring Exception likely thrown while receiving SIGUSR1"); + continue; + } + throw; + } + + try { + request_handlers[code](str.get()); + } catch (const std::exception &exception) { + std::cout << std::endl + << "~~~~~~~~~~~~~~[\033[31mRequestHandlerEngine::start(): FATAL " + "EXCEPTION\033[0m]~~~~~~~~~~~~~~" + << std::endl + << "| Exception thrown while handling request number: " << code << " : " + << str.get() << std::endl + << "| TID of offending thread: " << gettid() << std::endl + << "| PID of offending thread: " << getpid() << std::endl + << "| PPID of offending thread: " << getppid() << std::endl + << "| " << std::endl + << "| `" << typeid(exception).name() << ": " << exception.what() << std::endl + << "|" << std::endl + << "~~~~~~~~~~~~~~[\033[31mRequestHandlerEngine::start(): FATAL " + "EXCEPTION\033[0m]~~~~~~~~~~~~~~" + << std::endl + << std::endl; + + exit(EXIT_FAILURE); + } + + LOG(CAPIO_LOG_SERVER_REQUEST_END); + } + + LOG("Terminated handling of posix clients"); +} \ No newline at end of file diff --git a/src/server/communication-service/CapioCommunicationService.hpp b/capio-server/src/communication-service/capio_communication_service.cpp similarity index 75% rename from src/server/communication-service/CapioCommunicationService.hpp rename to capio-server/src/communication-service/capio_communication_service.cpp index 8839c38c9..da3470428 100644 --- a/src/server/communication-service/CapioCommunicationService.hpp +++ b/capio-server/src/communication-service/capio_communication_service.cpp @@ -1,22 +1,18 @@ -#ifndef CAPIOCOMMUNICATIONSERVICE_HPP -#define CAPIOCOMMUNICATIONSERVICE_HPP - -#include "control_plane/capio_control_plane.hpp" -#include "data_plane/BackendInterface.hpp" - -#include "control_plane/fs_control_plane.hpp" -#include "control_plane/multicast_control_plane.hpp" -#include "data_plane/MTCL_backend.hpp" - -class CapioCommunicationService { - - public: - ~CapioCommunicationService() { +#include +#include +#include +#include +#include +#include +#include +#include + + CapioCommunicationService::~CapioCommunicationService() { delete capio_control_plane; delete capio_backend; }; - CapioCommunicationService(std::string &backend_name, const int port, + CapioCommunicationService::CapioCommunicationService(std::string &backend_name, const int port, const std::string &control_backend_name) { START_LOG(gettid(), "call(backend_name=%s)", backend_name.c_str()); @@ -35,7 +31,7 @@ class CapioCommunicationService { server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "Selected backend is " + backend_name); server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "Selected backend port is " + std::to_string(port)); - capio_backend = new MTCL_backend(backend_name, std::to_string(port), + capio_backend = new MTCLBackend(backend_name, std::to_string(port), CAPIO_BACKEND_DEFAULT_SLEEP_TIME); } else if (backend_name == "FS") { server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "Selected backend is File System"); @@ -64,8 +60,3 @@ class CapioCommunicationService { "Error: unknown control plane backend: " + control_backend_name); } } -}; - -inline CapioCommunicationService *capio_communication_service; - -#endif // CAPIOCOMMUNICATIONSERVICE_HPP diff --git a/src/server/communication-service/control_plane/fs_control_plane.hpp b/capio-server/src/communication-service/control-plane/fs_control_plane.cpp similarity index 81% rename from src/server/communication-service/control_plane/fs_control_plane.hpp rename to capio-server/src/communication-service/control-plane/fs_control_plane.cpp index 2988d84a7..c40ea267c 100644 --- a/src/server/communication-service/control_plane/fs_control_plane.hpp +++ b/capio-server/src/communication-service/control-plane/fs_control_plane.cpp @@ -1,19 +1,12 @@ -#ifndef FS_CONTROL_PLANE_HPP -#define FS_CONTROL_PLANE_HPP - #include #include #include +#include +#include +#include +#include -class FSControlPlane : public CapioControlPlane { - char ownHostname[HOST_NAME_MAX] = {0}; - int _backend_port; - bool *continue_execution; - std::thread *thread; - std::vector token_used_to_connect; - std::mutex *token_used_to_connect_mutex; - - void generate_aliveness_token(const int port) const { + void FSControlPlane::generate_aliveness_token(const int port) const { START_LOG(gettid(), "call(port=d)", port); std::string token_filename(ownHostname); @@ -29,7 +22,7 @@ class FSControlPlane : public CapioControlPlane { server_println(CAPIO_SERVER_CLI_LOG_SERVER, "Generated token at " + token_filename); } - void delete_aliveness_token() const { + void FSControlPlane::delete_aliveness_token() { START_LOG(gettid(), "call()"); std::string token_filename(ownHostname); @@ -44,10 +37,7 @@ class FSControlPlane : public CapioControlPlane { LOG("Removed token"); } - /* - * Monitor the file system for the presence of tokens. - */ - static void fs_server_aliveness_detector_thread(const bool *continue_execution, +void FSControlPlane::fs_server_aliveness_detector_thread(const bool *continue_execution, std::vector *token_used_to_connect, std::mutex *token_used_to_connect_mutex) { START_LOG(gettid(), "call()"); @@ -93,8 +83,8 @@ class FSControlPlane : public CapioControlPlane { sleep(1); } - public: - explicit FSControlPlane(int backend_port) : _backend_port(backend_port) { + + FSControlPlane::FSControlPlane(int backend_port) : _backend_port(backend_port) { gethostname(ownHostname, HOST_NAME_MAX); generate_aliveness_token(backend_port); continue_execution = new bool(true); @@ -105,7 +95,7 @@ class FSControlPlane : public CapioControlPlane { "FSControlPlane initialization completed."); }; - ~FSControlPlane() override { + FSControlPlane::~FSControlPlane() { delete_aliveness_token(); pthread_cancel(thread->native_handle()); thread->join(); @@ -116,7 +106,4 @@ class FSControlPlane : public CapioControlPlane { server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, "FSControlPlane cleanup completed."); } - void notify_all(event_type event, const std::filesystem::path &path) override {} -}; - -#endif // FS_CONTROL_PLANE_HPP \ No newline at end of file + void FSControlPlane::notify_all(FSControlPlane::event_type event, const std::filesystem::path &path) {} diff --git a/src/server/communication-service/control_plane/multicast_control_plane.hpp b/capio-server/src/communication-service/control-plane/multicast_control_plane.cpp similarity index 90% rename from src/server/communication-service/control_plane/multicast_control_plane.hpp rename to capio-server/src/communication-service/control-plane/multicast_control_plane.cpp index 526734abe..b959f077e 100644 --- a/src/server/communication-service/control_plane/multicast_control_plane.hpp +++ b/capio-server/src/communication-service/control-plane/multicast_control_plane.cpp @@ -1,22 +1,15 @@ -#ifndef MULTICAST_CONTROL_PLANE_HPP -#define MULTICAST_CONTROL_PLANE_HPP #include #include #include #include #include #include - #include "multicast_utils.hpp" +#include +#include -class MulticastControlPlane : public CapioControlPlane { - bool *continue_execution; - std::thread *discovery_thread, *controlpl_incoming; - std::vector token_used_to_connect; - std::mutex *token_used_to_connect_mutex; - char ownHostname[HOST_NAME_MAX] = {0}; - static void multicast_server_aliveness_thread(const bool *continue_execution, +void MulticastControlPlane::multicast_server_aliveness_thread(const bool *continue_execution, std::vector *token_used_to_connect, std::mutex *token_used_to_connect_mutex, int dataplane_backend_port) { @@ -73,7 +66,7 @@ class MulticastControlPlane : public CapioControlPlane { } } - static void multicast_control_plane_incoming_thread(const bool *continue_execution) { + void MulticastControlPlane::multicast_control_plane_incoming_thread(const bool *continue_execution) { START_LOG(gettid(), "Call(multicast_control_plane_incoming_thread)"); char incoming_msg[MULTICAST_CONTROLPL_MESSAGE_SIZE] = {0}; sockaddr_in addr = {}; @@ -117,8 +110,8 @@ class MulticastControlPlane : public CapioControlPlane { close(discovery_socket); } - public: - explicit MulticastControlPlane(int dataplane_backend_port) { + +MulticastControlPlane::MulticastControlPlane(int dataplane_backend_port) { START_LOG(gettid(), "call(dataplane_backend_port=%d)", dataplane_backend_port); gethostname(ownHostname, HOST_NAME_MAX); continue_execution = new bool(true); @@ -132,7 +125,7 @@ class MulticastControlPlane : public CapioControlPlane { new std::thread(multicast_control_plane_incoming_thread, continue_execution); } - ~MulticastControlPlane() override { + MulticastControlPlane::~MulticastControlPlane() { *continue_execution = false; pthread_cancel(discovery_thread->native_handle()); discovery_thread->join(); @@ -144,7 +137,7 @@ class MulticastControlPlane : public CapioControlPlane { server_println(CAPIO_SERVER_CLI_LOG_SERVER, "MulticastControlPlane correctly terminated"); } - void notify_all(const event_type event, const std::filesystem::path &path) override { + void MulticastControlPlane::notify_all(const event_type event, const std::filesystem::path &path) { START_LOG(gettid(), "call(event=%s, path=%s)", event, path.string().c_str()); sockaddr_in addr = {}; const auto socket = open_outgoing_multicast_socket(MULTICAST_CONTROLPL_ADDR, @@ -164,6 +157,3 @@ class MulticastControlPlane : public CapioControlPlane { close(socket); } -}; - -#endif // MULTICAST_CONTROL_PLANE_HPP \ No newline at end of file diff --git a/src/server/communication-service/control_plane/multicast_utils.hpp b/capio-server/src/communication-service/control-plane/multicast_utils.hpp similarity index 99% rename from src/server/communication-service/control_plane/multicast_utils.hpp rename to capio-server/src/communication-service/control-plane/multicast_utils.hpp index 1b42b50c3..dfe44db42 100644 --- a/src/server/communication-service/control_plane/multicast_utils.hpp +++ b/capio-server/src/communication-service/control-plane/multicast_utils.hpp @@ -1,6 +1,8 @@ #ifndef CAPIO_MULTICAST_UTILS_HPP #define CAPIO_MULTICAST_UTILS_HPP +#include + static int open_outgoing_multicast_socket(const char *address, const int port, sockaddr_in *addr) { int transmission_socket = socket(AF_INET, SOCK_DGRAM, 0); if (transmission_socket < 0) { diff --git a/capio-server/src/communication-service/data-plane/mtcl_backend.cpp b/capio-server/src/communication-service/data-plane/mtcl_backend.cpp new file mode 100644 index 000000000..9fd31b6f2 --- /dev/null +++ b/capio-server/src/communication-service/data-plane/mtcl_backend.cpp @@ -0,0 +1,318 @@ +#include +#include + +TransportUnit *MTCLBackend::receive_unit(MTCL::HandleUser *HandlerPointer) { + START_LOG(gettid(), "call()"); + size_t filepath_len; + const auto unit = new TransportUnit(); + HandlerPointer->receive(&filepath_len, sizeof(size_t)); + LOG("Incoming path of length %ld", filepath_len); + unit->_filepath.reserve(filepath_len + 1); + HandlerPointer->receive(unit->_filepath.data(), filepath_len); + LOG("Received message! Path : %s", unit->_filepath.c_str()); + HandlerPointer->receive(&unit->_buffer_size, sizeof(capio_off64_t)); + LOG("Buffer size for incoming data is %ld", unit->_buffer_size); + unit->_bytes = new char[unit->_buffer_size]; + LOG("Allocated space for incoming data"); + HandlerPointer->receive(unit->_bytes, unit->_buffer_size); + LOG("Received file buffer data"); + HandlerPointer->receive(&unit->_start_write_offset, sizeof(capio_off64_t)); + LOG("Received chunk of data should be stored on offset %ld of file %s", + unit->_start_write_offset, unit->_filepath.c_str()); + return unit; +} + +void MTCLBackend::send_unit(MTCL::HandleUser *HandlerPointer, const TransportUnit *unit) { + START_LOG(gettid(), "call()"); + LOG("[send] buffer=%s", unit->_bytes); + /** + * step0: send file path + * step1: send receive buffer size + * step1: send offset of write + * step2: send data + */ + const size_t file_path_length = unit->_filepath.length(); + + HandlerPointer->send(&file_path_length, sizeof(size_t)); + LOG("Size of path that is being sent: %ld", file_path_length); + + HandlerPointer->send(unit->_filepath.c_str(), file_path_length); + LOG("Sent file path: %s", unit->_filepath.c_str()); + + HandlerPointer->send(&unit->_buffer_size, sizeof(capio_off64_t)); + LOG("Size of file buffer to be sent: %ld", unit->_buffer_size); + + HandlerPointer->send(unit->_bytes, unit->_buffer_size); + LOG("Sent %ld bytes of data chunk", unit->_buffer_size); + + HandlerPointer->send(&unit->_start_write_offset, sizeof(capio_off64_t)); + LOG("Sent start write offset : %ld", unit->_start_write_offset); + + // DO NOT DELETE unit: here just afterward, the unit experiences a pop() which + // effectively calls delete on the container. If I delete it here, a double delete is + // raised +} + +/** + * This thread will handle connections towards a single target. + */ +void MTCLBackend::server_connection_handler(MTCL::HandleUser HandlerPointer, + const std::string remote_hostname, const int sleep_time, + TransportUnitInterface interface, const bool *terminate, + CONN_HANDLER_ORIGIN source) { + START_LOG(gettid(), "call(remote_hostname=%s, kind=%s)", remote_hostname.c_str(), + source == FROM_REMOTE ? "from remote server" : "to remote server"); + // out = data to sent to others + // in = data from others + auto [in, out, mutex] = interface; + + while (HandlerPointer.isValid()) { + // execute up to N operation of send &/or receive, to avoid starvation due to + // semaphores. + constexpr int max_net_op = 10; + + // Send phase + for (int completed_io_operations = 0; completed_io_operations < max_net_op && !out->empty(); + ++completed_io_operations) { + LOG("[send] Starting send section"); + const auto unit = out->front(); + + LOG("[send] Sending %ld bytes of file %s to %s", unit->_buffer_size, + unit->_filepath.c_str(), remote_hostname.c_str()); + send_unit(&HandlerPointer, unit); + LOG("[send] Message sent"); + + const std::lock_guard lg(*mutex); + LOG("[send] Locked guard"); + out->pop(); + } + + // Receive phase + size_t receive_size = 0, completed_io_operations = 0; + HandlerPointer.probe(receive_size, false); + while (completed_io_operations < max_net_op && receive_size > 0) { + LOG("[recv] Receiving data"); + auto unit = receive_unit(&HandlerPointer); + LOG("[recv] Lock guard"); + const std::lock_guard lg(*mutex); + in->push(unit); + LOG("[recv] Pushed %ld bytes to be stored on file %s", unit->_buffer_size, + unit->_filepath.c_str()); + + ++completed_io_operations; + receive_size = 0; + HandlerPointer.probe(receive_size, false); + } + + // terminate phase + if (*terminate) { + const std::lock_guard lg(*mutex); + LOG("[TERM PHASE] Locked access send and receive queues"); + while (!out->empty()) { + const auto unit = out->front(); + send_unit(&HandlerPointer, unit); + out->pop(); + } + LOG("[TERM PHASE] Emptied queues. Closing connection"); + HandlerPointer.close(); + LOG("[TERM PHASE] Terminating thread server_connection_handler"); + return; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time)); + } +} + +void MTCLBackend::incoming_connection_listener( + const bool *continue_execution, int sleep_time, + std::unordered_map *open_connections, std::mutex *guard, + std::vector *_connection_threads, bool *terminate) { + + char ownHostname[HOST_NAME_MAX] = {0}; + gethostname(ownHostname, HOST_NAME_MAX); + + START_LOG(gettid(), "call(sleep_time=%d, hostname=%s)", sleep_time, ownHostname); + + while (*continue_execution) { + auto UserManager = MTCL::Manager::getNext(std::chrono::microseconds(sleep_time)); + + if (!UserManager.isValid()) { + continue; + } + LOG("Handle user is valid"); + char connected_hostname[HOST_NAME_MAX] = {0}; + UserManager.receive(connected_hostname, HOST_NAME_MAX); + + server_println(CAPIO_SERVER_CLI_LOG_SERVER, + std::string("Connected from ") + connected_hostname); + + LOG("Received connection hostname: %s", connected_hostname); + + const std::lock_guard lock(*guard); + + open_connections->insert( + {connected_hostname, + std::make_tuple(new std::queue(), new std::queue(), + new std::mutex())}); + + _connection_threads->push_back(new std::thread( + server_connection_handler, std::move(UserManager), connected_hostname, sleep_time, + open_connections->at(connected_hostname), terminate, FROM_REMOTE)); + } +} + +void MTCLBackend::connect_to(std::string hostname_port) { + START_LOG(gettid(), "call( hostname_port=%s)", hostname_port.c_str()); + std::string remoteHost = hostname_port.substr(0, hostname_port.find_last_of(':')); + const std::string remoteToken = usedProtocol + ":" + hostname_port; + + if (remoteToken == selfToken || // skip on 0.0.0.0 + remoteToken == usedProtocol + ":" + ownHostname + ":" + ownPort // skip on my real IP + ) { + LOG("Skipping to connect to self"); + return; + } + + if (connected_hostnames_map.find(remoteToken) != connected_hostnames_map.end()) { + LOG("Remote host %s is already connected", remoteHost.c_str()); + return; + } + + LOG("Trying to connect on remote: %s", remoteToken.c_str()); + if (auto UserManager = MTCL::Manager::connect(remoteToken); UserManager.isValid()) { + server_println(CAPIO_SERVER_CLI_LOG_SERVER, std::string("Connected to ") + remoteToken); + LOG("Connected to: %s", remoteToken.c_str()); + UserManager.send(ownHostname, HOST_NAME_MAX); + const std::lock_guard lg(*_guard); + + auto connection_tuple = std::make_tuple( + new std::queue(), new std::queue(), new std::mutex()); + connected_hostnames_map.insert({remoteHost, connection_tuple}); + + connection_threads.push_back( + new std::thread(server_connection_handler, std::move(UserManager), remoteHost.c_str(), + thread_sleep_times, connection_tuple, terminate, TO_REMOTE)); + } else { + server_println(CAPIO_SERVER_CLI_LOG_SERVER_WARNING, "Warning: tried to connect to " + + std::string(remoteHost) + + " but connection is not valid"); + } +} + +MTCLBackend::MTCLBackend(const std::string &proto, const std::string &port, int sleep_time) + : selfToken(proto + ":0.0.0.0:" + port), ownPort(port), usedProtocol(proto), + thread_sleep_times(sleep_time) { + START_LOG(gettid(), "INFO: instance of CapioCommunicationService"); + + terminate = new bool; + *terminate = false; + + _guard = new std::mutex(); + + gethostname(ownHostname, HOST_NAME_MAX); + LOG("My hostname is %s. Starting to listen on connection %s", ownHostname, selfToken.c_str()); + + std::string hostname_id("server-"); + hostname_id += ownHostname; + MTCL::Manager::init(hostname_id); + + *continue_execution = true; + + MTCL::Manager::listen(selfToken); + + th = new std::thread(incoming_connection_listener, std::ref(continue_execution), sleep_time, + &connected_hostnames_map, _guard, &connection_threads, terminate); + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "MTCL_backend initialization completed."); +} + +MTCLBackend::~MTCLBackend() { + START_LOG(gettid(), "call()"); + *terminate = true; + *continue_execution = false; + + for (const auto thread : connection_threads) { + thread->join(); + } + LOG("Terminated connection threads"); + + pthread_cancel(th->native_handle()); + th->join(); + delete th; + delete continue_execution; + delete terminate; + + LOG("Handler closed."); + + MTCL::Manager::finalize(); + LOG("Finalizing MTCL backend"); + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "MTCL_backend cleanup completed."); +} + +std::string MTCLBackend::receive(char *buf, capio_off64_t *buf_size, capio_off64_t *start_offset) { + START_LOG(gettid(), "call()"); + + std::queue *inQueue = nullptr; + TransportUnitInterface interface; + bool found = false; + while (!found) { + for (auto [hostname, data] : connected_hostnames_map) { + inQueue = std::get<0>(data); + interface = data; + found = !inQueue->empty(); + LOG("Hostname %s, %s incoming data", hostname.c_str(), found ? "has" : "has not"); + } + if (!found) { + LOG("No incoming messages. Putting thread to sleep"); + std::this_thread::sleep_for(std::chrono::milliseconds(thread_sleep_times)); + } + } + LOG("Found incoming message"); + const std::lock_guard lg(*std::get<2>(interface)); + auto inputUnit = inQueue->front(); + *buf_size = inputUnit->_buffer_size; + *start_offset = inputUnit->_start_write_offset; + memcpy(buf, inputUnit->_bytes, *buf_size); + LOG("Received buffer: %s", inputUnit->_bytes); + inQueue->pop(); + + std::string filename(inputUnit->_filepath); + + return filename; +} + +void MTCLBackend::send(const std::string &target, char *buf, uint64_t buf_size, + const std::string &filepath, const capio_off64_t start_offset) { + START_LOG(gettid(), "call(target=%s, buf_size=%ld, file_path=%s, start_offset=%ld, buf=%s)", + target.c_str(), buf_size, filepath.c_str(), start_offset, buf); + + if (const auto element = connected_hostnames_map.find(target); + element != connected_hostnames_map.end()) { + LOG("Found alive connection for given target"); + + const auto interface = element->second; + auto *out = std::get<1>(interface); + + const auto outputUnit = new TransportUnit(); + outputUnit->_buffer_size = buf_size; + outputUnit->_filepath = filepath; + outputUnit->_start_write_offset = start_offset; + outputUnit->_bytes = new char[buf_size]; + memcpy(outputUnit->_bytes, buf, buf_size); + LOG("Copied buffer: %s", outputUnit->_bytes); + + const std::lock_guard lg(*std::get<2>(interface)); + LOG("Pushing Transport unit to out queue"); + out->push(outputUnit); + } else { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, "can't find target"); + } +} + +std::vector MTCLBackend::get_open_connections() { + std::vector connections; + + for (const auto &[hostname, _] : connected_hostnames_map) { + connections.push_back(hostname); + } + return connections; +} diff --git a/src/server/file-manager/file_manager_impl.hpp b/capio-server/src/file-manager/file_manager.cpp similarity index 81% rename from src/server/file-manager/file_manager_impl.hpp rename to capio-server/src/file-manager/file_manager.cpp index 1d3257448..2082d0f72 100644 --- a/src/server/file-manager/file_manager_impl.hpp +++ b/capio-server/src/file-manager/file_manager.cpp @@ -1,12 +1,16 @@ #ifndef FILE_MANAGER_HPP #define FILE_MANAGER_HPP +#include "include/file-manager/file_manager.hpp" #include "capio/env.hpp" -#include "client-manager/client_manager.hpp" -#include "file_manager.hpp" -#include "storage-service/capio_storage_service.hpp" + + #include "utils/distributed_semaphore.hpp" -inline std::string CapioFileManager::getMetadataPath(const std::string &path) { +#include +#include +#include + + std::string CapioFileManager::getMetadataPath(const std::string &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); const std::filesystem::path &metadata_path = get_capio_metadata_path(); @@ -34,16 +38,7 @@ inline std::string CapioFileManager::getMetadataPath(const std::string &path) { return token_full_path; } -/** - * @brief Creates the directory structure for the metadata file and proceed to return the path - * pointing to the metadata token file. For improvements in performances, a hash map is included to - * cache the computed paths. For thread safety concerns, see - * https://en.cppreference.com/w/cpp/container#Thread_safety - * - * @param path real path of the file - * @return std::string with the translated capio token metadata path - */ -inline std::string CapioFileManager::getAndCreateMetadataPath(const std::string &path) { + std::string CapioFileManager::getAndCreateMetadataPath(const std::string &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); static std::unordered_map metadata_paths; if (metadata_paths.find(path) == metadata_paths.end()) { @@ -59,36 +54,17 @@ inline std::string CapioFileManager::getAndCreateMetadataPath(const std::string return metadata_paths[path]; } -/** - * @brief Get the file size - * - * @param path - * @return uintmax_t file size if file exists, 0 otherwise - */ -inline uintmax_t CapioFileManager::get_file_size_if_exists(const std::filesystem::path &path) { + uintmax_t CapioFileManager::get_file_size_if_exists(const std::filesystem::path &path) { return std::filesystem::exists(path) ? std::filesystem::file_size(path) : 0; } -/** - * @brief Register a thread to the threads waiting for a file to exists (inside the CapioFSMonitor) - * for a given file path to exists - * - * @param path - * @param tid - */ -inline void CapioFileManager::addThreadAwaitingCreation(const std::string &path, pid_t tid) { + void CapioFileManager::addThreadAwaitingCreation(const std::string &path, pid_t tid) { START_LOG(gettid(), "call(path=%s, tid=%ld)", path.c_str(), tid); const std::lock_guard lg(creation_mutex); thread_awaiting_file_creation[path].push_back(tid); } -/** - * @brief Awakes all threads waiting for the creation of a file - * - * @param path file that has just been created - * @param pids - */ -inline void CapioFileManager::_unlockThreadAwaitingCreation(const std::string &path, + void CapioFileManager::_unlockThreadAwaitingCreation(const std::string &path, const std::vector &pids) { START_LOG(gettid(), "call(path=%s)", path.c_str()); for (const auto tid : pids) { @@ -101,15 +77,7 @@ inline void CapioFileManager::_unlockThreadAwaitingCreation(const std::string &p } } -/** - * @brief Register a process waiting on a file to exist and with a file size of at least the - * expected_size parameter. - * - * @param path - * @param tid - * @param expected_size - */ -inline void CapioFileManager::addThreadAwaitingData(const std::string &path, int tid, + void CapioFileManager::addThreadAwaitingData(const std::string &path, int tid, size_t expected_size) { START_LOG(gettid(), "call(path=%s, tid=%ld, expected_size=%ld)", path.c_str(), tid, expected_size); @@ -125,14 +93,7 @@ inline void CapioFileManager::addThreadAwaitingData(const std::string &path, int thread_awaiting_data[path].emplace(tid, expected_size); } -/** - * @brief Loop between all thread registered on the file path, and check for each - * one if enough data has been produced. If so, unlock and remove the thread - * - * @param path - * @param pids_awaiting - */ -inline void CapioFileManager::_unlockThreadAwaitingData( + void CapioFileManager::_unlockThreadAwaitingData( const std::string &path, std::unordered_map &pids_awaiting) { START_LOG(gettid(), "call(path=%s)", path.c_str()); @@ -189,12 +150,7 @@ inline void CapioFileManager::_unlockThreadAwaitingData( LOG("Completed loops over threads vector for file!"); } -/** - * @brief Update the CAPIO metadata n_close option by adding one to the current value - * - * @param path - */ -inline void CapioFileManager::increaseCloseCount(const std::filesystem::path &path) { + void CapioFileManager::increaseCloseCount(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); auto metadata_path = getAndCreateMetadataPath(path); auto lock = new DistributedSemaphore(metadata_path + ".lock", 300); @@ -217,12 +173,7 @@ inline void CapioFileManager::increaseCloseCount(const std::filesystem::path &pa delete lock; } -/** - * @brief Set a CAPIO handled file to be committed - * - * @param path - */ -inline void CapioFileManager::setCommitted(const std::filesystem::path &path) { + void CapioFileManager::setCommitted(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); auto metadata_path = getAndCreateMetadataPath(path); LOG("Creating token %s", metadata_path.c_str()); @@ -231,13 +182,7 @@ inline void CapioFileManager::setCommitted(const std::filesystem::path &path) { close(fd); } -/** - * @brief Set all the files that are currently open, or have been open by a given process to be - * committed - * - * @param tid - */ -inline void CapioFileManager::setCommitted(const pid_t tid) { + void CapioFileManager::setCommitted(const pid_t tid) { START_LOG(gettid(), "call(tid=%d)", tid); auto files = client_manager->get_produced_files(tid); for (const auto &file : *files) { @@ -246,14 +191,7 @@ inline void CapioFileManager::setCommitted(const pid_t tid) { } } -/** - * @brief Returns whether the file is committed or not - * - * @param path - * @return true if is committed - * @return false if it is not - */ -inline bool CapioFileManager::isCommitted(const std::filesystem::path &path) { + bool CapioFileManager::isCommitted(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); /** * Hash map to store committed files to avoid recomputing the commit state of a given file @@ -361,11 +299,7 @@ inline bool CapioFileManager::isCommitted(const std::filesystem::path &path) { return false; } -/** - * @brief Check for threads awaiting file creation and unlock threads waiting on them - * - */ -inline void CapioFileManager::checkFilesAwaitingCreation() { + void CapioFileManager::checkFilesAwaitingCreation() { // NOTE: do not put inside here log code as it will generate a lot of useless log const std::lock_guard lg(creation_mutex); std::vector path_to_delete; @@ -385,12 +319,7 @@ inline void CapioFileManager::checkFilesAwaitingCreation() { } } -/** - * @brief check if there are threads waiting for data, and for each one of them check if the file - * has enough data - * - */ -inline void CapioFileManager::checkFileAwaitingData() { + void CapioFileManager::checkFileAwaitingData() { // NOTE: do not put inside here log code as it will generate a lot of useless log const std::lock_guard lg(data_mutex); for (auto iter = thread_awaiting_data.begin(); iter != thread_awaiting_data.end();) { @@ -413,10 +342,7 @@ inline void CapioFileManager::checkFileAwaitingData() { } } -/** - * @brief commit directories that have NFILES inside them if their commit rule is n_files - */ -inline void CapioFileManager::checkDirectoriesNFiles() const { + void CapioFileManager::checkDirectoriesNFiles() const { /* * WARN: this function directly access the _location internal structure in read only mode to * avoid race conditions. Since we do not update locations, get the pointer only at the diff --git a/capio-server/src/file-manager/fs_monitor.cpp b/capio-server/src/file-manager/fs_monitor.cpp new file mode 100644 index 000000000..c90e11935 --- /dev/null +++ b/capio-server/src/file-manager/fs_monitor.cpp @@ -0,0 +1,76 @@ +#include +#include +#include +#include + + +FileSystemMonitor::FileSystemMonitor() { + START_LOG(gettid(), "call()"); + *continue_execution = true; + th = new std::thread(_main, std::ref(continue_execution)); + server_println(CAPIO_SERVER_CLI_LOG_SERVER, + "CapioFileSystemMonitor initialization completed."); +} + +void FileSystemMonitor::print_message_error(const std::string &func, const std::exception &exception) { + START_LOG(gettid(), "call()"); + std::cout << std::endl + << "~~~~~~~~~~~~~~[\033[31mFileSystemMonitor: FATAL " + "EXCEPTION\033[0m]~~~~~~~~~~~~~~" + << std::endl + << "| Exception thrown while handling method: " << func << " : " << std::endl + << "| TID of offending thread: " << gettid() << std::endl + << "| PID of offending thread: " << getpid() << std::endl + << "| PPID of offending thread: " << getppid() << std::endl + << "| " << std::endl + << "| `" << typeid(exception).name() << ": " << exception.what() << std::endl + << "|" << std::endl + << "~~~~~~~~~~~~~~[\033[31mFileSystemMonitor: FATAL " + "EXCEPTION\033[0m]~~~~~~~~~~~~~~" + << std::endl + << std::endl; + + ERR_EXIT("%s", exception.what()); +} + +void FileSystemMonitor::_main(const bool *continue_execution) { + START_LOG(gettid(), "INFO: instance of FileSystemMonitor"); + + timespec sleep{}; + sleep.tv_nsec = 300; // sleep 0.3 seconds + while (*continue_execution) { + try { + file_manager->checkFilesAwaitingCreation(); + } catch (const std::exception &exception) { + print_message_error("file_manager->checkFilesAwaitingCreation()", exception); + } + + try { + file_manager->checkFileAwaitingData(); + } catch (const std::exception &exception) { + print_message_error("file_manager->checkFileAwaitingData()", exception); + } + + try { + file_manager->checkDirectoriesNFiles(); + } catch (const std::exception &exception) { + print_message_error("file_manager->checkDirectoriesNFiles()", exception); + } + nanosleep(&sleep, nullptr); + } +} + +FileSystemMonitor::~FileSystemMonitor() { + START_LOG(gettid(), "call()"); + *continue_execution = false; + try { + th->join(); + } catch (const std::system_error &exception) { + print_message_error("~FileSystemMonitor()::th->joing()", exception); + } + + delete th; + delete continue_execution; + server_println(CAPIO_SERVER_CLI_LOG_SERVER, "CapioFileSystemMonitor cleanup completed."); +} + diff --git a/src/server/storage-service/CapioFile/CapioMemoryFile.hpp b/capio-server/src/storage-service/capio_memory_file.cpp similarity index 68% rename from src/server/storage-service/CapioFile/CapioMemoryFile.hpp rename to capio-server/src/storage-service/capio_memory_file.cpp index c6eabc0f8..edcc9b584 100644 --- a/src/server/storage-service/CapioFile/CapioMemoryFile.hpp +++ b/capio-server/src/storage-service/capio_memory_file.cpp @@ -1,33 +1,10 @@ -#ifndef CAPIOMEMORYFILE_HPP -#define CAPIOMEMORYFILE_HPP - -#include -#include -#include -#include -#include -#include - -#include - -#include "CapioFile.hpp" -class CapioMemoryFile : public CapioFile { - std::map> memoryBlocks; +#include "include/storage-service/capio_file.hpp" +#include - // Static file sizes of file pages - static constexpr u_int32_t _pageSizeMB = 4; - static constexpr u_int64_t _pageSizeBytes = _pageSizeMB * 1024 * 1024; - char *cross_page_buffer_view; - /** - * Compute the offsets required to handle write operations onto CapioMemoryFile - * @param offset Offset from the start of the file, on which the write operation will begin - * @param length Size of the buffer that will be written into memory - * @return tuple - */ - static auto compute_offsets(const std::size_t offset, std::size_t length) { + auto CapioMemoryFile::compute_offsets(const std::size_t offset, std::size_t length) { START_LOG(gettid(), "call(offset=%llu, length=%llu)", offset, length); // Compute the offset of the memoryBlocks component. const auto map_offset = offset / _pageSizeBytes; @@ -47,32 +24,22 @@ class CapioMemoryFile : public CapioFile { return std::tuple(map_offset, mem_block_offset, first_write_size); } - /** - * Retrieve a block with memory already reserved at a given offset - * @param id - * @return - */ - std::vector &get_block(u_int64_t id) { + + std::vector &CapioMemoryFile::get_block(u_int64_t id) { std::vector &block = memoryBlocks[id]; block.resize(_pageSizeBytes); // reserve 4MB of space return block; } - public: - explicit CapioMemoryFile(const std::string &filePath) : CapioFile(filePath) { + + CapioMemoryFile::CapioMemoryFile(const std::string &filePath) : CapioFile(filePath) { cross_page_buffer_view = new char[_pageSizeBytes]; } - ~CapioMemoryFile() override { delete[] cross_page_buffer_view; } + CapioMemoryFile::~CapioMemoryFile() { delete[] cross_page_buffer_view; } - /** - * Write data to a file stored inside the memory - * @param buffer buffer to store inside memory (i.e. content of the file) - * @param file_offset offset internal to the file - * @param buffer_length Size of the buffer. - */ - std::size_t writeData(const char *buffer, const std::size_t file_offset, - std::size_t buffer_length) override { + std::size_t CapioMemoryFile::writeData(const char *buffer, const std::size_t file_offset, + std::size_t buffer_length) { const auto &[map_offset, write_offset, first_write_size] = compute_offsets(file_offset, buffer_length); @@ -107,14 +74,8 @@ class CapioMemoryFile : public CapioFile { return totalSize; } - /** - * Read from Capio File - * @param buffer Buffer to read to - * @param file_offset Starting offset of read operation from CapioMemFile - * @param buffer_size Length of buffer - * @return number of bytes read from CapioMemoryFile - */ - std::size_t readData(char *buffer, std::size_t file_offset, std::size_t buffer_size) { + + std::size_t CapioMemoryFile::readData(char *buffer, std::size_t file_offset, std::size_t buffer_size) { std::size_t bytesRead = 0; const auto &[map_offset, mem_block_offset_begin, target_buffer_size] = @@ -141,14 +102,8 @@ class CapioMemoryFile : public CapioFile { return bytesRead; } - /** - * Store data inside the CapioMemoryFile by reading it from a SPSCQueue object. Behaves just - * like the writeData method - * @param queue - * @param offset - * @param length - */ - void readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) override { + + void CapioMemoryFile::readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) { const auto &[map_offset, write_offset, first_write_size] = compute_offsets(offset, length); auto remaining_bytes = length; @@ -179,15 +134,9 @@ class CapioMemoryFile : public CapioFile { totalSize = std::max(totalSize, offset + length); } - /** - * Write the content of the capioFile to a SPSCQueue object - * @param queue - * @param offset - * @param length - * @return - */ - std::size_t writeToQueue(SPSCQueue &queue, std::size_t offset, - std::size_t length) const override { + + std::size_t CapioMemoryFile::writeToQueue(SPSCQueue &queue, std::size_t offset, + std::size_t length) const { START_LOG(gettid(), "call(offset=%llu, length=%llu)", offset, length); std::size_t bytesRead = 0; @@ -211,6 +160,3 @@ class CapioMemoryFile : public CapioFile { } return bytesRead; } -}; - -#endif // CAPIOMEMORYFILE_HPP \ No newline at end of file diff --git a/capio-server/src/storage-service/capio_remote_file.cpp b/capio-server/src/storage-service/capio_remote_file.cpp new file mode 100644 index 000000000..9d6968616 --- /dev/null +++ b/capio-server/src/storage-service/capio_remote_file.cpp @@ -0,0 +1,27 @@ + +#include + + + CapioRemoteFile::CapioRemoteFile(const std::string &filePath) : CapioFile(filePath) {} + + CapioRemoteFile::~CapioRemoteFile() {} + + + std::size_t CapioRemoteFile::writeData(const char *buffer, const std::size_t file_offset, + std::size_t buffer_length) { + return 0; + } + + + std::size_t CapioRemoteFile::readData(char *buffer, std::size_t file_offset, std::size_t buffer_size) { + return 0; + } + + + void CapioRemoteFile::readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) {} + + + std::size_t CapioRemoteFile::writeToQueue(SPSCQueue &queue, std::size_t offset, + std::size_t length) const { + return 0; + } diff --git a/src/server/storage-service/capio_storage_service.hpp b/capio-server/src/storage-service/capio_storage_service.cpp similarity index 58% rename from src/server/storage-service/capio_storage_service.hpp rename to capio-server/src/storage-service/capio_storage_service.cpp index 0f6c3e211..d8faa7d12 100644 --- a/src/server/storage-service/capio_storage_service.hpp +++ b/capio-server/src/storage-service/capio_storage_service.cpp @@ -1,35 +1,24 @@ -#ifndef CAPIO_STORAGE_SERVICE_H -#define CAPIO_STORAGE_SERVICE_H - -#include "../../posix/utils/env.hpp" -#include "CapioFile/CapioFile.hpp" -#include "CapioFile/CapioMemoryFile.hpp" -#include "CapioFile/CapioRemoteFile.hpp" - -class CapioStorageService { - // TODO: put all of this conde on a different thread - - std::unordered_map *_client_to_server_queue; - std::unordered_map *_server_to_client_queue; - std::unordered_map *_stored_files; - - std::unordered_map>> - *_threads_waiting_for_memory_data; - - /** - * Return a file if exists. if not, create it and then return it - * @param file_name - * @return - */ - [[nodiscard]] auto getFile(const std::string &file_name) const { + + + + +#include +#include +#include +#include +#include + + + + + auto CapioStorageService::getFile(const std::string &file_name) const { if (_stored_files->find(file_name) == _stored_files->end()) { createMemoryFile(file_name); } return _stored_files->at(file_name); } - public: - CapioStorageService() { + CapioStorageService::CapioStorageService() { START_LOG(gettid(), "call()"); _stored_files = new std::unordered_map; _client_to_server_queue = new std::unordered_map; @@ -41,7 +30,7 @@ class CapioStorageService { "CapioStorageService initialization completed."); } - ~CapioStorageService() { + CapioStorageService::~CapioStorageService() { // TODO: dump files to FS delete _stored_files; delete _client_to_server_queue; @@ -50,16 +39,12 @@ class CapioStorageService { server_println(CAPIO_SERVER_CLI_LOG_SERVER, "CapioStorageService cleanup completed."); } - void createMemoryFile(const std::string &file_name) const { + void CapioStorageService::createMemoryFile(const std::string &file_name) const { _stored_files->emplace(file_name, new CapioMemoryFile(file_name)); } - /** - * Create a CapioRemoteFile, after checking that an instance of CapioMemoryFile (meaning a local - * file) is not present - * @param file_name file path - */ - void createRemoteFile(const std::string &file_name) const { + + void CapioStorageService::createRemoteFile(const std::string &file_name) const { /* * First we check that the file associate does not yet exists, as it might be produced * by another app running under the same server instance. if it is not found, we create @@ -72,25 +57,15 @@ class CapioStorageService { } } - void deleteFile(const std::string &file_name) const { _stored_files->erase(file_name); } + void CapioStorageService::deleteFile(const std::string &file_name) const { _stored_files->erase(file_name); } + - /** - * Notify the occurrence of an operation on a given file, for which other servers running at a - * certain point might be required to know. This function is used to allow CAPIO to function in - * the event that a distributed file system (or at least a shared directory) is not available - */ - void notifyEvent(const std::string &event_name, const std::filesystem::path &filename) const { + void CapioStorageService::notifyEvent(const std::string &event_name, const std::filesystem::path &filename) const { // TODO: implement this } - /** - * Add a new thread in the list of thhreads awaiting for expected_size to be available - * @param tid - * @param path - * @param offset - * @param size - */ - void addThreadWaitingForData(pid_t tid, const std::string &path, capio_off64_t offset, + + void CapioStorageService::addThreadWaitingForData(pid_t tid, const std::string &path, capio_off64_t offset, capio_off64_t size) const { START_LOG(gettid(), "call(tid=%d, path=%s, offset=%lld, size=%lld)", tid, path.c_str(), offset, size); @@ -102,7 +77,7 @@ class CapioStorageService { _threads_waiting_for_memory_data->at(path).emplace_back(std::make_tuple(offset, size, tid)); } - void check_and_unlock_thread_awaiting_data(const std::string &path) { + void CapioStorageService::check_and_unlock_thread_awaiting_data(const std::string &path) { auto threads = _threads_waiting_for_memory_data->at(path); auto file_size = sizeOf(path); @@ -114,22 +89,14 @@ class CapioStorageService { } } - /** - * Return size of given path as contained inside memory - * @param path - * @return - */ - size_t sizeOf(const std::string &path) const { + + size_t CapioStorageService::sizeOf(const std::string &path) const { START_LOG(gettid(), "call(file=%s)", path.c_str()); return getFile(path)->getSize(); } - /** - * Initialize a new client data structure - * @param app_name - * @param pid - */ - void register_client(const std::string &app_name, const pid_t pid) const { + + void CapioStorageService::register_client(const std::string &app_name, const pid_t pid) const { START_LOG(gettid(), "call(app_name=%s)", app_name.c_str()); _client_to_server_queue->emplace( pid, @@ -142,14 +109,8 @@ class CapioStorageService { LOG("Created communication queues"); } - /** - * Send the file content to a client application - * @param pid - * @param file - * @param offset - * @param size - */ - void reply_to_client(pid_t pid, const std::string &file, capio_off64_t offset, + + void CapioStorageService::reply_to_client(pid_t pid, const std::string &file, capio_off64_t offset, capio_off64_t size) const { START_LOG(gettid(), "call(pid=%llu, file=%s, offset=%llu, size=%llu)", pid, file.c_str(), offset, size); @@ -157,24 +118,13 @@ class CapioStorageService { getFile(file)->writeToQueue(*_server_to_client_queue->at(pid), offset, size); } - /** - * Send raw data to client without fetching from the storage manager itself - * @param pid - * @param data - * @param len - */ - void reply_to_client_raw(pid_t pid, const char *data, const capio_off64_t len) const { + + void CapioStorageService::reply_to_client_raw(pid_t pid, const char *data, const capio_off64_t len) const { _server_to_client_queue->at(pid)->write(data, len); } - /** - * Receive the file content from the client application - * @param tid - * @param file - * @param offset - * @param size - */ - void recive_from_client(pid_t tid, const std::string &file, capio_off64_t offset, + + void CapioStorageService::recive_from_client(pid_t tid, const std::string &file, capio_off64_t offset, off64_t size) const { START_LOG(gettid(), "call(tid=%d, file=%s, offset=%lld, size=%lld)", tid, file.c_str(), offset, size); @@ -183,18 +133,13 @@ class CapioStorageService { f->readFromQueue(*queue, offset, size); } - void remove_client(const pid_t pid) const { + void CapioStorageService::remove_client(const pid_t pid) const { _client_to_server_queue->erase(pid); _server_to_client_queue->erase(pid); } - /** - * Return a list of regex used to match files that need to be stored inside memory first - * to a posix application - * @param pid - * @return - */ - [[nodiscard]] size_t sendFilesToStoreInMemory(const long pid) const { + + size_t CapioStorageService::sendFilesToStoreInMemory(const long pid) const { START_LOG(gettid(), "call(pid=%d)", pid); if (capio_global_configuration->StoreOnlyInMemory) { @@ -217,8 +162,3 @@ class CapioStorageService { LOG("Return value=%llu", files_to_store_in_mem.size()); return files_to_store_in_mem.size(); } -}; - -inline CapioStorageService *storage_service; - -#endif // CAPIO_STORAGE_SERVICE_H \ No newline at end of file diff --git a/src/server/utils/configuration.hpp b/capio-server/utils/configuration.hpp similarity index 98% rename from src/server/utils/configuration.hpp rename to capio-server/utils/configuration.hpp index 16ec95e2c..1416b2d0c 100644 --- a/src/server/utils/configuration.hpp +++ b/capio-server/utils/configuration.hpp @@ -6,6 +6,7 @@ #include #include #include +#include /* * Variables required to be globally available diff --git a/src/server/utils/distributed_semaphore.hpp b/capio-server/utils/distributed_semaphore.hpp similarity index 100% rename from src/server/utils/distributed_semaphore.hpp rename to capio-server/utils/distributed_semaphore.hpp diff --git a/src/server/utils/parser.hpp b/capio-server/utils/parser.hpp similarity index 98% rename from src/server/utils/parser.hpp rename to capio-server/utils/parser.hpp index 9fba79cfc..efb0180a3 100644 --- a/src/server/utils/parser.hpp +++ b/capio-server/utils/parser.hpp @@ -1,6 +1,8 @@ #ifndef PARSER_HPP #define PARSER_HPP +#include + std::string parseCLI(int argc, char **argv, char *resolve_prefix) { Logger *log; diff --git a/src/server/utils/signals.hpp b/capio-server/utils/signals.hpp similarity index 94% rename from src/server/utils/signals.hpp rename to capio-server/utils/signals.hpp index 35f0ea5d6..16d5cf75b 100644 --- a/src/server/utils/signals.hpp +++ b/capio-server/utils/signals.hpp @@ -1,8 +1,8 @@ #ifndef CAPIO_SERVER_HANDLERS_SIGNALS_HPP #define CAPIO_SERVER_HANDLERS_SIGNALS_HPP -#include "../communication-service/data_plane/BackendInterface.hpp" -#include "communication-service/CapioCommunicationService.hpp" +#include +#include #include diff --git a/src/server/utils/types.hpp b/capio-server/utils/types.hpp similarity index 100% rename from src/server/utils/types.hpp rename to capio-server/utils/types.hpp diff --git a/docker-development/build-and-startup.sh b/scripts/docker-development/build-and-startup.sh similarity index 77% rename from docker-development/build-and-startup.sh rename to scripts/docker-development/build-and-startup.sh index 4a4d77351..df223d16f 100755 --- a/docker-development/build-and-startup.sh +++ b/scripts/docker-development/build-and-startup.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash -cd .. +cd ../.. docker build -t alphaunito/capio --build-arg CAPIO_LOG=ON --build-arg CMAKE_BUILD_TYPE=Debug . -cd docker-development +cd scripts/docker-development docker compose up diff --git a/docker-development/docker-compose.yml b/scripts/docker-development/docker-compose.yml similarity index 100% rename from docker-development/docker-compose.yml rename to scripts/docker-development/docker-compose.yml diff --git a/src/server/client-manager/request_handler_engine.hpp b/src/server/client-manager/request_handler_engine.hpp deleted file mode 100644 index 61f4b7c57..000000000 --- a/src/server/client-manager/request_handler_engine.hpp +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef CAPIO_CL_ENGINE_MAIN_HPP -#define CAPIO_CL_ENGINE_MAIN_HPP - -#include "include/capio-cl-engine/capio_cl_engine.hpp" -#include "include/capio-cl-engine/json_parser.hpp" -#include "capio/requests.hpp" -#include "client_manager.hpp" -#include "file-manager/file_manager.hpp" - -/* - * SYSCALL REQUESTS handlers - */ -#include "handlers/close.hpp" -#include "handlers/consent.hpp" -#include "handlers/create.hpp" -#include "handlers/exit.hpp" -#include "handlers/files_in_memory.hpp" -#include "handlers/handshake.hpp" -#include "handlers/open.hpp" -#include "handlers/read.hpp" -#include "handlers/rename.hpp" -#include "handlers/write.hpp" - -/* - * POSIX GLIBC REQUESTS handlers - */ -#include "handlers/posix_readdir.hpp" - -/** - * @brief Class that handles the system calls received from the posix client application - * - */ -class RequestHandlerEngine { - std::array request_handlers{}; - CSBufRequest_t *buf_requests; - - static constexpr std::array build_request_handlers_table() { - std::array _request_handlers{0}; - - _request_handlers[CAPIO_REQUEST_CONSENT] = consent_to_proceed_handler; - _request_handlers[CAPIO_REQUEST_CLOSE] = close_handler; - _request_handlers[CAPIO_REQUEST_CREATE] = create_handler; - _request_handlers[CAPIO_REQUEST_EXIT_GROUP] = exit_handler; - _request_handlers[CAPIO_REQUEST_HANDSHAKE] = handshake_handler; - _request_handlers[CAPIO_REQUEST_MKDIR] = create_handler; - _request_handlers[CAPIO_REQUEST_OPEN] = open_handler; - _request_handlers[CAPIO_REQUEST_READ] = read_handler; - _request_handlers[CAPIO_REQUEST_RENAME] = rename_handler; - _request_handlers[CAPIO_REQUEST_WRITE] = write_handler; - _request_handlers[CAPIO_REQUEST_QUERY_MEM_FILE] = files_to_store_in_memory_handler; - _request_handlers[CAPIO_REQUEST_READ_MEM] = read_mem_handler; - _request_handlers[CAPIO_REQUEST_WRITE_MEM] = write_mem_handler; - _request_handlers[CAPIO_REQUEST_POSIX_DIR_COMMITTED] = posix_readdir_handler; - - return _request_handlers; - } - - /** - * Read next incoming request into @param str and returns the request code - * @param str - * @return request code - */ - inline auto read_next_request(char *str) const { - char req[CAPIO_REQ_MAX_SIZE]; - START_LOG(gettid(), "call()"); - buf_requests->read(req); - LOG("req=%s", req); - int code = -1; - auto [ptr, ec] = std::from_chars(req, req + 4, code); - if (ec == std::errc()) { - strcpy(str, ptr + 1); - } else { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, - "Received invalid code: " + std::to_string(code)); - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, - "Offending request: " + std::string(ptr) + " / " + req); - ERR_EXIT("Invalid request %d:%s", code, ptr); - } - return code; - } - - public: - explicit RequestHandlerEngine() { - START_LOG(gettid(), "call()"); - - client_manager = new ClientManager(); - request_handlers = build_request_handlers_table(); - buf_requests = - new CSBufRequest_t(SHM_COMM_CHAN_NAME, CAPIO_REQ_BUFF_CNT, CAPIO_REQ_MAX_SIZE, - capio_global_configuration->workflow_name); - - server_println(CAPIO_SERVER_CLI_LOG_SERVER, - "RequestHandlerEngine initialization completed."); - } - - ~RequestHandlerEngine() { - START_LOG(gettid(), "call()"); - delete buf_requests; - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "RequestHandlerEngine cleanup completed."); - } - - /** - * @brief Start the main loop on the main thread that will read each request one by one from all - * the posix clients (aggregated) and handle the response - * - */ - void start() const { - START_LOG(gettid(), "call()\n\n"); - - const auto str = std::unique_ptr(new char[CAPIO_REQ_MAX_SIZE]); - int code; - - /* When in termination_phase, we empty all requests while clients are connected. as soon - * as queues are empty and the server ha removed all requests, it calls the termination - * handler to stop the server execution - */ - while (!capio_global_configuration->termination_phase || - client_manager->get_connected_posix_client() > 0) { - LOG(CAPIO_LOG_SERVER_REQUEST_START); - try { - code = read_next_request(str.get()); - } catch (const std::exception &e) { - if (capio_global_configuration->termination_phase) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "Termination phase is in progress... " - "Ignoring Exception likely thrown while receiving SIGUSR1"); - continue; - } - throw; - } - - try { - request_handlers[code](str.get()); - } catch (const std::exception &exception) { - std::cout << std::endl - << "~~~~~~~~~~~~~~[\033[31mRequestHandlerEngine::start(): FATAL " - "EXCEPTION\033[0m]~~~~~~~~~~~~~~" - << std::endl - << "| Exception thrown while handling request number: " << code << " : " - << str.get() << std::endl - << "| TID of offending thread: " << gettid() << std::endl - << "| PID of offending thread: " << getpid() << std::endl - << "| PPID of offending thread: " << getppid() << std::endl - << "| " << std::endl - << "| `" << typeid(exception).name() << ": " << exception.what() - << std::endl - << "|" << std::endl - << "~~~~~~~~~~~~~~[\033[31mRequestHandlerEngine::start(): FATAL " - "EXCEPTION\033[0m]~~~~~~~~~~~~~~" - << std::endl - << std::endl; - - exit(EXIT_FAILURE); - } - - LOG(CAPIO_LOG_SERVER_REQUEST_END); - } - - LOG("Terminated handling of posix clients"); - } -}; - -inline RequestHandlerEngine *request_handlers_engine; - -#endif // CAPIO_CL_ENGINE_MAIN_HPP \ No newline at end of file diff --git a/src/server/communication-service/data_plane/MTCL_backend.hpp b/src/server/communication-service/data_plane/MTCL_backend.hpp deleted file mode 100644 index a92887abf..000000000 --- a/src/server/communication-service/data_plane/MTCL_backend.hpp +++ /dev/null @@ -1,368 +0,0 @@ -#ifndef CAPIOCOMMUNICATIONSERVICE_H -#define CAPIOCOMMUNICATIONSERVICE_H -#include "BackendInterface.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class TransportUnit { - protected: - std::string _filepath; - char *_bytes{}; - capio_off64_t _buffer_size{}; - capio_off64_t _start_write_offset{}; - - public: - TransportUnit() = default; - - ~TransportUnit() { delete[] _bytes; } - - friend class MTCL_backend; -}; - -class MTCL_backend : public BackendInterface { - typedef enum { FROM_REMOTE, TO_REMOTE } CONN_HANDLER_ORIGIN; - - typedef std::tuple *, std::queue *, std::mutex *> - TransportUnitInterface; - std::unordered_map connected_hostnames_map; - std::string selfToken, connectedHostname, ownPort, usedProtocol; - char ownHostname[HOST_NAME_MAX] = {0}; - int thread_sleep_times = 0; - bool *continue_execution = new bool; - std::mutex *_guard; - std::thread *th; - std::vector connection_threads; - bool *terminate; - - static TransportUnit *receive_unit(MTCL::HandleUser *HandlerPointer) { - START_LOG(gettid(), "call()"); - size_t filepath_len; - const auto unit = new TransportUnit(); - HandlerPointer->receive(&filepath_len, sizeof(size_t)); - LOG("Incoming path of length %ld", filepath_len); - unit->_filepath.reserve(filepath_len + 1); - HandlerPointer->receive(unit->_filepath.data(), filepath_len); - LOG("Received message! Path : %s", unit->_filepath.c_str()); - HandlerPointer->receive(&unit->_buffer_size, sizeof(capio_off64_t)); - LOG("Buffer size for incoming data is %ld", unit->_buffer_size); - unit->_bytes = new char[unit->_buffer_size]; - LOG("Allocated space for incoming data"); - HandlerPointer->receive(unit->_bytes, unit->_buffer_size); - LOG("Received file buffer data"); - HandlerPointer->receive(&unit->_start_write_offset, sizeof(capio_off64_t)); - LOG("Received chunk of data should be stored on offset %ld of file %s", - unit->_start_write_offset, unit->_filepath.c_str()); - return unit; - } - - static void send_unit(MTCL::HandleUser *HandlerPointer, const TransportUnit *unit) { - START_LOG(gettid(), "call()"); - LOG("[send] buffer=%s", unit->_bytes); - /** - * step0: send file path - * step1: send receive buffer size - * step1: send offset of write - * step2: send data - */ - const size_t file_path_length = unit->_filepath.length(); - - HandlerPointer->send(&file_path_length, sizeof(size_t)); - LOG("Size of path that is being sent: %ld", file_path_length); - - HandlerPointer->send(unit->_filepath.c_str(), file_path_length); - LOG("Sent file path: %s", unit->_filepath.c_str()); - - HandlerPointer->send(&unit->_buffer_size, sizeof(capio_off64_t)); - LOG("Size of file buffer to be sent: %ld", unit->_buffer_size); - - HandlerPointer->send(unit->_bytes, unit->_buffer_size); - LOG("Sent %ld bytes of data chunk", unit->_buffer_size); - - HandlerPointer->send(&unit->_start_write_offset, sizeof(capio_off64_t)); - LOG("Sent start write offset : %ld", unit->_start_write_offset); - - // DO NOT DELETE unit: here just afterward, the unit experiences a pop() which - // effectively calls delete on the container. If I delete it here, a double delete is - // raised - } - - /** - * This thread will handle connections towards a single target. - */ - void static server_connection_handler(MTCL::HandleUser HandlerPointer, - const std::string remote_hostname, const int sleep_time, - TransportUnitInterface interface, const bool *terminate, - CONN_HANDLER_ORIGIN source) { - START_LOG(gettid(), "call(remote_hostname=%s, kind=%s)", remote_hostname.c_str(), - source == FROM_REMOTE ? "from remote server" : "to remote server"); - // out = data to sent to others - // in = data from others - auto [in, out, mutex] = interface; - - while (HandlerPointer.isValid()) { - // execute up to N operation of send &/or receive, to avoid starvation due to - // semaphores. - constexpr int max_net_op = 10; - - // Send phase - for (int completed_io_operations = 0; - completed_io_operations < max_net_op && !out->empty(); ++completed_io_operations) { - LOG("[send] Starting send section"); - const auto unit = out->front(); - - LOG("[send] Sending %ld bytes of file %s to %s", unit->_buffer_size, - unit->_filepath.c_str(), remote_hostname.c_str()); - send_unit(&HandlerPointer, unit); - LOG("[send] Message sent"); - - const std::lock_guard lg(*mutex); - LOG("[send] Locked guard"); - out->pop(); - } - - // Receive phase - size_t receive_size = 0, completed_io_operations = 0; - HandlerPointer.probe(receive_size, false); - while (completed_io_operations < max_net_op && receive_size > 0) { - LOG("[recv] Receiving data"); - auto unit = receive_unit(&HandlerPointer); - LOG("[recv] Lock guard"); - const std::lock_guard lg(*mutex); - in->push(unit); - LOG("[recv] Pushed %ld bytes to be stored on file %s", unit->_buffer_size, - unit->_filepath.c_str()); - - ++completed_io_operations; - receive_size = 0; - HandlerPointer.probe(receive_size, false); - } - - // terminate phase - if (*terminate) { - const std::lock_guard lg(*mutex); - LOG("[TERM PHASE] Locked access send and receive queues"); - while (!out->empty()) { - const auto unit = out->front(); - send_unit(&HandlerPointer, unit); - out->pop(); - } - LOG("[TERM PHASE] Emptied queues. Closing connection"); - HandlerPointer.close(); - LOG("[TERM PHASE] Terminating thread server_connection_handler"); - return; - } - - std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time)); - } - } - - void static incoming_connection_listener( - const bool *continue_execution, int sleep_time, - std::unordered_map *open_connections, - std::mutex *guard, std::vector *_connection_threads, bool *terminate) { - - char ownHostname[HOST_NAME_MAX] = {0}; - gethostname(ownHostname, HOST_NAME_MAX); - - START_LOG(gettid(), "call(sleep_time=%d, hostname=%s)", sleep_time, ownHostname); - - while (*continue_execution) { - auto UserManager = MTCL::Manager::getNext(std::chrono::microseconds(sleep_time)); - - if (!UserManager.isValid()) { - continue; - } - LOG("Handle user is valid"); - char connected_hostname[HOST_NAME_MAX] = {0}; - UserManager.receive(connected_hostname, HOST_NAME_MAX); - - server_println(CAPIO_SERVER_CLI_LOG_SERVER, - std::string("Connected from ") + connected_hostname); - - LOG("Received connection hostname: %s", connected_hostname); - - const std::lock_guard lock(*guard); - - open_connections->insert( - {connected_hostname, - std::make_tuple(new std::queue(), - new std::queue(), new std::mutex())}); - - _connection_threads->push_back(new std::thread( - server_connection_handler, std::move(UserManager), connected_hostname, sleep_time, - open_connections->at(connected_hostname), terminate, FROM_REMOTE)); - } - } - - public: - void connect_to(std::string hostname_port) override { - START_LOG(gettid(), "call( hostname_port=%s)", hostname_port.c_str()); - std::string remoteHost = hostname_port.substr(0, hostname_port.find_last_of(':')); - const std::string remoteToken = usedProtocol + ":" + hostname_port; - - if (remoteToken == selfToken || // skip on 0.0.0.0 - remoteToken == usedProtocol + ":" + ownHostname + ":" + ownPort // skip on my real IP - ) { - LOG("Skipping to connect to self"); - return; - } - - if (connected_hostnames_map.find(remoteToken) != connected_hostnames_map.end()) { - LOG("Remote host %s is already connected", remoteHost.c_str()); - return; - } - - LOG("Trying to connect on remote: %s", remoteToken.c_str()); - if (auto UserManager = MTCL::Manager::connect(remoteToken); UserManager.isValid()) { - server_println(CAPIO_SERVER_CLI_LOG_SERVER, std::string("Connected to ") + remoteToken); - LOG("Connected to: %s", remoteToken.c_str()); - UserManager.send(ownHostname, HOST_NAME_MAX); - const std::lock_guard lg(*_guard); - - auto connection_tuple = - std::make_tuple(new std::queue(), - new std::queue(), new std::mutex()); - connected_hostnames_map.insert({remoteHost, connection_tuple}); - - connection_threads.push_back(new std::thread( - server_connection_handler, std::move(UserManager), remoteHost.c_str(), - thread_sleep_times, connection_tuple, terminate, TO_REMOTE)); - } else { - server_println(CAPIO_SERVER_CLI_LOG_SERVER_WARNING, "Warning: tried to connect to " + - std::string(remoteHost) + - " but connection is not valid"); - } - } - - explicit MTCL_backend(const std::string &proto, const std::string &port, int sleep_time) - : selfToken(proto + ":0.0.0.0:" + port), ownPort(port), usedProtocol(proto), - thread_sleep_times(sleep_time) { - START_LOG(gettid(), "INFO: instance of CapioCommunicationService"); - - terminate = new bool; - *terminate = false; - - _guard = new std::mutex(); - - gethostname(ownHostname, HOST_NAME_MAX); - LOG("My hostname is %s. Starting to listen on connection %s", ownHostname, - selfToken.c_str()); - - std::string hostname_id("server-"); - hostname_id += ownHostname; - MTCL::Manager::init(hostname_id); - - *continue_execution = true; - - MTCL::Manager::listen(selfToken); - - th = new std::thread(incoming_connection_listener, std::ref(continue_execution), sleep_time, - &connected_hostnames_map, _guard, &connection_threads, terminate); - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "MTCL_backend initialization completed."); - } - - ~MTCL_backend() override { - START_LOG(gettid(), "call()"); - *terminate = true; - *continue_execution = false; - - for (const auto thread : connection_threads) { - thread->join(); - } - LOG("Terminated connection threads"); - - pthread_cancel(th->native_handle()); - th->join(); - delete th; - delete continue_execution; - delete terminate; - - LOG("Handler closed."); - - MTCL::Manager::finalize(); - LOG("Finalizing MTCL backend"); - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "MTCL_backend cleanup completed."); - } - - std::string receive(char *buf, capio_off64_t *buf_size, capio_off64_t *start_offset) override { - START_LOG(gettid(), "call()"); - - std::queue *inQueue = nullptr; - TransportUnitInterface interface; - bool found = false; - while (!found) { - for (auto [hostname, data] : connected_hostnames_map) { - inQueue = std::get<0>(data); - interface = data; - found = !inQueue->empty(); - LOG("Hostname %s, %s incoming data", hostname.c_str(), found ? "has" : "has not"); - } - if (!found) { - LOG("No incoming messages. Putting thread to sleep"); - std::this_thread::sleep_for(std::chrono::milliseconds(thread_sleep_times)); - } - } - LOG("Found incoming message"); - const std::lock_guard lg(*std::get<2>(interface)); - auto inputUnit = inQueue->front(); - *buf_size = inputUnit->_buffer_size; - *start_offset = inputUnit->_start_write_offset; - memcpy(buf, inputUnit->_bytes, *buf_size); - LOG("Received buffer: %s", inputUnit->_bytes); - inQueue->pop(); - - std::string filename(inputUnit->_filepath); - - return filename; - } - - void send(const std::string &target, char *buf, uint64_t buf_size, const std::string &filepath, - const capio_off64_t start_offset) override { - START_LOG(gettid(), "call(target=%s, buf_size=%ld, file_path=%s, start_offset=%ld, buf=%s)", - target.c_str(), buf_size, filepath.c_str(), start_offset, buf); - - if (const auto element = connected_hostnames_map.find(target); - element != connected_hostnames_map.end()) { - LOG("Found alive connection for given target"); - - const auto interface = element->second; - auto *out = std::get<1>(interface); - - const auto outputUnit = new TransportUnit(); - outputUnit->_buffer_size = buf_size; - outputUnit->_filepath = filepath; - outputUnit->_start_write_offset = start_offset; - outputUnit->_bytes = new char[buf_size]; - memcpy(outputUnit->_bytes, buf, buf_size); - LOG("Copied buffer: %s", outputUnit->_bytes); - - const std::lock_guard lg(*std::get<2>(interface)); - LOG("Pushing Transport unit to out queue"); - out->push(outputUnit); - } else { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, "can't find target"); - } - } - - std::vector get_open_connections() override { - std::vector connections; - - for (const auto &[hostname, _] : connected_hostnames_map) { - connections.push_back(hostname); - } - return connections; - } -}; - -#endif // CAPIOCOMMUNICATIONSERVICE_H diff --git a/src/server/file-manager/file_manager.hpp b/src/server/file-manager/file_manager.hpp deleted file mode 100644 index 70bc2016c..000000000 --- a/src/server/file-manager/file_manager.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef FILE_MANAGER_HEADER_HPP -#define FILE_MANAGER_HEADER_HPP - -#include - -inline std::mutex creation_mutex; -inline std::mutex data_mutex; -/** - * @brief Class that handle all the information related to the files handled by capio, as well - * metadata for such files. - * - */ -class CapioFileManager { - std::unordered_map> thread_awaiting_file_creation; - std::unordered_map> thread_awaiting_data; - - static std::string getAndCreateMetadataPath(const std::string &path); - - static void _unlockThreadAwaitingCreation(const std::string &path, - const std::vector &pids); - - static void _unlockThreadAwaitingData(const std::string &path, - std::unordered_map &pids_awaiting); - - public: - CapioFileManager() { - START_LOG(gettid(), "call()"); - server_println(CAPIO_SERVER_CLI_LOG_SERVER, "CapioFileManager initialization completed."); - } - - ~CapioFileManager() { - START_LOG(gettid(), "call()"); - server_println(CAPIO_SERVER_CLI_LOG_SERVER, "CapioFileManager cleanup completed."); - } - - static uintmax_t get_file_size_if_exists(const std::filesystem::path &path); - static std::string getMetadataPath(const std::string &path); - static void increaseCloseCount(const std::filesystem::path &path); - static bool isCommitted(const std::filesystem::path &path); - static void setCommitted(const std::filesystem::path &path); - static void setCommitted(pid_t tid); - void addThreadAwaitingData(const std::string &path, int tid, size_t expected_size); - void addThreadAwaitingCreation(const std::string &path, pid_t tid); - void checkFilesAwaitingCreation(); - void checkFileAwaitingData(); - void checkDirectoriesNFiles() const; -}; - -inline CapioFileManager *file_manager; - -#include "fs_monitor.hpp" - -#include "file_manager_impl.hpp" - -#endif // FILE_MANAGER_HEADER_HPP \ No newline at end of file diff --git a/src/server/file-manager/fs_monitor.hpp b/src/server/file-manager/fs_monitor.hpp deleted file mode 100644 index c2c523c30..000000000 --- a/src/server/file-manager/fs_monitor.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef CAPIO_FS_FILE_SYSTEM_MONITOR_HPP -#define CAPIO_FS_FILE_SYSTEM_MONITOR_HPP -#include - -/** - * @brief Class that monitors the composition of the CAPIO_DIR directory. - * - */ -class FileSystemMonitor { - std::thread *th; - - bool *continue_execution = new bool; - - static void print_message_error(const std::string &func, const std::exception &exception) { - START_LOG(gettid(), "call()"); - std::cout << std::endl - << "~~~~~~~~~~~~~~[\033[31mFileSystemMonitor: FATAL " - "EXCEPTION\033[0m]~~~~~~~~~~~~~~" - << std::endl - << "| Exception thrown while handling method: " << func << " : " << std::endl - << "| TID of offending thread: " << gettid() << std::endl - << "| PID of offending thread: " << getpid() << std::endl - << "| PPID of offending thread: " << getppid() << std::endl - << "| " << std::endl - << "| `" << typeid(exception).name() << ": " << exception.what() << std::endl - << "|" << std::endl - << "~~~~~~~~~~~~~~[\033[31mFileSystemMonitor: FATAL " - "EXCEPTION\033[0m]~~~~~~~~~~~~~~" - << std::endl - << std::endl; - - ERR_EXIT("%s", exception.what()); - } - - public: - /** - * @brief Main thread execution loop. Main idea is to check - * whether the files exists on the file system. Then if they exists, wake both thread waiting - * for file existence and files waiting for data, as the check on the file size (ie. if there is - * enough data) is carried out by the CapioFileManager class and not by the file_system monitor - * component itself. At creation a thread is spawned that will continue until a process signals - * it to stop by setting the continue_execution parameter to false. - * - * @param continue_execution - */ - static void _main(const bool *continue_execution) { - START_LOG(gettid(), "INFO: instance of FileSystemMonitor"); - - timespec sleep{}; - sleep.tv_nsec = 300; // sleep 0.3 seconds - while (*continue_execution) { - try { - file_manager->checkFilesAwaitingCreation(); - } catch (const std::exception &exception) { - print_message_error("file_manager->checkFilesAwaitingCreation()", exception); - } - - try { - file_manager->checkFileAwaitingData(); - } catch (const std::exception &exception) { - print_message_error("file_manager->checkFileAwaitingData()", exception); - } - - try { - file_manager->checkDirectoriesNFiles(); - } catch (const std::exception &exception) { - print_message_error("file_manager->checkDirectoriesNFiles()", exception); - } - nanosleep(&sleep, nullptr); - } - } - - explicit FileSystemMonitor() { - START_LOG(gettid(), "call()"); - *continue_execution = true; - th = new std::thread(_main, std::ref(continue_execution)); - server_println(CAPIO_SERVER_CLI_LOG_SERVER, - "CapioFileSystemMonitor initialization completed."); - } - - ~FileSystemMonitor() { - START_LOG(gettid(), "call()"); - *continue_execution = false; - try { - th->join(); - } catch (const std::system_error &exception) { - print_message_error("~FileSystemMonitor()::th->joing()", exception); - } - - delete th; - delete continue_execution; - server_println(CAPIO_SERVER_CLI_LOG_SERVER, "CapioFileSystemMonitor cleanup completed."); - } -}; - -inline FileSystemMonitor *fs_monitor; - -#endif // CAPIO_FS_FILE_SYSTEM_MONITOR_HPP \ No newline at end of file diff --git a/src/server/storage-service/CapioFile/CapioFile.hpp b/src/server/storage-service/CapioFile/CapioFile.hpp deleted file mode 100644 index af6ac1a51..000000000 --- a/src/server/storage-service/CapioFile/CapioFile.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef CAPIOFILE_HPP -#define CAPIOFILE_HPP - -class CapioFile { - protected: - const std::string fileName; - std::size_t totalSize; - - public: - explicit CapioFile(const std::string &filePath) : fileName(filePath), totalSize(0) {}; - virtual ~CapioFile() = default; - - [[nodiscard]] std::size_t getSize() const { - START_LOG(gettid(), "call()"); - return totalSize; - } - - [[nodiscard]] const std::string &getFileName() const { return fileName; } - - /** - * Write data to a file stored inside the memory - * @param buffer buffer to store inside memory (i.e. content of the file) - * @param file_offset offset internal to the file - * @param buffer_length Size of the buffer. - */ - virtual std::size_t writeData(const char *buffer, std::size_t file_offset, - std::size_t buffer_length) = 0; - /** - * Read from Capio File - * @param buffer Buffer to read to - * @param file_offset Starting offset of read operation from CapioMemFile - * @param buffer_size Length of buffer - * @return number of bytes read from CapioMemoryFile - */ - virtual std::size_t readData(char *buffer, std::size_t file_offset, - std::size_t buffer_size) = 0; - - /** - * Store data inside the CapioMemoryFile by reading it from a SPSCQueue object. Behaves just - * like the writeData method - * @param queue - * @param offset - * @param length - */ - virtual void readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) = 0; - - /** - * Write the content of the capioFile to a SPSCQueue object - * @param queue - * @param offset - * @param length - * @return - */ - virtual std::size_t writeToQueue(SPSCQueue &queue, std::size_t offset, - std::size_t length) const = 0; -}; - -#endif // CAPIOFILE_HPP \ No newline at end of file diff --git a/src/server/storage-service/CapioFile/CapioRemoteFile.hpp b/src/server/storage-service/CapioFile/CapioRemoteFile.hpp deleted file mode 100644 index 5181e2bae..000000000 --- a/src/server/storage-service/CapioFile/CapioRemoteFile.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef CAPIOREMOTEFILE_HPP -#define CAPIOREMOTEFILE_HPP - -#include - -#include "CapioFile.hpp" - -class CapioRemoteFile : public CapioFile { - public: - explicit CapioRemoteFile(const std::string &filePath) : CapioFile(filePath) {} - - ~CapioRemoteFile() override {} - - /** - * Write data to a file stored inside the memory - * @param buffer buffer to store inside memory (i.e. content of the file) - * @param file_offset offset internal to the file - * @param buffer_length Size of the buffer. - */ - std::size_t writeData(const char *buffer, const std::size_t file_offset, - std::size_t buffer_length) override { - return 0; - } - - /** - * Read from Capio File - * @param buffer Buffer to read to - * @param file_offset Starting offset of read operation from CapioMemFile - * @param buffer_size Length of buffer - * @return number of bytes read from CapioMemoryFile - */ - std::size_t readData(char *buffer, std::size_t file_offset, std::size_t buffer_size) { - return 0; - } - - /** - * Store data inside the CapioMemoryFile by reading it from a SPSCQueue object. Behaves just - * like the writeData method - * @param queue - * @param offset - * @param length - */ - void readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) override {} - - /** - * Write the content of the capioFile to a SPSCQueue object - * @param queue - * @param offset - * @param length - * @return - */ - std::size_t writeToQueue(SPSCQueue &queue, std::size_t offset, - std::size_t length) const override { - return 0; - } -}; - -#endif // CAPIOMEMORYFILE_HPP \ No newline at end of file diff --git a/tests/multinode/backend/CMakeLists.txt b/tests/multinode/backend/CMakeLists.txt index 3b8a79e8d..98445d736 100644 --- a/tests/multinode/backend/CMakeLists.txt +++ b/tests/multinode/backend/CMakeLists.txt @@ -3,7 +3,7 @@ ##################################### set(TARGET_NAME capio_backend_unit_tests) -set(TARGET_INCLUDE_FOLDER "../../../src/server") +set(TARGET_INCLUDE_FOLDER "../../../capio-server") set(TARGET_SOURCES src/main.cpp ) diff --git a/tests/multinode/backend/src/main.cpp b/tests/multinode/backend/src/main.cpp index 768ea9b5f..d1145deb2 100644 --- a/tests/multinode/backend/src/main.cpp +++ b/tests/multinode/backend/src/main.cpp @@ -2,7 +2,7 @@ #include #include -#include "../server/utils/configuration.hpp" +#include "../capio-server/utils/configuration.hpp" #include "MTCL.hpp" #include diff --git a/tests/unit/MemoryFiles/CMakeLists.txt b/tests/unit/MemoryFiles/CMakeLists.txt index 349f168c4..f8022d267 100644 --- a/tests/unit/MemoryFiles/CMakeLists.txt +++ b/tests/unit/MemoryFiles/CMakeLists.txt @@ -2,7 +2,7 @@ # Target information ##################################### set(TARGET_NAME capio_memory_file_unit_tests) -set(TARGET_INCLUDE_FOLDER "${PROJECT_SOURCE_DIR}/src/posix") +set(TARGET_INCLUDE_FOLDER "../../../capio-posix") set(TARGET_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp ) diff --git a/tests/unit/posix/CMakeLists.txt b/tests/unit/posix/CMakeLists.txt index 4bb8bf0a0..491d4e41f 100644 --- a/tests/unit/posix/CMakeLists.txt +++ b/tests/unit/posix/CMakeLists.txt @@ -2,7 +2,7 @@ # Target information ##################################### set(TARGET_NAME capio_posix_unit_tests) -set(TARGET_INCLUDE_FOLDER "${PROJECT_SOURCE_DIR}/src/posix") +set(TARGET_INCLUDE_FOLDER "../../../capio-posix") set(TARGET_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/realpath.cpp ) diff --git a/tests/unit/server/CMakeLists.txt b/tests/unit/server/CMakeLists.txt index b7aa6d0bc..2940a0827 100644 --- a/tests/unit/server/CMakeLists.txt +++ b/tests/unit/server/CMakeLists.txt @@ -3,7 +3,7 @@ ##################################### set(TARGET_NAME capio_server_unit_tests) -set(TARGET_INCLUDE_FOLDER "${PROJECT_SOURCE_DIR}/src/server") +set(TARGET_INCLUDE_FOLDER "../../../capio-server") set(TARGET_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp ) diff --git a/tests/unit/server/src/CapioCacheSPSCQueueTests.hpp b/tests/unit/server/src/CapioCacheSPSCQueueTests.hpp index 35bfc0f5a..d5db897ab 100644 --- a/tests/unit/server/src/CapioCacheSPSCQueueTests.hpp +++ b/tests/unit/server/src/CapioCacheSPSCQueueTests.hpp @@ -3,12 +3,12 @@ #include -#include "../server/utils/configuration.hpp" +#include "../capio-server/utils/configuration.hpp" -#include "../common/capio/response_queue.hpp" -#include "../posix/utils/env.hpp" -#include "../posix/utils/filesystem.hpp" -#include "../posix/utils/types.hpp" +#include "../capio-posix/utils/env.hpp" +#include "../capio-posix/utils/filesystem.hpp" +#include "../capio-posix/utils/types.hpp" +#include "../common-headers/capio/response_queue.hpp" #include "storage-service/CapioFile/CapioMemoryFile.hpp" @@ -16,7 +16,7 @@ inline SPSCQueue *cts_queue, *stc_queue; inline std::unordered_map *bufs_response; inline CircularBuffer *buf_requests; -#include "../posix/utils/cache.hpp" +#include "../capio-posix/utils/cache.hpp" #include "SourceText.hpp" auto checkStringEquality = [](const std::string &a, const std::string &b) { diff --git a/tests/unit/server/src/CapioFileTests.hpp b/tests/unit/server/src/CapioFileTests.hpp index 9380a5554..20548a98f 100644 --- a/tests/unit/server/src/CapioFileTests.hpp +++ b/tests/unit/server/src/CapioFileTests.hpp @@ -1,6 +1,6 @@ #ifndef CAPIOFILETESTS_HPP #define CAPIOFILETESTS_HPP -#include "../server/storage-service/CapioFile/CapioMemoryFile.hpp" +#include "../capio-server/storage-service/CapioFile/CapioMemoryFile.hpp" constexpr size_t FILE_SIZE = 8 * 1024 * 1024; From a099e65615f392034a0e2dd1db18505218a1b251 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Fri, 29 Aug 2025 19:31:24 +0000 Subject: [PATCH 03/10] code format --- capio-common/capio/env.hpp | 2 - .../control-plane/multicast_control_plane.hpp | 15 +- .../capio_communication_service.cpp | 109 ++++---- .../control-plane/fs_control_plane.cpp | 171 ++++++------ .../control-plane/multicast_control_plane.cpp | 248 +++++++++--------- 5 files changed, 268 insertions(+), 277 deletions(-) diff --git a/capio-common/capio/env.hpp b/capio-common/capio/env.hpp index e4f509ef5..069ee5743 100644 --- a/capio-common/capio/env.hpp +++ b/capio-common/capio/env.hpp @@ -113,8 +113,6 @@ inline std::string get_capio_workflow_name() { return name; } - - inline long get_cache_lines() { START_LOG(capio_syscall(SYS_gettid), "call()"); static long data_bufs_size = -1; diff --git a/capio-server/include/communication-service/control-plane/multicast_control_plane.hpp b/capio-server/include/communication-service/control-plane/multicast_control_plane.hpp index ade6e4eb6..a0c1f9b56 100644 --- a/capio-server/include/communication-service/control-plane/multicast_control_plane.hpp +++ b/capio-server/include/communication-service/control-plane/multicast_control_plane.hpp @@ -1,10 +1,10 @@ #ifndef MULTICAST_CONTROL_PLANE_HPP #define MULTICAST_CONTROL_PLANE_HPP -#include #include -#include -#include #include +#include +#include +#include class MulticastControlPlane : public CapioControlPlane { bool *continue_execution; @@ -18,15 +18,14 @@ class MulticastControlPlane : public CapioControlPlane { std::mutex *token_used_to_connect_mutex, int dataplane_backend_port); - - static void multicast_control_plane_incoming_thread(const bool *continue_execution) ; + static void multicast_control_plane_incoming_thread(const bool *continue_execution); public: - explicit MulticastControlPlane(int dataplane_backend_port) ; + explicit MulticastControlPlane(int dataplane_backend_port); - ~MulticastControlPlane() override ; + ~MulticastControlPlane() override; void notify_all(const event_type event, const std::filesystem::path &path) override; }; -#endif //MULTICAST_CONTROL_PLANE_HPP +#endif // MULTICAST_CONTROL_PLANE_HPP diff --git a/capio-server/src/communication-service/capio_communication_service.cpp b/capio-server/src/communication-service/capio_communication_service.cpp index da3470428..2c856a097 100644 --- a/capio-server/src/communication-service/capio_communication_service.cpp +++ b/capio-server/src/communication-service/capio_communication_service.cpp @@ -1,62 +1,61 @@ +#include +#include +#include #include #include -#include #include -#include #include #include -#include - CapioCommunicationService::~CapioCommunicationService() { - delete capio_control_plane; - delete capio_backend; - }; - - CapioCommunicationService::CapioCommunicationService(std::string &backend_name, const int port, - const std::string &control_backend_name) { - START_LOG(gettid(), "call(backend_name=%s)", backend_name.c_str()); - - LOG("My hostname is %s. Starting to listen on connection", - capio_global_configuration->node_name); - - if (backend_name == "MQTT" || backend_name == "MPI") { - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "Warn: selected backend is not yet officially supported. Setting backend to TCP"); - backend_name = "TCP"; - } - - if (backend_name == "TCP" || backend_name == "UCX") { - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "Selected backend is " + backend_name); - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, - "Selected backend port is " + std::to_string(port)); - capio_backend = new MTCLBackend(backend_name, std::to_string(port), - CAPIO_BACKEND_DEFAULT_SLEEP_TIME); - } else if (backend_name == "FS") { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "Selected backend is File System"); - capio_backend = new NoBackend(); - } else if (backend_name == "none") { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, - "Skipping communication backend startup"); - } else { - START_LOG(gettid(), "call()"); - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, - "Provided communication backend " + backend_name + " is invalid"); - ERR_EXIT("No valid backend was provided"); - } - - server_println(CAPIO_SERVER_CLI_LOG_SERVER, - "CapioCommunicationService initialization completed."); - - if (control_backend_name == "fs") { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "Starting FS control plane"); - capio_control_plane = new FSControlPlane(port); - } else if (control_backend_name == "multicast") { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "Starting multicast control plane"); - capio_control_plane = new MulticastControlPlane(port); - } else { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, - "Error: unknown control plane backend: " + control_backend_name); - } +CapioCommunicationService::~CapioCommunicationService() { + delete capio_control_plane; + delete capio_backend; +}; + +CapioCommunicationService::CapioCommunicationService(std::string &backend_name, const int port, + const std::string &control_backend_name) { + START_LOG(gettid(), "call(backend_name=%s)", backend_name.c_str()); + + LOG("My hostname is %s. Starting to listen on connection", + capio_global_configuration->node_name); + + if (backend_name == "MQTT" || backend_name == "MPI") { + server_println( + CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "Warn: selected backend is not yet officially supported. Setting backend to TCP"); + backend_name = "TCP"; + } + + if (backend_name == "TCP" || backend_name == "UCX") { + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "Selected backend is " + backend_name); + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, + "Selected backend port is " + std::to_string(port)); + capio_backend = + new MTCLBackend(backend_name, std::to_string(port), CAPIO_BACKEND_DEFAULT_SLEEP_TIME); + } else if (backend_name == "FS") { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "Selected backend is File System"); + capio_backend = new NoBackend(); + } else if (backend_name == "none") { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "Skipping communication backend startup"); + } else { + START_LOG(gettid(), "call()"); + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, + "Provided communication backend " + backend_name + " is invalid"); + ERR_EXIT("No valid backend was provided"); + } + + server_println(CAPIO_SERVER_CLI_LOG_SERVER, + "CapioCommunicationService initialization completed."); + + if (control_backend_name == "fs") { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "Starting FS control plane"); + capio_control_plane = new FSControlPlane(port); + } else if (control_backend_name == "multicast") { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "Starting multicast control plane"); + capio_control_plane = new MulticastControlPlane(port); + } else { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, + "Error: unknown control plane backend: " + control_backend_name); } +} diff --git a/capio-server/src/communication-service/control-plane/fs_control_plane.cpp b/capio-server/src/communication-service/control-plane/fs_control_plane.cpp index c40ea267c..c3ae7285e 100644 --- a/capio-server/src/communication-service/control-plane/fs_control_plane.cpp +++ b/capio-server/src/communication-service/control-plane/fs_control_plane.cpp @@ -1,109 +1,108 @@ #include #include #include -#include #include #include +#include #include - void FSControlPlane::generate_aliveness_token(const int port) const { - START_LOG(gettid(), "call(port=d)", port); +void FSControlPlane::generate_aliveness_token(const int port) const { + START_LOG(gettid(), "call(port=d)", port); + + std::string token_filename(ownHostname); + token_filename += ".alive_connection"; - std::string token_filename(ownHostname); - token_filename += ".alive_connection"; + LOG("Creating alive token %s", token_filename.c_str()); - LOG("Creating alive token %s", token_filename.c_str()); + std::ofstream FilePort(token_filename); + FilePort << port; + FilePort.close(); - std::ofstream FilePort(token_filename); - FilePort << port; - FilePort.close(); + LOG("Saved self token info to FS"); + server_println(CAPIO_SERVER_CLI_LOG_SERVER, "Generated token at " + token_filename); +} - LOG("Saved self token info to FS"); - server_println(CAPIO_SERVER_CLI_LOG_SERVER, "Generated token at " + token_filename); +void FSControlPlane::delete_aliveness_token() { + START_LOG(gettid(), "call()"); + + std::string token_filename(ownHostname); + token_filename += ".alive_connection"; + if (!std::filesystem::exists(token_filename)) { + LOG("Token does not exists. Skipping delettion"); + return; } - void FSControlPlane::delete_aliveness_token() { - START_LOG(gettid(), "call()"); + LOG("Removing alive token %s", token_filename.c_str()); + std::filesystem::remove(token_filename); + LOG("Removed token"); +} - std::string token_filename(ownHostname); - token_filename += ".alive_connection"; - if (!std::filesystem::exists(token_filename)) { - LOG("Token does not exists. Skipping delettion"); - return; - } +void FSControlPlane::fs_server_aliveness_detector_thread( + const bool *continue_execution, std::vector *token_used_to_connect, + std::mutex *token_used_to_connect_mutex) { + START_LOG(gettid(), "call()"); - LOG("Removing alive token %s", token_filename.c_str()); - std::filesystem::remove(token_filename); - LOG("Removed token"); + if (!continue_execution) { + LOG("Terminating execution"); + return; } -void FSControlPlane::fs_server_aliveness_detector_thread(const bool *continue_execution, - std::vector *token_used_to_connect, - std::mutex *token_used_to_connect_mutex) { - START_LOG(gettid(), "call()"); + auto dir_iterator = std::filesystem::directory_iterator(std::filesystem::current_path()); + for (const auto &entry : dir_iterator) { + const auto token_path = entry.path(); - if (!continue_execution) { - LOG("Terminating execution"); - return; + if (!entry.is_regular_file() || token_path.extension() != ".alive_connection") { + LOG("Filename %s is not valid", entry.path().c_str()); + continue; } - auto dir_iterator = std::filesystem::directory_iterator(std::filesystem::current_path()); - for (const auto &entry : dir_iterator) { - const auto token_path = entry.path(); - - if (!entry.is_regular_file() || token_path.extension() != ".alive_connection") { - LOG("Filename %s is not valid", entry.path().c_str()); - continue; - } - - LOG("Found token %s", token_path.c_str()); - - std::ifstream MyReadFile(token_path.filename()); - std::string remoteHost = entry.path().stem(), remotePort; - LOG("Testing for file: %s (hostname: %s, port=%s)", entry.path().filename().c_str(), - remoteHost.c_str(), remotePort.c_str()); - - getline(MyReadFile, remotePort); - MyReadFile.close(); - - const auto hostname_port = std::string(remoteHost) + ":" + remotePort; - std::lock_guard lock(*token_used_to_connect_mutex); - if (std::find(token_used_to_connect->begin(), token_used_to_connect->end(), - hostname_port) != token_used_to_connect->end()) { - LOG("Token already handled... skipping it!"); - continue; - }; - - // TODO: as of now we will not connect with servers - // TODO: that terminates and then comes back up online... - token_used_to_connect->push_back(hostname_port); - capio_backend->connect_to(std::string(remoteHost) + ":" + remotePort); - } - LOG("Terminated loop. sleeping one second"); - sleep(1); - } + LOG("Found token %s", token_path.c_str()); + std::ifstream MyReadFile(token_path.filename()); + std::string remoteHost = entry.path().stem(), remotePort; + LOG("Testing for file: %s (hostname: %s, port=%s)", entry.path().filename().c_str(), + remoteHost.c_str(), remotePort.c_str()); - FSControlPlane::FSControlPlane(int backend_port) : _backend_port(backend_port) { - gethostname(ownHostname, HOST_NAME_MAX); - generate_aliveness_token(backend_port); - continue_execution = new bool(true); - token_used_to_connect_mutex = new std::mutex(); - thread = new std::thread(fs_server_aliveness_detector_thread, std::ref(continue_execution), - &token_used_to_connect, token_used_to_connect_mutex); - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "FSControlPlane initialization completed."); - }; - - FSControlPlane::~FSControlPlane() { - delete_aliveness_token(); - pthread_cancel(thread->native_handle()); - thread->join(); - delete thread; - delete continue_execution; - delete token_used_to_connect_mutex; - - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, "FSControlPlane cleanup completed."); - } + getline(MyReadFile, remotePort); + MyReadFile.close(); - void FSControlPlane::notify_all(FSControlPlane::event_type event, const std::filesystem::path &path) {} + const auto hostname_port = std::string(remoteHost) + ":" + remotePort; + std::lock_guard lock(*token_used_to_connect_mutex); + if (std::find(token_used_to_connect->begin(), token_used_to_connect->end(), + hostname_port) != token_used_to_connect->end()) { + LOG("Token already handled... skipping it!"); + continue; + }; + + // TODO: as of now we will not connect with servers + // TODO: that terminates and then comes back up online... + token_used_to_connect->push_back(hostname_port); + capio_backend->connect_to(std::string(remoteHost) + ":" + remotePort); + } + LOG("Terminated loop. sleeping one second"); + sleep(1); +} + +FSControlPlane::FSControlPlane(int backend_port) : _backend_port(backend_port) { + gethostname(ownHostname, HOST_NAME_MAX); + generate_aliveness_token(backend_port); + continue_execution = new bool(true); + token_used_to_connect_mutex = new std::mutex(); + thread = new std::thread(fs_server_aliveness_detector_thread, std::ref(continue_execution), + &token_used_to_connect, token_used_to_connect_mutex); + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, "FSControlPlane initialization completed."); +}; + +FSControlPlane::~FSControlPlane() { + delete_aliveness_token(); + pthread_cancel(thread->native_handle()); + thread->join(); + delete thread; + delete continue_execution; + delete token_used_to_connect_mutex; + + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, "FSControlPlane cleanup completed."); +} + +void FSControlPlane::notify_all(FSControlPlane::event_type event, + const std::filesystem::path &path) {} diff --git a/capio-server/src/communication-service/control-plane/multicast_control_plane.cpp b/capio-server/src/communication-service/control-plane/multicast_control_plane.cpp index b959f077e..493d287b8 100644 --- a/capio-server/src/communication-service/control-plane/multicast_control_plane.cpp +++ b/capio-server/src/communication-service/control-plane/multicast_control_plane.cpp @@ -1,159 +1,155 @@ +#include "multicast_utils.hpp" #include #include #include +#include +#include #include #include #include -#include "multicast_utils.hpp" -#include -#include +void MulticastControlPlane::multicast_server_aliveness_thread( + const bool *continue_execution, std::vector *token_used_to_connect, + std::mutex *token_used_to_connect_mutex, int dataplane_backend_port) { -void MulticastControlPlane::multicast_server_aliveness_thread(const bool *continue_execution, - std::vector *token_used_to_connect, - std::mutex *token_used_to_connect_mutex, - int dataplane_backend_port) { - - START_LOG(gettid(), "call(data_plane_backend_port=%d)", dataplane_backend_port); - - char incomingMessage[MULTICAST_ALIVE_TOKEN_MESSAGE_SIZE]; - - const std::string SELF_TOKEN = std::string(capio_global_configuration->node_name) + ":" + - std::to_string(dataplane_backend_port); - - sockaddr_in addr = {}; - socklen_t addrlen = {}; - const auto discovery_socket = - open_outgoing_socket(MULTICAST_DISCOVERY_ADDR, MULTICAST_DISCOVERY_PORT, addr, addrlen); - - server_println(CAPIO_SERVER_CLI_LOG_SERVER, std::string("Multicast discovery service @ ") + - MULTICAST_DISCOVERY_ADDR + ":" + - std::to_string(MULTICAST_DISCOVERY_PORT)); - - while (*continue_execution) { - bzero(incomingMessage, sizeof(incomingMessage)); - // Send port of local data plane backend - send_multicast_alive_token(dataplane_backend_port); - LOG("Waiting for incoming token..."); - - do { - const auto recv_sice = - recvfrom(discovery_socket, incomingMessage, MULTICAST_ALIVE_TOKEN_MESSAGE_SIZE, - 0, reinterpret_cast(&addr), &addrlen); - LOG("Received multicast data of size %ld and content %s", recv_sice, - incomingMessage); - if (recv_sice < 0) { - server_println( - CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, - std::string("WARNING: received 0 bytes from multicast socket: ")); - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, - "Execution will continue only with FS discovery support"); - return; - } - } while (std::string(incomingMessage) == SELF_TOKEN); - - std::lock_guard lg(*token_used_to_connect_mutex); - if (std::find(token_used_to_connect->begin(), token_used_to_connect->end(), - incomingMessage) == token_used_to_connect->end()) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, - "Multicast adv: " + std::string(incomingMessage)); - LOG("Received message: %s", incomingMessage); - token_used_to_connect->push_back(incomingMessage); - capio_backend->connect_to(incomingMessage); - } + START_LOG(gettid(), "call(data_plane_backend_port=%d)", dataplane_backend_port); - sleep(1); - } - } + char incomingMessage[MULTICAST_ALIVE_TOKEN_MESSAGE_SIZE]; + + const std::string SELF_TOKEN = std::string(capio_global_configuration->node_name) + ":" + + std::to_string(dataplane_backend_port); + + sockaddr_in addr = {}; + socklen_t addrlen = {}; + const auto discovery_socket = + open_outgoing_socket(MULTICAST_DISCOVERY_ADDR, MULTICAST_DISCOVERY_PORT, addr, addrlen); - void MulticastControlPlane::multicast_control_plane_incoming_thread(const bool *continue_execution) { - START_LOG(gettid(), "Call(multicast_control_plane_incoming_thread)"); - char incoming_msg[MULTICAST_CONTROLPL_MESSAGE_SIZE] = {0}; - sockaddr_in addr = {}; - socklen_t addrlen = {}; - const auto discovery_socket = - open_outgoing_socket(MULTICAST_CONTROLPL_ADDR, MULTICAST_CONTROLPL_PORT, addr, addrlen); + server_println(CAPIO_SERVER_CLI_LOG_SERVER, std::string("Multicast discovery service @ ") + + MULTICAST_DISCOVERY_ADDR + ":" + + std::to_string(MULTICAST_DISCOVERY_PORT)); - server_println(CAPIO_SERVER_CLI_LOG_SERVER, std::string("Multicast control plane @ ") + - MULTICAST_CONTROLPL_ADDR + ":" + - std::to_string(MULTICAST_CONTROLPL_PORT)); + while (*continue_execution) { + bzero(incomingMessage, sizeof(incomingMessage)); + // Send port of local data plane backend + send_multicast_alive_token(dataplane_backend_port); + LOG("Waiting for incoming token..."); - while (*continue_execution) { - bzero(incoming_msg, sizeof(incoming_msg)); + do { const auto recv_sice = - recvfrom(discovery_socket, incoming_msg, MULTICAST_CONTROLPL_MESSAGE_SIZE, 0, + recvfrom(discovery_socket, incomingMessage, MULTICAST_ALIVE_TOKEN_MESSAGE_SIZE, 0, reinterpret_cast(&addr), &addrlen); - LOG("Received multicast data of size %ld and content %s", recv_sice, incoming_msg); + LOG("Received multicast data of size %ld and content %s", recv_sice, incomingMessage); if (recv_sice < 0) { server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, std::string("WARNING: received 0 bytes from multicast socket: ")); server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, "Execution will continue only with FS discovery support"); - continue; - } - - event_type event; - char source_hostname[HOST_NAME_MAX]; - char source_path[PATH_MAX]; - - sscanf(incoming_msg, "%d %s %s", reinterpret_cast(&event), source_hostname, - source_path); - - if (strcmp(capio_global_configuration->node_name, source_hostname) == 0) { - continue; + return; } + } while (std::string(incomingMessage) == SELF_TOKEN); + std::lock_guard lg(*token_used_to_connect_mutex); + if (std::find(token_used_to_connect->begin(), token_used_to_connect->end(), + incomingMessage) == token_used_to_connect->end()) { server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, - "Received control message: " + std::string(incoming_msg)); + "Multicast adv: " + std::string(incomingMessage)); + LOG("Received message: %s", incomingMessage); + token_used_to_connect->push_back(incomingMessage); + capio_backend->connect_to(incomingMessage); } - close(discovery_socket); + sleep(1); } +} + +void MulticastControlPlane::multicast_control_plane_incoming_thread( + const bool *continue_execution) { + START_LOG(gettid(), "Call(multicast_control_plane_incoming_thread)"); + char incoming_msg[MULTICAST_CONTROLPL_MESSAGE_SIZE] = {0}; + sockaddr_in addr = {}; + socklen_t addrlen = {}; + const auto discovery_socket = + open_outgoing_socket(MULTICAST_CONTROLPL_ADDR, MULTICAST_CONTROLPL_PORT, addr, addrlen); + + server_println(CAPIO_SERVER_CLI_LOG_SERVER, std::string("Multicast control plane @ ") + + MULTICAST_CONTROLPL_ADDR + ":" + + std::to_string(MULTICAST_CONTROLPL_PORT)); + + while (*continue_execution) { + bzero(incoming_msg, sizeof(incoming_msg)); + const auto recv_sice = + recvfrom(discovery_socket, incoming_msg, MULTICAST_CONTROLPL_MESSAGE_SIZE, 0, + reinterpret_cast(&addr), &addrlen); + LOG("Received multicast data of size %ld and content %s", recv_sice, incoming_msg); + if (recv_sice < 0) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, + std::string("WARNING: received 0 bytes from multicast socket: ")); + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, + "Execution will continue only with FS discovery support"); + continue; + } + event_type event; + char source_hostname[HOST_NAME_MAX]; + char source_path[PATH_MAX]; -MulticastControlPlane::MulticastControlPlane(int dataplane_backend_port) { - START_LOG(gettid(), "call(dataplane_backend_port=%d)", dataplane_backend_port); - gethostname(ownHostname, HOST_NAME_MAX); - continue_execution = new bool(true); - token_used_to_connect_mutex = new std::mutex(); + sscanf(incoming_msg, "%d %s %s", reinterpret_cast(&event), source_hostname, + source_path); - discovery_thread = new std::thread(multicast_server_aliveness_thread, continue_execution, - &token_used_to_connect, token_used_to_connect_mutex, - dataplane_backend_port); - - controlpl_incoming = - new std::thread(multicast_control_plane_incoming_thread, continue_execution); - } + if (strcmp(capio_global_configuration->node_name, source_hostname) == 0) { + continue; + } - MulticastControlPlane::~MulticastControlPlane() { - *continue_execution = false; - pthread_cancel(discovery_thread->native_handle()); - discovery_thread->join(); - pthread_cancel(controlpl_incoming->native_handle()); - controlpl_incoming->join(); - delete token_used_to_connect_mutex; - delete discovery_thread; - delete continue_execution; - server_println(CAPIO_SERVER_CLI_LOG_SERVER, "MulticastControlPlane correctly terminated"); + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_INFO, + "Received control message: " + std::string(incoming_msg)); } - void MulticastControlPlane::notify_all(const event_type event, const std::filesystem::path &path) { - START_LOG(gettid(), "call(event=%s, path=%s)", event, path.string().c_str()); - sockaddr_in addr = {}; - const auto socket = open_outgoing_multicast_socket(MULTICAST_CONTROLPL_ADDR, - MULTICAST_CONTROLPL_PORT, &addr); + close(discovery_socket); +} - char message[MULTICAST_CONTROLPL_MESSAGE_SIZE]; - sprintf(message, "%03d %s %s", event, ownHostname, path.string().c_str()); - - LOG("Sending message: %s", message); - if (sendto(socket, message, strlen(message), 0, reinterpret_cast(&addr), - sizeof(addr)) < 0) { - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, - "WARNING: unable to send message(" + std::string(message) + - ") to multicast address!: " + strerror(errno)); - } - LOG("Sent message"); - - close(socket); +MulticastControlPlane::MulticastControlPlane(int dataplane_backend_port) { + START_LOG(gettid(), "call(dataplane_backend_port=%d)", dataplane_backend_port); + gethostname(ownHostname, HOST_NAME_MAX); + continue_execution = new bool(true); + token_used_to_connect_mutex = new std::mutex(); + + discovery_thread = new std::thread(multicast_server_aliveness_thread, continue_execution, + &token_used_to_connect, token_used_to_connect_mutex, + dataplane_backend_port); + + controlpl_incoming = + new std::thread(multicast_control_plane_incoming_thread, continue_execution); +} + +MulticastControlPlane::~MulticastControlPlane() { + *continue_execution = false; + pthread_cancel(discovery_thread->native_handle()); + discovery_thread->join(); + pthread_cancel(controlpl_incoming->native_handle()); + controlpl_incoming->join(); + delete token_used_to_connect_mutex; + delete discovery_thread; + delete continue_execution; + server_println(CAPIO_SERVER_CLI_LOG_SERVER, "MulticastControlPlane correctly terminated"); +} + +void MulticastControlPlane::notify_all(const event_type event, const std::filesystem::path &path) { + START_LOG(gettid(), "call(event=%s, path=%s)", event, path.string().c_str()); + sockaddr_in addr = {}; + const auto socket = + open_outgoing_multicast_socket(MULTICAST_CONTROLPL_ADDR, MULTICAST_CONTROLPL_PORT, &addr); + + char message[MULTICAST_CONTROLPL_MESSAGE_SIZE]; + sprintf(message, "%03d %s %s", event, ownHostname, path.string().c_str()); + + LOG("Sending message: %s", message); + if (sendto(socket, message, strlen(message), 0, reinterpret_cast(&addr), + sizeof(addr)) < 0) { + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_ERROR, + "WARNING: unable to send message(" + std::string(message) + + ") to multicast address!: " + strerror(errno)); } + LOG("Sent message"); + + close(socket); +} From 26745281106178f04a526c42c0cec0ee9503f4c0 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Fri, 29 Aug 2025 19:47:53 +0000 Subject: [PATCH 04/10] Dockerfile fix --- Dockerfile | 4 +++- .../communication-service/control-plane/multicast_utils.hpp | 6 ++++++ tests/unit/server/src/CapioCacheSPSCQueueTests.hpp | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index ab6078535..cfbd1db84 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,9 @@ RUN apt update \ COPY CMakeLists.txt /opt/capio/ COPY scripts /opt/capio/scripts -COPY src /opt/capio/src +COPY capio-common /opt/capio/capio-common +COPY capio-posix /opt/capio/capio-posix +COPY capio-server /opt/capio/capio-server COPY tests /opt/capio/tests COPY capiorun /opt/capio/capiorun diff --git a/capio-server/src/communication-service/control-plane/multicast_utils.hpp b/capio-server/src/communication-service/control-plane/multicast_utils.hpp index dfe44db42..8684deedf 100644 --- a/capio-server/src/communication-service/control-plane/multicast_utils.hpp +++ b/capio-server/src/communication-service/control-plane/multicast_utils.hpp @@ -1,6 +1,12 @@ #ifndef CAPIO_MULTICAST_UTILS_HPP #define CAPIO_MULTICAST_UTILS_HPP +#include +#include +#include +#include +#include +#include #include static int open_outgoing_multicast_socket(const char *address, const int port, sockaddr_in *addr) { diff --git a/tests/unit/server/src/CapioCacheSPSCQueueTests.hpp b/tests/unit/server/src/CapioCacheSPSCQueueTests.hpp index d5db897ab..eae76bca0 100644 --- a/tests/unit/server/src/CapioCacheSPSCQueueTests.hpp +++ b/tests/unit/server/src/CapioCacheSPSCQueueTests.hpp @@ -8,7 +8,7 @@ #include "../capio-posix/utils/env.hpp" #include "../capio-posix/utils/filesystem.hpp" #include "../capio-posix/utils/types.hpp" -#include "../common-headers/capio/response_queue.hpp" +#include "capio/response_queue.hpp" #include "storage-service/CapioFile/CapioMemoryFile.hpp" From 7b6ee7f972a4e6d236d491770ce3f02a442217f7 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Sat, 30 Aug 2025 07:17:41 +0000 Subject: [PATCH 05/10] Fixed cmake compilation of tests --- CMakeLists.txt | 2 +- Dockerfile | 2 +- {tests => capio-tests}/CMakeLists.txt | 0 .../multinode/backend/CMakeLists.txt | 23 +++++++++++++------ .../multinode/backend/docker-compose.yml | 0 .../multinode/backend/src/MTCL.hpp | 4 +++- .../multinode/backend/src/main.cpp | 0 .../multinode/integration/CMakeLists.txt | 0 .../multinode/integration/docker-compose.yml | 0 .../multinode/integration/src/common.hpp | 0 .../multinode/integration/src/mapreduce.cpp | 0 .../multinode/integration/src/merge.cpp | 0 .../multinode/integration/src/split.cpp | 0 .../unit/MemoryFiles/CMakeLists.txt | 9 +++++++- .../unit/MemoryFiles/src/main.cpp | 0 .../unit/posix/CMakeLists.txt | 0 .../unit/posix/src/realpath.cpp | 0 .../unit/server/CMakeLists.txt | 13 +++++++---- .../server/src/CapioCacheSPSCQueueTests.hpp | 2 +- .../unit/server/src/CapioFileTests.hpp | 2 +- .../unit/server/src/SourceText.hpp | 0 .../unit/server/src/main.cpp | 0 .../unit/syscall/CMakeLists.txt | 0 .../unit/syscall/src/chdir.cpp | 0 .../unit/syscall/src/clone.cpp | 0 .../unit/syscall/src/directory.cpp | 0 .../unit/syscall/src/dirent.cpp | 0 .../unit/syscall/src/dup.cpp | 0 .../unit/syscall/src/fcntl.cpp | 0 .../unit/syscall/src/file.cpp | 0 .../unit/syscall/src/main.cpp | 0 .../unit/syscall/src/rename.cpp | 0 .../unit/syscall/src/stat.cpp | 0 .../unit/syscall/src/statx.cpp | 0 .../unit/syscall/src/write.cpp | 0 35 files changed, 39 insertions(+), 18 deletions(-) rename {tests => capio-tests}/CMakeLists.txt (100%) rename {tests => capio-tests}/multinode/backend/CMakeLists.txt (78%) rename {tests => capio-tests}/multinode/backend/docker-compose.yml (100%) rename {tests => capio-tests}/multinode/backend/src/MTCL.hpp (93%) rename {tests => capio-tests}/multinode/backend/src/main.cpp (100%) rename {tests => capio-tests}/multinode/integration/CMakeLists.txt (100%) rename {tests => capio-tests}/multinode/integration/docker-compose.yml (100%) rename {tests => capio-tests}/multinode/integration/src/common.hpp (100%) rename {tests => capio-tests}/multinode/integration/src/mapreduce.cpp (100%) rename {tests => capio-tests}/multinode/integration/src/merge.cpp (100%) rename {tests => capio-tests}/multinode/integration/src/split.cpp (100%) rename {tests => capio-tests}/unit/MemoryFiles/CMakeLists.txt (89%) rename {tests => capio-tests}/unit/MemoryFiles/src/main.cpp (100%) rename {tests => capio-tests}/unit/posix/CMakeLists.txt (100%) rename {tests => capio-tests}/unit/posix/src/realpath.cpp (100%) rename {tests => capio-tests}/unit/server/CMakeLists.txt (76%) rename {tests => capio-tests}/unit/server/src/CapioCacheSPSCQueueTests.hpp (99%) rename {tests => capio-tests}/unit/server/src/CapioFileTests.hpp (98%) rename {tests => capio-tests}/unit/server/src/SourceText.hpp (100%) rename {tests => capio-tests}/unit/server/src/main.cpp (100%) rename {tests => capio-tests}/unit/syscall/CMakeLists.txt (100%) rename {tests => capio-tests}/unit/syscall/src/chdir.cpp (100%) rename {tests => capio-tests}/unit/syscall/src/clone.cpp (100%) rename {tests => capio-tests}/unit/syscall/src/directory.cpp (100%) rename {tests => capio-tests}/unit/syscall/src/dirent.cpp (100%) rename {tests => capio-tests}/unit/syscall/src/dup.cpp (100%) rename {tests => capio-tests}/unit/syscall/src/fcntl.cpp (100%) rename {tests => capio-tests}/unit/syscall/src/file.cpp (100%) rename {tests => capio-tests}/unit/syscall/src/main.cpp (100%) rename {tests => capio-tests}/unit/syscall/src/rename.cpp (100%) rename {tests => capio-tests}/unit/syscall/src/stat.cpp (100%) rename {tests => capio-tests}/unit/syscall/src/statx.cpp (100%) rename {tests => capio-tests}/unit/syscall/src/write.cpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e78276fe..635470d1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,5 +111,5 @@ install( IF (CAPIO_BUILD_TESTS) message(STATUS "Building CAPIO test suite") add_compile_definitions(CAPIO_BUILD_TESTS) - add_subdirectory(tests) + add_subdirectory(capio-tests) ENDIF (CAPIO_BUILD_TESTS) \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index cfbd1db84..919b22d79 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ COPY scripts /opt/capio/scripts COPY capio-common /opt/capio/capio-common COPY capio-posix /opt/capio/capio-posix COPY capio-server /opt/capio/capio-server -COPY tests /opt/capio/tests +COPY capio-tests /opt/capio/tests COPY capiorun /opt/capio/capiorun RUN mkdir -p /opt/capio/build \ diff --git a/tests/CMakeLists.txt b/capio-tests/CMakeLists.txt similarity index 100% rename from tests/CMakeLists.txt rename to capio-tests/CMakeLists.txt diff --git a/tests/multinode/backend/CMakeLists.txt b/capio-tests/multinode/backend/CMakeLists.txt similarity index 78% rename from tests/multinode/backend/CMakeLists.txt rename to capio-tests/multinode/backend/CMakeLists.txt index 98445d736..cd83cbea5 100644 --- a/tests/multinode/backend/CMakeLists.txt +++ b/capio-tests/multinode/backend/CMakeLists.txt @@ -3,7 +3,6 @@ ##################################### set(TARGET_NAME capio_backend_unit_tests) -set(TARGET_INCLUDE_FOLDER "../../../capio-server") set(TARGET_SOURCES src/main.cpp ) @@ -14,18 +13,28 @@ set(TARGET_SOURCES add_executable(${TARGET_NAME} ${TARGET_SOURCES}) ##################################### - # Include files and directories ##################################### -file(GLOB_RECURSE CAPIO_SERVER_HEADERS "${TARGET_INCLUDE_FOLDER}/*.hpp") -target_sources(${TARGET_NAME} PRIVATE - "${CAPIO_COMMON_HEADERS}" - "${CAPIO_SERVER_HEADERS}" -) target_include_directories(${TARGET_NAME} PRIVATE ${TARGET_INCLUDE_FOLDER} ${mtcl_SOURCE_DIR}/include + "${CMAKE_SOURCE_DIR}/capio-server/" +) + +file(GLOB_RECURSE CAPIO_SERVER_SOURCES + "${CMAKE_SOURCE_DIR}/capio-server/src/communication-service/*.cpp" ) +file(GLOB_RECURSE CAPIO_SERVER_HEADERS + "${TARGET_INCLUDE_FOLDER}/*.hpp" +) + +target_sources(${TARGET_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp + ${CAPIO_SERVER_SOURCES} + "${CAPIO_COMMON_HEADERS}" + "${CAPIO_SERVER_HEADERS}" +) + ##################################### # Link libraries diff --git a/tests/multinode/backend/docker-compose.yml b/capio-tests/multinode/backend/docker-compose.yml similarity index 100% rename from tests/multinode/backend/docker-compose.yml rename to capio-tests/multinode/backend/docker-compose.yml diff --git a/tests/multinode/backend/src/MTCL.hpp b/capio-tests/multinode/backend/src/MTCL.hpp similarity index 93% rename from tests/multinode/backend/src/MTCL.hpp rename to capio-tests/multinode/backend/src/MTCL.hpp index f74c3ccc0..19bf9192c 100644 --- a/tests/multinode/backend/src/MTCL.hpp +++ b/capio-tests/multinode/backend/src/MTCL.hpp @@ -2,8 +2,10 @@ #define TEST_CAPIOCOMMUNICATIONSERVICE_HPP #include -#include +#include #include +#include +#include #include constexpr char TEST_MESSAGE[] = "hello world how is it going?"; diff --git a/tests/multinode/backend/src/main.cpp b/capio-tests/multinode/backend/src/main.cpp similarity index 100% rename from tests/multinode/backend/src/main.cpp rename to capio-tests/multinode/backend/src/main.cpp diff --git a/tests/multinode/integration/CMakeLists.txt b/capio-tests/multinode/integration/CMakeLists.txt similarity index 100% rename from tests/multinode/integration/CMakeLists.txt rename to capio-tests/multinode/integration/CMakeLists.txt diff --git a/tests/multinode/integration/docker-compose.yml b/capio-tests/multinode/integration/docker-compose.yml similarity index 100% rename from tests/multinode/integration/docker-compose.yml rename to capio-tests/multinode/integration/docker-compose.yml diff --git a/tests/multinode/integration/src/common.hpp b/capio-tests/multinode/integration/src/common.hpp similarity index 100% rename from tests/multinode/integration/src/common.hpp rename to capio-tests/multinode/integration/src/common.hpp diff --git a/tests/multinode/integration/src/mapreduce.cpp b/capio-tests/multinode/integration/src/mapreduce.cpp similarity index 100% rename from tests/multinode/integration/src/mapreduce.cpp rename to capio-tests/multinode/integration/src/mapreduce.cpp diff --git a/tests/multinode/integration/src/merge.cpp b/capio-tests/multinode/integration/src/merge.cpp similarity index 100% rename from tests/multinode/integration/src/merge.cpp rename to capio-tests/multinode/integration/src/merge.cpp diff --git a/tests/multinode/integration/src/split.cpp b/capio-tests/multinode/integration/src/split.cpp similarity index 100% rename from tests/multinode/integration/src/split.cpp rename to capio-tests/multinode/integration/src/split.cpp diff --git a/tests/unit/MemoryFiles/CMakeLists.txt b/capio-tests/unit/MemoryFiles/CMakeLists.txt similarity index 89% rename from tests/unit/MemoryFiles/CMakeLists.txt rename to capio-tests/unit/MemoryFiles/CMakeLists.txt index f8022d267..7d436e931 100644 --- a/tests/unit/MemoryFiles/CMakeLists.txt +++ b/capio-tests/unit/MemoryFiles/CMakeLists.txt @@ -2,9 +2,16 @@ # Target information ##################################### set(TARGET_NAME capio_memory_file_unit_tests) -set(TARGET_INCLUDE_FOLDER "../../../capio-posix") + +file(GLOB_RECURSE CAPIO_SERVER_SOURCES ${CMAKE_SOURCE_DIR}/capio-server/ "*.cpp") + +set(TARGET_INCLUDE_FOLDER + "${CMAKE_SOURCE_DIR}/capio-server/" + "${CMAKE_SOURCE_DIR}../../../capio-posix") + set(TARGET_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp + ${CAPIO_SERVER_SOURCES} ) ##################################### diff --git a/tests/unit/MemoryFiles/src/main.cpp b/capio-tests/unit/MemoryFiles/src/main.cpp similarity index 100% rename from tests/unit/MemoryFiles/src/main.cpp rename to capio-tests/unit/MemoryFiles/src/main.cpp diff --git a/tests/unit/posix/CMakeLists.txt b/capio-tests/unit/posix/CMakeLists.txt similarity index 100% rename from tests/unit/posix/CMakeLists.txt rename to capio-tests/unit/posix/CMakeLists.txt diff --git a/tests/unit/posix/src/realpath.cpp b/capio-tests/unit/posix/src/realpath.cpp similarity index 100% rename from tests/unit/posix/src/realpath.cpp rename to capio-tests/unit/posix/src/realpath.cpp diff --git a/tests/unit/server/CMakeLists.txt b/capio-tests/unit/server/CMakeLists.txt similarity index 76% rename from tests/unit/server/CMakeLists.txt rename to capio-tests/unit/server/CMakeLists.txt index 2940a0827..0b3215300 100644 --- a/tests/unit/server/CMakeLists.txt +++ b/capio-tests/unit/server/CMakeLists.txt @@ -3,10 +3,6 @@ ##################################### set(TARGET_NAME capio_server_unit_tests) -set(TARGET_INCLUDE_FOLDER "../../../capio-server") -set(TARGET_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp -) ##################################### # Target definition @@ -14,11 +10,18 @@ set(TARGET_SOURCES add_executable(${TARGET_NAME} ${TARGET_SOURCES}) ##################################### - # Include files and directories ##################################### +file(GLOB_RECURSE CAPIO_SERVER_SOURCES + "${CMAKE_SOURCE_DIR}/capio-server/src/storage-service/*.cpp" + "${CMAKE_SOURCE_DIR}/capio-server/src/capio-cl-engine/capio_cl_engine.cpp" + "${CMAKE_SOURCE_DIR}/capio-server/src/client-manager/client_manager.cpp" +) file(GLOB_RECURSE CAPIO_SERVER_HEADERS "${TARGET_INCLUDE_FOLDER}/*.hpp") +set(TARGET_INCLUDE_FOLDER "${CMAKE_SOURCE_DIR}/capio-server/") target_sources(${TARGET_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp + ${CAPIO_SERVER_SOURCES} "${CAPIO_COMMON_HEADERS}" "${CAPIO_SERVER_HEADERS}" ) diff --git a/tests/unit/server/src/CapioCacheSPSCQueueTests.hpp b/capio-tests/unit/server/src/CapioCacheSPSCQueueTests.hpp similarity index 99% rename from tests/unit/server/src/CapioCacheSPSCQueueTests.hpp rename to capio-tests/unit/server/src/CapioCacheSPSCQueueTests.hpp index eae76bca0..b65f777b0 100644 --- a/tests/unit/server/src/CapioCacheSPSCQueueTests.hpp +++ b/capio-tests/unit/server/src/CapioCacheSPSCQueueTests.hpp @@ -10,7 +10,7 @@ #include "../capio-posix/utils/types.hpp" #include "capio/response_queue.hpp" -#include "storage-service/CapioFile/CapioMemoryFile.hpp" +#include inline SPSCQueue *cts_queue, *stc_queue; inline std::unordered_map *bufs_response; diff --git a/tests/unit/server/src/CapioFileTests.hpp b/capio-tests/unit/server/src/CapioFileTests.hpp similarity index 98% rename from tests/unit/server/src/CapioFileTests.hpp rename to capio-tests/unit/server/src/CapioFileTests.hpp index 20548a98f..72ebb7ce2 100644 --- a/tests/unit/server/src/CapioFileTests.hpp +++ b/capio-tests/unit/server/src/CapioFileTests.hpp @@ -1,6 +1,6 @@ #ifndef CAPIOFILETESTS_HPP #define CAPIOFILETESTS_HPP -#include "../capio-server/storage-service/CapioFile/CapioMemoryFile.hpp" +#include constexpr size_t FILE_SIZE = 8 * 1024 * 1024; diff --git a/tests/unit/server/src/SourceText.hpp b/capio-tests/unit/server/src/SourceText.hpp similarity index 100% rename from tests/unit/server/src/SourceText.hpp rename to capio-tests/unit/server/src/SourceText.hpp diff --git a/tests/unit/server/src/main.cpp b/capio-tests/unit/server/src/main.cpp similarity index 100% rename from tests/unit/server/src/main.cpp rename to capio-tests/unit/server/src/main.cpp diff --git a/tests/unit/syscall/CMakeLists.txt b/capio-tests/unit/syscall/CMakeLists.txt similarity index 100% rename from tests/unit/syscall/CMakeLists.txt rename to capio-tests/unit/syscall/CMakeLists.txt diff --git a/tests/unit/syscall/src/chdir.cpp b/capio-tests/unit/syscall/src/chdir.cpp similarity index 100% rename from tests/unit/syscall/src/chdir.cpp rename to capio-tests/unit/syscall/src/chdir.cpp diff --git a/tests/unit/syscall/src/clone.cpp b/capio-tests/unit/syscall/src/clone.cpp similarity index 100% rename from tests/unit/syscall/src/clone.cpp rename to capio-tests/unit/syscall/src/clone.cpp diff --git a/tests/unit/syscall/src/directory.cpp b/capio-tests/unit/syscall/src/directory.cpp similarity index 100% rename from tests/unit/syscall/src/directory.cpp rename to capio-tests/unit/syscall/src/directory.cpp diff --git a/tests/unit/syscall/src/dirent.cpp b/capio-tests/unit/syscall/src/dirent.cpp similarity index 100% rename from tests/unit/syscall/src/dirent.cpp rename to capio-tests/unit/syscall/src/dirent.cpp diff --git a/tests/unit/syscall/src/dup.cpp b/capio-tests/unit/syscall/src/dup.cpp similarity index 100% rename from tests/unit/syscall/src/dup.cpp rename to capio-tests/unit/syscall/src/dup.cpp diff --git a/tests/unit/syscall/src/fcntl.cpp b/capio-tests/unit/syscall/src/fcntl.cpp similarity index 100% rename from tests/unit/syscall/src/fcntl.cpp rename to capio-tests/unit/syscall/src/fcntl.cpp diff --git a/tests/unit/syscall/src/file.cpp b/capio-tests/unit/syscall/src/file.cpp similarity index 100% rename from tests/unit/syscall/src/file.cpp rename to capio-tests/unit/syscall/src/file.cpp diff --git a/tests/unit/syscall/src/main.cpp b/capio-tests/unit/syscall/src/main.cpp similarity index 100% rename from tests/unit/syscall/src/main.cpp rename to capio-tests/unit/syscall/src/main.cpp diff --git a/tests/unit/syscall/src/rename.cpp b/capio-tests/unit/syscall/src/rename.cpp similarity index 100% rename from tests/unit/syscall/src/rename.cpp rename to capio-tests/unit/syscall/src/rename.cpp diff --git a/tests/unit/syscall/src/stat.cpp b/capio-tests/unit/syscall/src/stat.cpp similarity index 100% rename from tests/unit/syscall/src/stat.cpp rename to capio-tests/unit/syscall/src/stat.cpp diff --git a/tests/unit/syscall/src/statx.cpp b/capio-tests/unit/syscall/src/statx.cpp similarity index 100% rename from tests/unit/syscall/src/statx.cpp rename to capio-tests/unit/syscall/src/statx.cpp diff --git a/tests/unit/syscall/src/write.cpp b/capio-tests/unit/syscall/src/write.cpp similarity index 100% rename from tests/unit/syscall/src/write.cpp rename to capio-tests/unit/syscall/src/write.cpp From efdd15a7d5568d11935e6f4d55266c9feaf0fb09 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Sat, 30 Aug 2025 07:25:32 +0000 Subject: [PATCH 06/10] fix --- .github/workflows/ci-tests.yaml | 6 ++++-- Dockerfile | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index ac4009a39..6a10fcc39 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -70,8 +70,10 @@ jobs: strategy: matrix: path: - - "src" - - "tests" + - "capio-posix" + - "capio-server" + - "capio-common" + - "capio-tests" steps: - uses: actions/checkout@v4 - name: "Run clang-format style check" diff --git a/Dockerfile b/Dockerfile index 919b22d79..de3a4da2e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ COPY scripts /opt/capio/scripts COPY capio-common /opt/capio/capio-common COPY capio-posix /opt/capio/capio-posix COPY capio-server /opt/capio/capio-server -COPY capio-tests /opt/capio/tests +COPY capio-tests /opt/capio/capio-tests COPY capiorun /opt/capio/capiorun RUN mkdir -p /opt/capio/build \ From c19c5888d561c6de991f90a708a583600c9e004e Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Sat, 30 Aug 2025 07:35:33 +0000 Subject: [PATCH 07/10] reformat --- .github/workflows/ci-tests.yaml | 2 +- capio-posix/utils/env.hpp | 1 - capio-server/capio_server.cpp | 10 +- .../include/capio-cl-engine/json_parser.hpp | 2 +- .../include/client-manager/handlers.hpp | 9 +- .../control-plane/capio_control_plane.hpp | 4 +- .../control-plane/fs_control_plane.hpp | 16 +- .../data-plane/backend_interface.hpp | 4 +- .../data-plane/transport_unit.hpp | 7 +- .../include/file-manager/fs_monitor.hpp | 4 +- .../include/storage-service/capio_file.hpp | 38 ++- .../storage-service/capio_storage_service.hpp | 26 +- .../src/capio-cl-engine/capio_cl_engine.cpp | 2 +- .../src/client-manager/client_manager.cpp | 137 +++++---- .../src/client-manager/handlers/close.cpp | 5 +- .../src/client-manager/handlers/consent.cpp | 5 +- .../src/client-manager/handlers/open.cpp | 6 +- .../src/file-manager/file_manager.cpp | 35 ++- capio-server/src/file-manager/fs_monitor.cpp | 12 +- .../src/storage-service/capio_memory_file.cpp | 245 ++++++++-------- .../src/storage-service/capio_remote_file.cpp | 34 +-- .../storage-service/capio_storage_service.cpp | 276 +++++++++--------- capio-server/utils/configuration.hpp | 2 +- capio-server/utils/signals.hpp | 2 +- 24 files changed, 416 insertions(+), 468 deletions(-) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 6a10fcc39..ec9aa73e6 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -19,7 +19,7 @@ jobs: - name: "Run codespell" uses: codespell-project/actions-codespell@v2 with: - exclude_file: tests/unit/server/src/SourceText.hpp + exclude_file: capio-tests/unit/server/src/SourceText.hpp docker-check: name: "Check Docker image" runs-on: ubuntu-22.04 diff --git a/capio-posix/utils/env.hpp b/capio-posix/utils/env.hpp index 4c5711979..cba743fa0 100644 --- a/capio-posix/utils/env.hpp +++ b/capio-posix/utils/env.hpp @@ -24,7 +24,6 @@ inline capio_off64_t get_capio_write_cache_size() { return cache_size; } - inline long get_posix_read_cache_line_size() { START_LOG(capio_syscall(SYS_gettid), "call()"); static long data_bufs_count = -1; diff --git a/capio-server/capio_server.cpp b/capio-server/capio_server.cpp index e9faef1dd..539f05ad5 100644 --- a/capio-server/capio_server.cpp +++ b/capio-server/capio_server.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -15,9 +14,7 @@ #include #include #include -#include #include -#include #include "utils/configuration.hpp" @@ -27,10 +24,6 @@ #include "capio/logger.hpp" #include "capio/semaphore.hpp" - - - - #include #include #include @@ -39,9 +32,8 @@ #include #include - #include -#include "utils/signals.hpp" +#include int main(int argc, char **argv) { std::cout << CAPIO_LOG_SERVER_BANNER; diff --git a/capio-server/include/capio-cl-engine/json_parser.hpp b/capio-server/include/capio-cl-engine/json_parser.hpp index 5262056b5..4746683da 100644 --- a/capio-server/include/capio-cl-engine/json_parser.hpp +++ b/capio-server/include/capio-cl-engine/json_parser.hpp @@ -38,7 +38,7 @@ class JsonParser { * @return CapioCLEngine instance with the information provided by the config file */ static CapioCLEngine *parse(const std::filesystem::path &source, - const std::filesystem::path resolve_prexix); + const std::filesystem::path resolve_prexix); }; #endif // JSON_PARSER_HPP diff --git a/capio-server/include/client-manager/handlers.hpp b/capio-server/include/client-manager/handlers.hpp index 5c0f08073..1986ca65f 100644 --- a/capio-server/include/client-manager/handlers.hpp +++ b/capio-server/include/client-manager/handlers.hpp @@ -59,8 +59,8 @@ void handshake_handler(const char *const str); void open_handler(const char *const str); /** -* -*/ + * + */ void posix_readdir_handler(const char *const str); /** @@ -73,7 +73,6 @@ void read_handler(const char *const str); void read_mem_handler(const char *const str); - /** * @brief Handle the rename systemcall * @@ -92,6 +91,4 @@ void write_handler(const char *const str); void write_mem_handler(const char *const str); - - -#endif //HANDLERS_HPP +#endif // HANDLERS_HPP diff --git a/capio-server/include/communication-service/control-plane/capio_control_plane.hpp b/capio-server/include/communication-service/control-plane/capio_control_plane.hpp index 4a74581aa..ed369d71b 100644 --- a/capio-server/include/communication-service/control-plane/capio_control_plane.hpp +++ b/capio-server/include/communication-service/control-plane/capio_control_plane.hpp @@ -3,7 +3,7 @@ #include class CapioControlPlane { -public: + public: typedef enum { CREATE, DELETE, WRITE } event_type; virtual ~CapioControlPlane() = default; @@ -27,4 +27,4 @@ class CapioControlPlane { inline CapioControlPlane *capio_control_plane; -#endif //CAPIO_CONTROL_PLANE_HPP +#endif // CAPIO_CONTROL_PLANE_HPP diff --git a/capio-server/include/communication-service/control-plane/fs_control_plane.hpp b/capio-server/include/communication-service/control-plane/fs_control_plane.hpp index a5a73c784..2a33dd3ae 100644 --- a/capio-server/include/communication-service/control-plane/fs_control_plane.hpp +++ b/capio-server/include/communication-service/control-plane/fs_control_plane.hpp @@ -1,11 +1,11 @@ #ifndef FS_CONTROL_PLANE_HPP #define FS_CONTROL_PLANE_HPP -#include -#include -#include #include #include +#include +#include +#include class FSControlPlane : public CapioControlPlane { char ownHostname[HOST_NAME_MAX] = {0}; @@ -15,7 +15,7 @@ class FSControlPlane : public CapioControlPlane { std::vector token_used_to_connect; std::mutex *token_used_to_connect_mutex; - void generate_aliveness_token(const int port) const ; + void generate_aliveness_token(const int port) const; void delete_aliveness_token(); @@ -27,11 +27,11 @@ class FSControlPlane : public CapioControlPlane { std::mutex *token_used_to_connect_mutex); public: - explicit FSControlPlane(int backend_port) ; + explicit FSControlPlane(int backend_port); - ~FSControlPlane() ; + ~FSControlPlane(); - void notify_all(event_type event, const std::filesystem::path &path) ; + void notify_all(event_type event, const std::filesystem::path &path); }; -#endif //FS_CONTROL_PLANE_HPP +#endif // FS_CONTROL_PLANE_HPP diff --git a/capio-server/include/communication-service/data-plane/backend_interface.hpp b/capio-server/include/communication-service/data-plane/backend_interface.hpp index 375fa93bb..df0e26031 100644 --- a/capio-server/include/communication-service/data-plane/backend_interface.hpp +++ b/capio-server/include/communication-service/data-plane/backend_interface.hpp @@ -2,9 +2,9 @@ #define BACKEND_INTERFACE_HPP #include "capio/constants.hpp" -#include #include #include +#include #include class NotImplementedBackendMethod : public std::exception { @@ -79,4 +79,4 @@ class NoBackend final : public BackendInterface { }; inline BackendInterface *capio_backend; -#endif //BACKEND_INTERFACE_HPP +#endif // BACKEND_INTERFACE_HPP diff --git a/capio-server/include/communication-service/data-plane/transport_unit.hpp b/capio-server/include/communication-service/data-plane/transport_unit.hpp index 4e1e877fc..a0261d378 100644 --- a/capio-server/include/communication-service/data-plane/transport_unit.hpp +++ b/capio-server/include/communication-service/data-plane/transport_unit.hpp @@ -5,13 +5,13 @@ #include class TransportUnit { -protected: + protected: std::string _filepath; char *_bytes{}; capio_off64_t _buffer_size{}; capio_off64_t _start_write_offset{}; -public: + public: TransportUnit() = default; ~TransportUnit() { delete[] _bytes; } @@ -19,5 +19,4 @@ class TransportUnit { friend class MTCLBackend; }; - -#endif //TRANSPORT_UNIT_HPP +#endif // TRANSPORT_UNIT_HPP diff --git a/capio-server/include/file-manager/fs_monitor.hpp b/capio-server/include/file-manager/fs_monitor.hpp index fcdc44542..abc2ba402 100644 --- a/capio-server/include/file-manager/fs_monitor.hpp +++ b/capio-server/include/file-manager/fs_monitor.hpp @@ -1,8 +1,8 @@ #ifndef CAPIO_FS_FILE_SYSTEM_MONITOR_HPP #define CAPIO_FS_FILE_SYSTEM_MONITOR_HPP +#include #include #include -#include /** * @brief Class that monitors the composition of the CAPIO_DIR directory. * @@ -27,7 +27,7 @@ class FileSystemMonitor { */ static void _main(const bool *continue_execution); - explicit FileSystemMonitor() ; + explicit FileSystemMonitor(); ~FileSystemMonitor(); }; diff --git a/capio-server/include/storage-service/capio_file.hpp b/capio-server/include/storage-service/capio_file.hpp index 3432fc918..080fa9efb 100644 --- a/capio-server/include/storage-service/capio_file.hpp +++ b/capio-server/include/storage-service/capio_file.hpp @@ -1,20 +1,19 @@ #ifndef CAPIO_FILE_HPP #define CAPIO_FILE_HPP -#include -#include #include #include +#include #include +#include #include - class CapioFile { -protected: + protected: const std::string fileName; std::size_t totalSize; -public: + public: explicit CapioFile(const std::string &filePath) : fileName(filePath), totalSize(0) {}; virtual ~CapioFile() = default; @@ -63,8 +62,6 @@ class CapioFile { std::size_t length) const = 0; }; - - class CapioMemoryFile : public CapioFile { std::map> memoryBlocks; @@ -87,12 +84,12 @@ class CapioMemoryFile : public CapioFile { * @param id * @return */ - std::vector &get_block(u_int64_t id) ; + std::vector &get_block(u_int64_t id); public: explicit CapioMemoryFile(const std::string &filePath); - ~CapioMemoryFile() ; + ~CapioMemoryFile(); /** * Write data to a file stored inside the memory @@ -101,7 +98,7 @@ class CapioMemoryFile : public CapioFile { * @param buffer_length Size of the buffer. */ std::size_t writeData(const char *buffer, const std::size_t file_offset, - std::size_t buffer_length) override ; + std::size_t buffer_length) override; /** * Read from Capio File @@ -110,7 +107,7 @@ class CapioMemoryFile : public CapioFile { * @param buffer_size Length of buffer * @return number of bytes read from CapioMemoryFile */ - std::size_t readData(char *buffer, std::size_t file_offset, std::size_t buffer_size) ; + std::size_t readData(char *buffer, std::size_t file_offset, std::size_t buffer_size); /** * Store data inside the CapioMemoryFile by reading it from a SPSCQueue object. Behaves just @@ -119,7 +116,7 @@ class CapioMemoryFile : public CapioFile { * @param offset * @param length */ - void readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) override ; + void readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) override; /** * Write the content of the capioFile to a SPSCQueue object @@ -129,15 +126,14 @@ class CapioMemoryFile : public CapioFile { * @return */ std::size_t writeToQueue(SPSCQueue &queue, std::size_t offset, - std::size_t length) const override ; + std::size_t length) const override; }; - class CapioRemoteFile : public CapioFile { -public: + public: explicit CapioRemoteFile(const std::string &filePath); - ~CapioRemoteFile() override ; + ~CapioRemoteFile() override; /** * Write data to a file stored inside the memory @@ -146,7 +142,7 @@ class CapioRemoteFile : public CapioFile { * @param buffer_length Size of the buffer. */ std::size_t writeData(const char *buffer, const std::size_t file_offset, - std::size_t buffer_length) override ; + std::size_t buffer_length) override; /** * Read from Capio File @@ -155,7 +151,7 @@ class CapioRemoteFile : public CapioFile { * @param buffer_size Length of buffer * @return number of bytes read from CapioMemoryFile */ - std::size_t readData(char *buffer, std::size_t file_offset, std::size_t buffer_size) ; + std::size_t readData(char *buffer, std::size_t file_offset, std::size_t buffer_size); /** * Store data inside the CapioMemoryFile by reading it from a SPSCQueue object. Behaves just @@ -164,7 +160,7 @@ class CapioRemoteFile : public CapioFile { * @param offset * @param length */ - void readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) override ; + void readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) override; /** * Write the content of the capioFile to a SPSCQueue object @@ -174,7 +170,7 @@ class CapioRemoteFile : public CapioFile { * @return */ std::size_t writeToQueue(SPSCQueue &queue, std::size_t offset, - std::size_t length) const override ; + std::size_t length) const override; }; -#endif //CAPIO_FILE_HPP +#endif // CAPIO_FILE_HPP diff --git a/capio-server/include/storage-service/capio_storage_service.hpp b/capio-server/include/storage-service/capio_storage_service.hpp index 7da5dd8e5..4dd234b86 100644 --- a/capio-server/include/storage-service/capio_storage_service.hpp +++ b/capio-server/include/storage-service/capio_storage_service.hpp @@ -2,8 +2,8 @@ #define CAPIO_STORAGE_SERVICE_H #include -#include #include +#include class CapioStorageService { // TODO: put all of this conde on a different thread @@ -20,30 +20,30 @@ class CapioStorageService { * @param file_name * @return */ - [[nodiscard]] auto getFile(const std::string &file_name) const ; + [[nodiscard]] auto getFile(const std::string &file_name) const; public: - CapioStorageService() ; + CapioStorageService(); - ~CapioStorageService() ; + ~CapioStorageService(); - void createMemoryFile(const std::string &file_name) const ; + void createMemoryFile(const std::string &file_name) const; /** * Create a CapioRemoteFile, after checking that an instance of CapioMemoryFile (meaning a local * file) is not present * @param file_name file path */ - void createRemoteFile(const std::string &file_name) const ; + void createRemoteFile(const std::string &file_name) const; - void deleteFile(const std::string &file_name) const ; + void deleteFile(const std::string &file_name) const; /** * Notify the occurrence of an operation on a given file, for which other servers running at a * certain point might be required to know. This function is used to allow CAPIO to function in * the event that a distributed file system (or at least a shared directory) is not available */ - void notifyEvent(const std::string &event_name, const std::filesystem::path &filename) const ; + void notifyEvent(const std::string &event_name, const std::filesystem::path &filename) const; /** * Add a new thread in the list of thhreads awaiting for expected_size to be available @@ -53,23 +53,23 @@ class CapioStorageService { * @param size */ void addThreadWaitingForData(pid_t tid, const std::string &path, capio_off64_t offset, - capio_off64_t size) const ; + capio_off64_t size) const; - void check_and_unlock_thread_awaiting_data(const std::string &path) ; + void check_and_unlock_thread_awaiting_data(const std::string &path); /** * Return size of given path as contained inside memory * @param path * @return */ - size_t sizeOf(const std::string &path) const ; + size_t sizeOf(const std::string &path) const; /** * Initialize a new client data structure * @param app_name * @param pid */ - void register_client(const std::string &app_name, const pid_t pid) const ; + void register_client(const std::string &app_name, const pid_t pid) const; /** * Send the file content to a client application @@ -79,7 +79,7 @@ class CapioStorageService { * @param size */ void reply_to_client(pid_t pid, const std::string &file, capio_off64_t offset, - capio_off64_t size) const ; + capio_off64_t size) const; /** * Send raw data to client without fetching from the storage manager itself diff --git a/capio-server/src/capio-cl-engine/capio_cl_engine.cpp b/capio-server/src/capio-cl-engine/capio_cl_engine.cpp index e37557a3f..af0bfd419 100644 --- a/capio-server/src/capio-cl-engine/capio_cl_engine.cpp +++ b/capio-server/src/capio-cl-engine/capio_cl_engine.cpp @@ -1,6 +1,6 @@ -#include #include "utils/configuration.hpp" +#include void CapioCLEngine::print() const { // First message diff --git a/capio-server/src/client-manager/client_manager.cpp b/capio-server/src/client-manager/client_manager.cpp index 79b964e6b..bbfefd10e 100644 --- a/capio-server/src/client-manager/client_manager.cpp +++ b/capio-server/src/client-manager/client_manager.cpp @@ -1,81 +1,74 @@ #include - ClientManager::ClientManager() { - START_LOG(gettid(), "call()"); - bufs_response = new std::unordered_map(); - app_names = new std::unordered_map; - files_created_by_producer = new std::unordered_map *>; - server_println(CAPIO_SERVER_CLI_LOG_SERVER, "ClientManager initialization completed."); +ClientManager::ClientManager() { + START_LOG(gettid(), "call()"); + bufs_response = new std::unordered_map(); + app_names = new std::unordered_map; + files_created_by_producer = new std::unordered_map *>; + server_println(CAPIO_SERVER_CLI_LOG_SERVER, "ClientManager initialization completed."); +} + +ClientManager::~ClientManager() { + START_LOG(gettid(), "call()"); + delete bufs_response; + delete app_names; + delete files_created_by_producer; + server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, "ClientManager cleanup completed."); +} + +void ClientManager::register_client(const std::string &app_name, pid_t tid) const { + START_LOG(gettid(), "call(tid=%ld, app_name=%s)", tid, app_name.c_str()); + // TODO: replace numbers with constexpr + auto *p_buf_response = new ResponseQueue(SHM_COMM_CHAN_NAME_RESP + std::to_string(tid), false); + + bufs_response->insert(std::make_pair(tid, p_buf_response)); + app_names->emplace(tid, app_name); + files_created_by_producer->emplace(tid, new std::vector); +} + +void ClientManager::remove_client(pid_t tid) const { + START_LOG(gettid(), "call(tid=%ld)", tid); + if (const auto it_resp = bufs_response->find(tid); it_resp != bufs_response->end()) { + delete it_resp->second; + bufs_response->erase(it_resp); } - - ClientManager::~ClientManager() { - START_LOG(gettid(), "call()"); - delete bufs_response; - delete app_names; - delete files_created_by_producer; - server_println(CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, "ClientManager cleanup completed."); - } - - - void ClientManager::register_client(const std::string &app_name, pid_t tid) const { - START_LOG(gettid(), "call(tid=%ld, app_name=%s)", tid, app_name.c_str()); - // TODO: replace numbers with constexpr - auto *p_buf_response = - new ResponseQueue(SHM_COMM_CHAN_NAME_RESP + std::to_string(tid), false); - - bufs_response->insert(std::make_pair(tid, p_buf_response)); - app_names->emplace(tid, app_name); - files_created_by_producer->emplace(tid, new std::vector); - } - - - void ClientManager::remove_client(pid_t tid) const { - START_LOG(gettid(), "call(tid=%ld)", tid); - if (const auto it_resp = bufs_response->find(tid); it_resp != bufs_response->end()) { - delete it_resp->second; - bufs_response->erase(it_resp); - } - files_created_by_producer->erase(tid); + files_created_by_producer->erase(tid); +} + +void ClientManager::reply_to_client(const pid_t tid, const capio_off64_t offset) const { + START_LOG(gettid(), "call(tid=%ld, offset=%llu)", tid, offset); + if (const auto out = bufs_response->find(tid); out != bufs_response->end()) { + out->second->write(offset); + return; } - - - void ClientManager::reply_to_client(const pid_t tid, const capio_off64_t offset) const { - START_LOG(gettid(), "call(tid=%ld, offset=%llu)", tid, offset); - if (const auto out = bufs_response->find(tid); out != bufs_response->end()) { - out->second->write(offset); - return; - } - LOG("Err: no such buffer for provided tid"); - } - - - void ClientManager::register_produced_file(pid_t tid, std::string &path) const { - START_LOG(gettid(), "call(tid=%ld, path=%s)", tid, path.c_str()); - if (const auto itm = files_created_by_producer->find(tid); - itm != files_created_by_producer->end()) { - itm->second->emplace_back(path); - return; - } - LOG("Error: tis is not present in files_created_by_producers map"); + LOG("Err: no such buffer for provided tid"); +} + +void ClientManager::register_produced_file(pid_t tid, std::string &path) const { + START_LOG(gettid(), "call(tid=%ld, path=%s)", tid, path.c_str()); + if (const auto itm = files_created_by_producer->find(tid); + itm != files_created_by_producer->end()) { + itm->second->emplace_back(path); + return; } - - - std::vector * ClientManager::get_produced_files(pid_t tid) const { - START_LOG(gettid(), "call(tid=%ld)", tid); - if (const auto itm = files_created_by_producer->find(tid); - itm == files_created_by_producer->end()) { - files_created_by_producer->emplace(tid, new std::vector()); - } - return files_created_by_producer->at(tid); + LOG("Error: tis is not present in files_created_by_producers map"); +} + +std::vector *ClientManager::get_produced_files(pid_t tid) const { + START_LOG(gettid(), "call(tid=%ld)", tid); + if (const auto itm = files_created_by_producer->find(tid); + itm == files_created_by_producer->end()) { + files_created_by_producer->emplace(tid, new std::vector()); } + return files_created_by_producer->at(tid); +} - - std::string ClientManager::get_app_name(pid_t tid) const { - START_LOG(gettid(), "call(tid=%ld)", tid); - if (const auto itm = app_names->find(tid); itm != app_names->end()) { - return itm->second; - } - return CAPIO_DEFAULT_APP_NAME; +std::string ClientManager::get_app_name(pid_t tid) const { + START_LOG(gettid(), "call(tid=%ld)", tid); + if (const auto itm = app_names->find(tid); itm != app_names->end()) { + return itm->second; } + return CAPIO_DEFAULT_APP_NAME; +} - size_t ClientManager::get_connected_posix_client() { return bufs_response->size(); } \ No newline at end of file +size_t ClientManager::get_connected_posix_client() { return bufs_response->size(); } \ No newline at end of file diff --git a/capio-server/src/client-manager/handlers/close.cpp b/capio-server/src/client-manager/handlers/close.cpp index 154c2fb77..bb6851379 100644 --- a/capio-server/src/client-manager/handlers/close.cpp +++ b/capio-server/src/client-manager/handlers/close.cpp @@ -1,10 +1,9 @@ -#include -#include #include +#include +#include #include #include - void close_handler(const char *const str) { pid_t tid; char path[PATH_MAX]; diff --git a/capio-server/src/client-manager/handlers/consent.cpp b/capio-server/src/client-manager/handlers/consent.cpp index 37f6f8184..662d66cff 100644 --- a/capio-server/src/client-manager/handlers/consent.cpp +++ b/capio-server/src/client-manager/handlers/consent.cpp @@ -1,10 +1,9 @@ -#include -#include #include +#include +#include #include #include - void consent_to_proceed_handler(const char *const str) { pid_t tid; char path[1024], source_func[1024]; diff --git a/capio-server/src/client-manager/handlers/open.cpp b/capio-server/src/client-manager/handlers/open.cpp index a66d79425..c8993eba2 100644 --- a/capio-server/src/client-manager/handlers/open.cpp +++ b/capio-server/src/client-manager/handlers/open.cpp @@ -1,9 +1,9 @@ -#include -#include #include +#include +#include #include -#include #include +#include void open_handler(const char *const str) { pid_t tid; diff --git a/capio-server/src/file-manager/file_manager.cpp b/capio-server/src/file-manager/file_manager.cpp index 2082d0f72..56d0eacee 100644 --- a/capio-server/src/file-manager/file_manager.cpp +++ b/capio-server/src/file-manager/file_manager.cpp @@ -3,14 +3,13 @@ #include "include/file-manager/file_manager.hpp" #include "capio/env.hpp" - #include "utils/distributed_semaphore.hpp" #include -#include #include +#include - std::string CapioFileManager::getMetadataPath(const std::string &path) { +std::string CapioFileManager::getMetadataPath(const std::string &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); const std::filesystem::path &metadata_path = get_capio_metadata_path(); @@ -38,7 +37,7 @@ return token_full_path; } - std::string CapioFileManager::getAndCreateMetadataPath(const std::string &path) { +std::string CapioFileManager::getAndCreateMetadataPath(const std::string &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); static std::unordered_map metadata_paths; if (metadata_paths.find(path) == metadata_paths.end()) { @@ -54,18 +53,18 @@ return metadata_paths[path]; } - uintmax_t CapioFileManager::get_file_size_if_exists(const std::filesystem::path &path) { +uintmax_t CapioFileManager::get_file_size_if_exists(const std::filesystem::path &path) { return std::filesystem::exists(path) ? std::filesystem::file_size(path) : 0; } - void CapioFileManager::addThreadAwaitingCreation(const std::string &path, pid_t tid) { +void CapioFileManager::addThreadAwaitingCreation(const std::string &path, pid_t tid) { START_LOG(gettid(), "call(path=%s, tid=%ld)", path.c_str(), tid); const std::lock_guard lg(creation_mutex); thread_awaiting_file_creation[path].push_back(tid); } - void CapioFileManager::_unlockThreadAwaitingCreation(const std::string &path, - const std::vector &pids) { +void CapioFileManager::_unlockThreadAwaitingCreation(const std::string &path, + const std::vector &pids) { START_LOG(gettid(), "call(path=%s)", path.c_str()); for (const auto tid : pids) { client_manager->reply_to_client(tid, 1); @@ -77,8 +76,8 @@ } } - void CapioFileManager::addThreadAwaitingData(const std::string &path, int tid, - size_t expected_size) { +void CapioFileManager::addThreadAwaitingData(const std::string &path, int tid, + size_t expected_size) { START_LOG(gettid(), "call(path=%s, tid=%ld, expected_size=%ld)", path.c_str(), tid, expected_size); @@ -93,7 +92,7 @@ thread_awaiting_data[path].emplace(tid, expected_size); } - void CapioFileManager::_unlockThreadAwaitingData( +void CapioFileManager::_unlockThreadAwaitingData( const std::string &path, std::unordered_map &pids_awaiting) { START_LOG(gettid(), "call(path=%s)", path.c_str()); @@ -150,7 +149,7 @@ LOG("Completed loops over threads vector for file!"); } - void CapioFileManager::increaseCloseCount(const std::filesystem::path &path) { +void CapioFileManager::increaseCloseCount(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); auto metadata_path = getAndCreateMetadataPath(path); auto lock = new DistributedSemaphore(metadata_path + ".lock", 300); @@ -173,7 +172,7 @@ delete lock; } - void CapioFileManager::setCommitted(const std::filesystem::path &path) { +void CapioFileManager::setCommitted(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); auto metadata_path = getAndCreateMetadataPath(path); LOG("Creating token %s", metadata_path.c_str()); @@ -182,7 +181,7 @@ close(fd); } - void CapioFileManager::setCommitted(const pid_t tid) { +void CapioFileManager::setCommitted(const pid_t tid) { START_LOG(gettid(), "call(tid=%d)", tid); auto files = client_manager->get_produced_files(tid); for (const auto &file : *files) { @@ -191,7 +190,7 @@ } } - bool CapioFileManager::isCommitted(const std::filesystem::path &path) { +bool CapioFileManager::isCommitted(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); /** * Hash map to store committed files to avoid recomputing the commit state of a given file @@ -299,7 +298,7 @@ return false; } - void CapioFileManager::checkFilesAwaitingCreation() { +void CapioFileManager::checkFilesAwaitingCreation() { // NOTE: do not put inside here log code as it will generate a lot of useless log const std::lock_guard lg(creation_mutex); std::vector path_to_delete; @@ -319,7 +318,7 @@ } } - void CapioFileManager::checkFileAwaitingData() { +void CapioFileManager::checkFileAwaitingData() { // NOTE: do not put inside here log code as it will generate a lot of useless log const std::lock_guard lg(data_mutex); for (auto iter = thread_awaiting_data.begin(); iter != thread_awaiting_data.end();) { @@ -342,7 +341,7 @@ } } - void CapioFileManager::checkDirectoriesNFiles() const { +void CapioFileManager::checkDirectoriesNFiles() const { /* * WARN: this function directly access the _location internal structure in read only mode to * avoid race conditions. Since we do not update locations, get the pointer only at the diff --git a/capio-server/src/file-manager/fs_monitor.cpp b/capio-server/src/file-manager/fs_monitor.cpp index c90e11935..1bfa5379e 100644 --- a/capio-server/src/file-manager/fs_monitor.cpp +++ b/capio-server/src/file-manager/fs_monitor.cpp @@ -1,18 +1,17 @@ -#include #include -#include #include - +#include +#include FileSystemMonitor::FileSystemMonitor() { START_LOG(gettid(), "call()"); *continue_execution = true; th = new std::thread(_main, std::ref(continue_execution)); - server_println(CAPIO_SERVER_CLI_LOG_SERVER, - "CapioFileSystemMonitor initialization completed."); + server_println(CAPIO_SERVER_CLI_LOG_SERVER, "CapioFileSystemMonitor initialization completed."); } -void FileSystemMonitor::print_message_error(const std::string &func, const std::exception &exception) { +void FileSystemMonitor::print_message_error(const std::string &func, + const std::exception &exception) { START_LOG(gettid(), "call()"); std::cout << std::endl << "~~~~~~~~~~~~~~[\033[31mFileSystemMonitor: FATAL " @@ -73,4 +72,3 @@ FileSystemMonitor::~FileSystemMonitor() { delete continue_execution; server_println(CAPIO_SERVER_CLI_LOG_SERVER, "CapioFileSystemMonitor cleanup completed."); } - diff --git a/capio-server/src/storage-service/capio_memory_file.cpp b/capio-server/src/storage-service/capio_memory_file.cpp index edcc9b584..b6ec0fea1 100644 --- a/capio-server/src/storage-service/capio_memory_file.cpp +++ b/capio-server/src/storage-service/capio_memory_file.cpp @@ -2,161 +2,154 @@ #include "include/storage-service/capio_file.hpp" #include +auto CapioMemoryFile::compute_offsets(const std::size_t offset, std::size_t length) { + START_LOG(gettid(), "call(offset=%llu, length=%llu)", offset, length); + // Compute the offset of the memoryBlocks component. + const auto map_offset = offset / _pageSizeBytes; + + // Compute the first write offset relative to the first block of memory + const auto mem_block_offset = offset % _pageSizeBytes; + + // compute the first write size. if the write operation is bigger than the size of the page + // in bytes, then we need to perform the first write operation with size equals to the + // distance between the write offset and the end of the page. otherwise it is possible to + // use the given length. The returned offset starts from mem_block_offset + const auto first_write_size = + length > _pageSizeBytes - mem_block_offset ? _pageSizeBytes - mem_block_offset : length; + + LOG("Computed offsets. map_offset=%llu, mem_block_offset=%llu, first_write_size=%llu", + map_offset, mem_block_offset, first_write_size); + return std::tuple(map_offset, mem_block_offset, first_write_size); +} + +std::vector &CapioMemoryFile::get_block(u_int64_t id) { + std::vector &block = memoryBlocks[id]; + block.resize(_pageSizeBytes); // reserve 4MB of space + return block; +} + +CapioMemoryFile::CapioMemoryFile(const std::string &filePath) : CapioFile(filePath) { + cross_page_buffer_view = new char[_pageSizeBytes]; +} + +CapioMemoryFile::~CapioMemoryFile() { delete[] cross_page_buffer_view; } + +std::size_t CapioMemoryFile::writeData(const char *buffer, const std::size_t file_offset, + std::size_t buffer_length) { + const auto &[map_offset, write_offset, first_write_size] = + compute_offsets(file_offset, buffer_length); + + // Execute first write which could be a smaller size + auto &block = memoryBlocks[map_offset]; + block.resize(_pageSizeBytes); // reserve 4MB of space + + std::copy(buffer, buffer + first_write_size, block.begin() + write_offset); + + // update remaining bytes to write + buffer_length -= first_write_size; + size_t map_count = 1; // start from map following the one obtained from the first write + + // Variable to store the read offset of the input buffer + auto buffer_offset = first_write_size; + + while (buffer_length > 0) { + auto &block = memoryBlocks[map_offset + map_count]; + block.resize(_pageSizeBytes); // reserve 4MB of space + // Compute the actual size of the current write + const auto write_size = buffer_length > _pageSizeBytes ? _pageSizeBytes : buffer_length; - auto CapioMemoryFile::compute_offsets(const std::size_t offset, std::size_t length) { - START_LOG(gettid(), "call(offset=%llu, length=%llu)", offset, length); - // Compute the offset of the memoryBlocks component. - const auto map_offset = offset / _pageSizeBytes; - - // Compute the first write offset relative to the first block of memory - const auto mem_block_offset = offset % _pageSizeBytes; - - // compute the first write size. if the write operation is bigger than the size of the page - // in bytes, then we need to perform the first write operation with size equals to the - // distance between the write offset and the end of the page. otherwise it is possible to - // use the given length. The returned offset starts from mem_block_offset - const auto first_write_size = - length > _pageSizeBytes - mem_block_offset ? _pageSizeBytes - mem_block_offset : length; + std::copy(buffer + buffer_offset, buffer + buffer_offset + write_size, block.data()); - LOG("Computed offsets. map_offset=%llu, mem_block_offset=%llu, first_write_size=%llu", - map_offset, mem_block_offset, first_write_size); - return std::tuple(map_offset, mem_block_offset, first_write_size); + buffer_offset += write_size; + map_count++; + buffer_length -= _pageSizeBytes; } + totalSize = std::max(totalSize, buffer_offset); + return totalSize; +} - std::vector &CapioMemoryFile::get_block(u_int64_t id) { - std::vector &block = memoryBlocks[id]; - block.resize(_pageSizeBytes); // reserve 4MB of space - return block; - } +std::size_t CapioMemoryFile::readData(char *buffer, std::size_t file_offset, + std::size_t buffer_size) { + std::size_t bytesRead = 0; + const auto &[map_offset, mem_block_offset_begin, target_buffer_size] = + compute_offsets(file_offset, buffer_size); - CapioMemoryFile::CapioMemoryFile(const std::string &filePath) : CapioFile(filePath) { - cross_page_buffer_view = new char[_pageSizeBytes]; - } + // Traverse the memory blocks to read the requested data starting from the first block of + // date + for (auto it = memoryBlocks.lower_bound(map_offset); it != memoryBlocks.end(); ++it) { + auto &[blockOffset, block] = *it; - CapioMemoryFile::~CapioMemoryFile() { delete[] cross_page_buffer_view; } + if (blockOffset * _pageSizeBytes >= file_offset + buffer_size) { + break; // Past the requested range + } - std::size_t CapioMemoryFile::writeData(const char *buffer, const std::size_t file_offset, - std::size_t buffer_length) { - const auto &[map_offset, write_offset, first_write_size] = - compute_offsets(file_offset, buffer_length); + // Copy the data to the buffer + std::size_t copyLength = target_buffer_size - mem_block_offset_begin; + std::copy(block.begin() + mem_block_offset_begin, + block.begin() + mem_block_offset_begin + target_buffer_size, buffer + bytesRead); - // Execute first write which could be a smaller size - auto &block = memoryBlocks[map_offset]; - block.resize(_pageSizeBytes); // reserve 4MB of space + bytesRead += copyLength; + } - std::copy(buffer, buffer + first_write_size, block.begin() + write_offset); + return bytesRead; +} - // update remaining bytes to write - buffer_length -= first_write_size; - size_t map_count = 1; // start from map following the one obtained from the first write +void CapioMemoryFile::readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) { + const auto &[map_offset, write_offset, first_write_size] = compute_offsets(offset, length); - // Variable to store the read offset of the input buffer - auto buffer_offset = first_write_size; + auto remaining_bytes = length; - while (buffer_length > 0) { - auto &block = memoryBlocks[map_offset + map_count]; - block.resize(_pageSizeBytes); // reserve 4MB of space + auto &block = memoryBlocks[map_offset]; + block.resize(_pageSizeBytes); // reserve 4MB of space - // Compute the actual size of the current write - const auto write_size = buffer_length > _pageSizeBytes ? _pageSizeBytes : buffer_length; + queue.read(block.data() + write_offset, first_write_size); + // update remaining bytes to write + remaining_bytes -= first_write_size; + size_t map_count = 1; // start from map following the one obtained from the first write - std::copy(buffer + buffer_offset, buffer + buffer_offset + write_size, block.data()); + // Variable to store the read offset of the input buffer + auto buffer_offset = first_write_size; - buffer_offset += write_size; - map_count++; - buffer_length -= _pageSizeBytes; - } + while (remaining_bytes > 0) { + auto &next_block = memoryBlocks[map_offset + map_count]; + next_block.resize(_pageSizeBytes); // reserve 4MB of space + // Compute the actual size of the current write + const auto write_size = length > _pageSizeBytes ? _pageSizeBytes : length; - totalSize = std::max(totalSize, buffer_offset); - return totalSize; + queue.read(next_block.data(), write_size); + buffer_offset += write_size; + map_count++; + remaining_bytes -= _pageSizeBytes; } + totalSize = std::max(totalSize, offset + length); +} - std::size_t CapioMemoryFile::readData(char *buffer, std::size_t file_offset, std::size_t buffer_size) { - std::size_t bytesRead = 0; +std::size_t CapioMemoryFile::writeToQueue(SPSCQueue &queue, std::size_t offset, + std::size_t length) const { + START_LOG(gettid(), "call(offset=%llu, length=%llu)", offset, length); + std::size_t bytesRead = 0; - const auto &[map_offset, mem_block_offset_begin, target_buffer_size] = - compute_offsets(file_offset, buffer_size); + while (bytesRead < length) { + const auto [map_offset, mem_block_offset_begin, buffer_view_size] = + compute_offsets(offset, length - bytesRead); - // Traverse the memory blocks to read the requested data starting from the first block of - // date - for (auto it = memoryBlocks.lower_bound(map_offset); it != memoryBlocks.end(); ++it) { + if (const auto it = memoryBlocks.lower_bound(map_offset); it != memoryBlocks.end()) { auto &[blockOffset, block] = *it; - if (blockOffset * _pageSizeBytes >= file_offset + buffer_size) { - break; // Past the requested range + if (blockOffset >= offset + length) { + return bytesRead; // Past the requested range } // Copy the data to the buffer - std::size_t copyLength = target_buffer_size - mem_block_offset_begin; - std::copy(block.begin() + mem_block_offset_begin, - block.begin() + mem_block_offset_begin + target_buffer_size, - buffer + bytesRead); - - bytesRead += copyLength; - } - - return bytesRead; - } - - - void CapioMemoryFile::readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) { - const auto &[map_offset, write_offset, first_write_size] = compute_offsets(offset, length); - - auto remaining_bytes = length; + queue.write(block.data() + mem_block_offset_begin, buffer_view_size); - auto &block = memoryBlocks[map_offset]; - block.resize(_pageSizeBytes); // reserve 4MB of space - - queue.read(block.data() + write_offset, first_write_size); - // update remaining bytes to write - remaining_bytes -= first_write_size; - size_t map_count = 1; // start from map following the one obtained from the first write - - // Variable to store the read offset of the input buffer - auto buffer_offset = first_write_size; - - while (remaining_bytes > 0) { - auto &next_block = memoryBlocks[map_offset + map_count]; - next_block.resize(_pageSizeBytes); // reserve 4MB of space - // Compute the actual size of the current write - const auto write_size = length > _pageSizeBytes ? _pageSizeBytes : length; - - queue.read(next_block.data(), write_size); - buffer_offset += write_size; - map_count++; - remaining_bytes -= _pageSizeBytes; - } - - totalSize = std::max(totalSize, offset + length); - } - - - std::size_t CapioMemoryFile::writeToQueue(SPSCQueue &queue, std::size_t offset, - std::size_t length) const { - START_LOG(gettid(), "call(offset=%llu, length=%llu)", offset, length); - std::size_t bytesRead = 0; - - while (bytesRead < length) { - const auto [map_offset, mem_block_offset_begin, buffer_view_size] = - compute_offsets(offset, length - bytesRead); - - if (const auto it = memoryBlocks.lower_bound(map_offset); it != memoryBlocks.end()) { - auto &[blockOffset, block] = *it; - - if (blockOffset >= offset + length) { - return bytesRead; // Past the requested range - } - - // Copy the data to the buffer - queue.write(block.data() + mem_block_offset_begin, buffer_view_size); - - bytesRead += buffer_view_size; - offset += buffer_view_size; - } + bytesRead += buffer_view_size; + offset += buffer_view_size; } - return bytesRead; } + return bytesRead; +} diff --git a/capio-server/src/storage-service/capio_remote_file.cpp b/capio-server/src/storage-service/capio_remote_file.cpp index 9d6968616..c635b039e 100644 --- a/capio-server/src/storage-service/capio_remote_file.cpp +++ b/capio-server/src/storage-service/capio_remote_file.cpp @@ -1,27 +1,23 @@ #include +CapioRemoteFile::CapioRemoteFile(const std::string &filePath) : CapioFile(filePath) {} - CapioRemoteFile::CapioRemoteFile(const std::string &filePath) : CapioFile(filePath) {} +CapioRemoteFile::~CapioRemoteFile() {} - CapioRemoteFile::~CapioRemoteFile() {} +std::size_t CapioRemoteFile::writeData(const char *buffer, const std::size_t file_offset, + std::size_t buffer_length) { + return 0; +} +std::size_t CapioRemoteFile::readData(char *buffer, std::size_t file_offset, + std::size_t buffer_size) { + return 0; +} - std::size_t CapioRemoteFile::writeData(const char *buffer, const std::size_t file_offset, - std::size_t buffer_length) { - return 0; - } +void CapioRemoteFile::readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) {} - - std::size_t CapioRemoteFile::readData(char *buffer, std::size_t file_offset, std::size_t buffer_size) { - return 0; - } - - - void CapioRemoteFile::readFromQueue(SPSCQueue &queue, std::size_t offset, std::size_t length) {} - - - std::size_t CapioRemoteFile::writeToQueue(SPSCQueue &queue, std::size_t offset, - std::size_t length) const { - return 0; - } +std::size_t CapioRemoteFile::writeToQueue(SPSCQueue &queue, std::size_t offset, + std::size_t length) const { + return 0; +} diff --git a/capio-server/src/storage-service/capio_storage_service.cpp b/capio-server/src/storage-service/capio_storage_service.cpp index d8faa7d12..f55ac94b7 100644 --- a/capio-server/src/storage-service/capio_storage_service.cpp +++ b/capio-server/src/storage-service/capio_storage_service.cpp @@ -1,164 +1,152 @@ - - #include #include #include -#include #include +#include - - - - auto CapioStorageService::getFile(const std::string &file_name) const { - if (_stored_files->find(file_name) == _stored_files->end()) { - createMemoryFile(file_name); - } - return _stored_files->at(file_name); - } - - CapioStorageService::CapioStorageService() { - START_LOG(gettid(), "call()"); - _stored_files = new std::unordered_map; - _client_to_server_queue = new std::unordered_map; - _server_to_client_queue = new std::unordered_map; - _threads_waiting_for_memory_data = - new std::unordered_map>>; - server_println(CAPIO_SERVER_CLI_LOG_SERVER, - "CapioStorageService initialization completed."); - } - - CapioStorageService::~CapioStorageService() { - // TODO: dump files to FS - delete _stored_files; - delete _client_to_server_queue; - delete _server_to_client_queue; - delete _threads_waiting_for_memory_data; - server_println(CAPIO_SERVER_CLI_LOG_SERVER, "CapioStorageService cleanup completed."); - } - - void CapioStorageService::createMemoryFile(const std::string &file_name) const { - _stored_files->emplace(file_name, new CapioMemoryFile(file_name)); +auto CapioStorageService::getFile(const std::string &file_name) const { + if (_stored_files->find(file_name) == _stored_files->end()) { + createMemoryFile(file_name); } - - - void CapioStorageService::createRemoteFile(const std::string &file_name) const { - /* - * First we check that the file associate does not yet exists, as it might be produced - * by another app running under the same server instance. if it is not found, we create - * the file - */ - START_LOG(gettid(), "call(file_name=%s)", file_name.c_str()); - if (_stored_files->find(file_name) == _stored_files->end()) { - LOG("File not found. Creating a new remote file"); - _stored_files->emplace(file_name, new CapioRemoteFile(file_name)); - } + return _stored_files->at(file_name); +} + +CapioStorageService::CapioStorageService() { + START_LOG(gettid(), "call()"); + _stored_files = new std::unordered_map; + _client_to_server_queue = new std::unordered_map; + _server_to_client_queue = new std::unordered_map; + _threads_waiting_for_memory_data = + new std::unordered_map>>; + server_println(CAPIO_SERVER_CLI_LOG_SERVER, "CapioStorageService initialization completed."); +} + +CapioStorageService::~CapioStorageService() { + // TODO: dump files to FS + delete _stored_files; + delete _client_to_server_queue; + delete _server_to_client_queue; + delete _threads_waiting_for_memory_data; + server_println(CAPIO_SERVER_CLI_LOG_SERVER, "CapioStorageService cleanup completed."); +} + +void CapioStorageService::createMemoryFile(const std::string &file_name) const { + _stored_files->emplace(file_name, new CapioMemoryFile(file_name)); +} + +void CapioStorageService::createRemoteFile(const std::string &file_name) const { + /* + * First we check that the file associate does not yet exists, as it might be produced + * by another app running under the same server instance. if it is not found, we create + * the file + */ + START_LOG(gettid(), "call(file_name=%s)", file_name.c_str()); + if (_stored_files->find(file_name) == _stored_files->end()) { + LOG("File not found. Creating a new remote file"); + _stored_files->emplace(file_name, new CapioRemoteFile(file_name)); } - - void CapioStorageService::deleteFile(const std::string &file_name) const { _stored_files->erase(file_name); } - - - void CapioStorageService::notifyEvent(const std::string &event_name, const std::filesystem::path &filename) const { - // TODO: implement this +} + +void CapioStorageService::deleteFile(const std::string &file_name) const { + _stored_files->erase(file_name); +} + +void CapioStorageService::notifyEvent(const std::string &event_name, + const std::filesystem::path &filename) const { + // TODO: implement this +} + +void CapioStorageService::addThreadWaitingForData(pid_t tid, const std::string &path, + capio_off64_t offset, capio_off64_t size) const { + START_LOG(gettid(), "call(tid=%d, path=%s, offset=%lld, size=%lld)", tid, path.c_str(), offset, + size); + if (_threads_waiting_for_memory_data->find(path) == _threads_waiting_for_memory_data->end()) { + _threads_waiting_for_memory_data->insert({path, {}}); } + _threads_waiting_for_memory_data->at(path).emplace_back(std::make_tuple(offset, size, tid)); +} - void CapioStorageService::addThreadWaitingForData(pid_t tid, const std::string &path, capio_off64_t offset, - capio_off64_t size) const { - START_LOG(gettid(), "call(tid=%d, path=%s, offset=%lld, size=%lld)", tid, path.c_str(), - offset, size); - if (_threads_waiting_for_memory_data->find(path) == - _threads_waiting_for_memory_data->end()) { - _threads_waiting_for_memory_data->insert({path, {}}); - } - - _threads_waiting_for_memory_data->at(path).emplace_back(std::make_tuple(offset, size, tid)); - } - - void CapioStorageService::check_and_unlock_thread_awaiting_data(const std::string &path) { - auto threads = _threads_waiting_for_memory_data->at(path); +void CapioStorageService::check_and_unlock_thread_awaiting_data(const std::string &path) { + auto threads = _threads_waiting_for_memory_data->at(path); - auto file_size = sizeOf(path); + auto file_size = sizeOf(path); - for (auto &[offset, size, thread_id] : threads) { - if (file_size >= offset + size) { - reply_to_client(thread_id, path, offset, size); - } + for (auto &[offset, size, thread_id] : threads) { + if (file_size >= offset + size) { + reply_to_client(thread_id, path, offset, size); } } - - - size_t CapioStorageService::sizeOf(const std::string &path) const { - START_LOG(gettid(), "call(file=%s)", path.c_str()); - return getFile(path)->getSize(); - } - - - void CapioStorageService::register_client(const std::string &app_name, const pid_t pid) const { - START_LOG(gettid(), "call(app_name=%s)", app_name.c_str()); - _client_to_server_queue->emplace( - pid, - new SPSCQueue("queue-" + std::to_string(pid) + +".cts", get_cache_lines(), - get_cache_line_size(), capio_global_configuration->workflow_name, false)); - _server_to_client_queue->emplace( - pid, - new SPSCQueue("queue-" + std::to_string(pid) + +".stc", get_cache_lines(), - get_cache_line_size(), capio_global_configuration->workflow_name, false)); - LOG("Created communication queues"); - } - - - void CapioStorageService::reply_to_client(pid_t pid, const std::string &file, capio_off64_t offset, - capio_off64_t size) const { - START_LOG(gettid(), "call(pid=%llu, file=%s, offset=%llu, size=%llu)", pid, file.c_str(), - offset, size); - - getFile(file)->writeToQueue(*_server_to_client_queue->at(pid), offset, size); +} + +size_t CapioStorageService::sizeOf(const std::string &path) const { + START_LOG(gettid(), "call(file=%s)", path.c_str()); + return getFile(path)->getSize(); +} + +void CapioStorageService::register_client(const std::string &app_name, const pid_t pid) const { + START_LOG(gettid(), "call(app_name=%s)", app_name.c_str()); + _client_to_server_queue->emplace(pid, new SPSCQueue("queue-" + std::to_string(pid) + +".cts", + get_cache_lines(), get_cache_line_size(), + capio_global_configuration->workflow_name, + false)); + _server_to_client_queue->emplace(pid, new SPSCQueue("queue-" + std::to_string(pid) + +".stc", + get_cache_lines(), get_cache_line_size(), + capio_global_configuration->workflow_name, + false)); + LOG("Created communication queues"); +} + +void CapioStorageService::reply_to_client(pid_t pid, const std::string &file, capio_off64_t offset, + capio_off64_t size) const { + START_LOG(gettid(), "call(pid=%llu, file=%s, offset=%llu, size=%llu)", pid, file.c_str(), + offset, size); + + getFile(file)->writeToQueue(*_server_to_client_queue->at(pid), offset, size); +} + +void CapioStorageService::reply_to_client_raw(pid_t pid, const char *data, + const capio_off64_t len) const { + _server_to_client_queue->at(pid)->write(data, len); +} + +void CapioStorageService::recive_from_client(pid_t tid, const std::string &file, + capio_off64_t offset, off64_t size) const { + START_LOG(gettid(), "call(tid=%d, file=%s, offset=%lld, size=%lld)", tid, file.c_str(), offset, + size); + const auto f = getFile(file); + const auto queue = _client_to_server_queue->at(tid); + f->readFromQueue(*queue, offset, size); +} + +void CapioStorageService::remove_client(const pid_t pid) const { + _client_to_server_queue->erase(pid); + _server_to_client_queue->erase(pid); +} + +size_t CapioStorageService::sendFilesToStoreInMemory(const long pid) const { + START_LOG(gettid(), "call(pid=%d)", pid); + + if (capio_global_configuration->StoreOnlyInMemory) { + LOG("All files should be handled in memory. sending * wildcard"); + char f[PATH_MAX + 1]{0}; + f[0] = '*'; + _server_to_client_queue->at(pid)->write(f, PATH_MAX); + LOG("Return value=%llu", 1); + return 1; } - - void CapioStorageService::reply_to_client_raw(pid_t pid, const char *data, const capio_off64_t len) const { - _server_to_client_queue->at(pid)->write(data, len); + auto files_to_store_in_mem = capio_cl_engine->getFileToStoreInMemory(); + for (const auto &file : files_to_store_in_mem) { + LOG("Sending file %s", file.c_str()); + char f[PATH_MAX + 1]{0}; + memcpy(f, file.c_str(), file.size()); + _server_to_client_queue->at(pid)->write(f, PATH_MAX); } - - void CapioStorageService::recive_from_client(pid_t tid, const std::string &file, capio_off64_t offset, - off64_t size) const { - START_LOG(gettid(), "call(tid=%d, file=%s, offset=%lld, size=%lld)", tid, file.c_str(), - offset, size); - const auto f = getFile(file); - const auto queue = _client_to_server_queue->at(tid); - f->readFromQueue(*queue, offset, size); - } - - void CapioStorageService::remove_client(const pid_t pid) const { - _client_to_server_queue->erase(pid); - _server_to_client_queue->erase(pid); - } - - - size_t CapioStorageService::sendFilesToStoreInMemory(const long pid) const { - START_LOG(gettid(), "call(pid=%d)", pid); - - if (capio_global_configuration->StoreOnlyInMemory) { - LOG("All files should be handled in memory. sending * wildcard"); - char f[PATH_MAX + 1]{0}; - f[0] = '*'; - _server_to_client_queue->at(pid)->write(f, PATH_MAX); - LOG("Return value=%llu", 1); - return 1; - } - - auto files_to_store_in_mem = capio_cl_engine->getFileToStoreInMemory(); - for (const auto &file : files_to_store_in_mem) { - LOG("Sending file %s", file.c_str()); - char f[PATH_MAX + 1]{0}; - memcpy(f, file.c_str(), file.size()); - _server_to_client_queue->at(pid)->write(f, PATH_MAX); - } - - LOG("Return value=%llu", files_to_store_in_mem.size()); - return files_to_store_in_mem.size(); - } + LOG("Return value=%llu", files_to_store_in_mem.size()); + return files_to_store_in_mem.size(); +} diff --git a/capio-server/utils/configuration.hpp b/capio-server/utils/configuration.hpp index 1416b2d0c..249962846 100644 --- a/capio-server/utils/configuration.hpp +++ b/capio-server/utils/configuration.hpp @@ -3,10 +3,10 @@ #include "capio/constants.hpp" +#include #include #include #include -#include /* * Variables required to be globally available diff --git a/capio-server/utils/signals.hpp b/capio-server/utils/signals.hpp index 16d5cf75b..892e0cfdb 100644 --- a/capio-server/utils/signals.hpp +++ b/capio-server/utils/signals.hpp @@ -1,8 +1,8 @@ #ifndef CAPIO_SERVER_HANDLERS_SIGNALS_HPP #define CAPIO_SERVER_HANDLERS_SIGNALS_HPP -#include #include +#include #include From 22e579eb9d16209c53f07b02c1ade4c5574bbc2c Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Sat, 30 Aug 2025 07:55:44 +0000 Subject: [PATCH 08/10] cmake-fixes --- capio-server/capio_server.cpp | 7 +------ capio-tests/unit/MemoryFiles/CMakeLists.txt | 4 ++-- capio-tests/unit/posix/CMakeLists.txt | 5 +++-- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/capio-server/capio_server.cpp b/capio-server/capio_server.cpp index 539f05ad5..29a80189a 100644 --- a/capio-server/capio_server.cpp +++ b/capio-server/capio_server.cpp @@ -12,14 +12,9 @@ #include #include #include -#include #include #include -#include "utils/configuration.hpp" - -#include "utils/types.hpp" - #include "capio/env.hpp" #include "capio/logger.hpp" #include "capio/semaphore.hpp" @@ -31,7 +26,7 @@ #include #include #include - +#include #include #include diff --git a/capio-tests/unit/MemoryFiles/CMakeLists.txt b/capio-tests/unit/MemoryFiles/CMakeLists.txt index 7d436e931..e2802bd7e 100644 --- a/capio-tests/unit/MemoryFiles/CMakeLists.txt +++ b/capio-tests/unit/MemoryFiles/CMakeLists.txt @@ -7,7 +7,7 @@ file(GLOB_RECURSE CAPIO_SERVER_SOURCES ${CMAKE_SOURCE_DIR}/capio-server/ "*.cpp" set(TARGET_INCLUDE_FOLDER "${CMAKE_SOURCE_DIR}/capio-server/" - "${CMAKE_SOURCE_DIR}../../../capio-posix") + "${CMAKE_SOURCE_DIR}/capio-posix") set(TARGET_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp @@ -22,7 +22,7 @@ add_executable(${TARGET_NAME} ${TARGET_SOURCES}) ##################################### # External projects ##################################### -set(SYSCALL_INTERCEPT_BINARY_DIR "${PROJECT_BINARY_DIR}/src/posix/syscall_intercept") +set(SYSCALL_INTERCEPT_BINARY_DIR "${PROJECT_BINARY_DIR}/capio-posix/syscall_intercept") set(SYSCALL_INTERCEPT_INCLUDE_FOLDER "${SYSCALL_INTERCEPT_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}") set(SYSCALL_INTERCEPT_LIB_FOLDER diff --git a/capio-tests/unit/posix/CMakeLists.txt b/capio-tests/unit/posix/CMakeLists.txt index 491d4e41f..57db916bd 100644 --- a/capio-tests/unit/posix/CMakeLists.txt +++ b/capio-tests/unit/posix/CMakeLists.txt @@ -2,7 +2,8 @@ # Target information ##################################### set(TARGET_NAME capio_posix_unit_tests) -set(TARGET_INCLUDE_FOLDER "../../../capio-posix") +set(TARGET_INCLUDE_FOLDER "${CMAKE_SOURCE_DIR}/capio-posix") +list(FILTER TARGET_INCLUDE_FOLDER EXCLUDE REGEX ".*/libcapio_posix\\.cpp$") set(TARGET_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/realpath.cpp ) @@ -15,7 +16,7 @@ add_executable(${TARGET_NAME} ${TARGET_SOURCES}) ##################################### # External projects ##################################### -set(SYSCALL_INTERCEPT_BINARY_DIR "${PROJECT_BINARY_DIR}/src/posix/syscall_intercept") +set(SYSCALL_INTERCEPT_BINARY_DIR "${PROJECT_BINARY_DIR}/capio-posix/syscall_intercept") set(SYSCALL_INTERCEPT_INCLUDE_FOLDER "${SYSCALL_INTERCEPT_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}") set(SYSCALL_INTERCEPT_LIB_FOLDER From 8c2617d03b81b7f882c2de3e7f05da253d2ca5dc Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Sat, 30 Aug 2025 08:23:53 +0000 Subject: [PATCH 09/10] refactor --- .github/workflows/ci-tests.yaml | 20 +++++++++---------- CMakeLists.txt | 4 ++-- Dockerfile | 4 ++-- README.md | 2 +- {capiorun => capio-run}/.gitignore | 0 {capiorun => capio-run}/capiorun | 0 {capiorun => capio-run}/readme.md | 0 capio-run/requirements.txt | 0 .../control-plane/fs_control_plane.hpp | 3 +-- .../control-plane/multicast_control_plane.hpp | 4 ++-- capiorun/requirements.txt | 1 - {benchmarks => scripts/benchmarks}/lmbench.sh | 0 12 files changed, 18 insertions(+), 20 deletions(-) rename {capiorun => capio-run}/.gitignore (100%) rename {capiorun => capio-run}/capiorun (100%) rename {capiorun => capio-run}/readme.md (100%) create mode 100644 capio-run/requirements.txt delete mode 100644 capiorun/requirements.txt rename {benchmarks => scripts/benchmarks}/lmbench.sh (100%) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index ec9aa73e6..ada146961 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -57,11 +57,11 @@ jobs: - name: "Run backend communication tests" working-directory: ${{ github.workspace }} - run: docker compose -f tests/multinode/backend/docker-compose.yml up --abort-on-container-exit + run: docker compose -f capio-tests/multinode/backend/docker-compose.yml up --abort-on-container-exit - name: "Run integration tests" working-directory: ${{ github.workspace }} - run: docker compose -f tests/multinode/integration/docker-compose.yml up --abort-on-container-exit + run: docker compose -f capio-tests/multinode/integration/docker-compose.yml up --abort-on-container-exit format-check: @@ -157,7 +157,7 @@ jobs: CAPIO_LOG_LEVEL: -1 run: | export LD_LIBRARY_PATH="/usr/local/lib:${LD_LIBRARY_PATH}" - + echo "Run CAPIO syscall Unit tests" capio_server --no-config & CAPIO_SERVER_PID=$! @@ -165,8 +165,8 @@ jobs: --gtest_break_on_failure --gtest_print_time=1 kill $CAPIO_SERVER_PID sleep 2 - - + + echo "Run CAPIO memory file integration tests" capio_server --no-config & CAPIO_SERVER_PID=$! @@ -174,16 +174,16 @@ jobs: --gtest_break_on_failure --gtest_print_time=1 kill $CAPIO_SERVER_PID sleep 2 - - - + + + echo "Run CAPIO POSIX Unit tests" capio_posix_unit_tests \ --gtest_break_on_failure \ --gtest_print_time=1 sleep 2 - - + + echo "Run CAPIO SERVER unit tests" capio_server_unit_tests \ --gtest_break_on_failure \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 635470d1b..163667559 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,10 +92,10 @@ add_subdirectory(capio-posix) add_subdirectory(capio-server) ##################################### -# Install capiorun +# Install capio-run ##################################### install( - FILES ${PROJECT_SOURCE_DIR}/capiorun/capiorun + FILES ${PROJECT_SOURCE_DIR}/capio-run/capiorun DESTINATION ${CMAKE_INSTALL_BINDIR} PERMISSIONS OWNER_READ diff --git a/Dockerfile b/Dockerfile index de3a4da2e..b36d637d5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,7 +22,7 @@ COPY capio-common /opt/capio/capio-common COPY capio-posix /opt/capio/capio-posix COPY capio-server /opt/capio/capio-server COPY capio-tests /opt/capio/capio-tests -COPY capiorun /opt/capio/capiorun +COPY capio-run /opt/capio/capio-run RUN mkdir -p /opt/capio/build \ && cmake \ @@ -100,7 +100,7 @@ COPY --from=builder \ "/usr/local/bin/capio_integration_test_map*" \ "/usr/local/bin/capio_integration_test_merge*" \ "/usr/local/bin/capio_integration_test_split*" \ - "/opt/capio/capiorun/capiorun" \ + "/opt/capio/capio-run/capiorun" \ /usr/local/bin/ # Pkgconfig diff --git a/README.md b/README.md index 746481162..333cde7c0 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ To launch your workflow with capio you can follow two routes: #### A) Use `capiorun` for simplified operations You can simplify the execution of workflow steps with CAPIO using the `capiorun` utility. See the -[`capiorun` documentation](capiorun/readme.md) for usage and examples. `capiorun` provides an easier way to manage +[`capiorun` documentation](capio-run/readme.md) for usage and examples. `capiorun` provides an easier way to manage daemon startup and environment preparation, so that the user do not need to manually prepare the environment. #### B) Manually launch CAPIO diff --git a/capiorun/.gitignore b/capio-run/.gitignore similarity index 100% rename from capiorun/.gitignore rename to capio-run/.gitignore diff --git a/capiorun/capiorun b/capio-run/capiorun similarity index 100% rename from capiorun/capiorun rename to capio-run/capiorun diff --git a/capiorun/readme.md b/capio-run/readme.md similarity index 100% rename from capiorun/readme.md rename to capio-run/readme.md diff --git a/capio-run/requirements.txt b/capio-run/requirements.txt new file mode 100644 index 000000000..e69de29bb diff --git a/capio-server/include/communication-service/control-plane/fs_control_plane.hpp b/capio-server/include/communication-service/control-plane/fs_control_plane.hpp index 2a33dd3ae..651eb65d8 100644 --- a/capio-server/include/communication-service/control-plane/fs_control_plane.hpp +++ b/capio-server/include/communication-service/control-plane/fs_control_plane.hpp @@ -1,7 +1,6 @@ #ifndef FS_CONTROL_PLANE_HPP #define FS_CONTROL_PLANE_HPP -#include #include #include #include @@ -15,7 +14,7 @@ class FSControlPlane : public CapioControlPlane { std::vector token_used_to_connect; std::mutex *token_used_to_connect_mutex; - void generate_aliveness_token(const int port) const; + void generate_aliveness_token(int port) const; void delete_aliveness_token(); diff --git a/capio-server/include/communication-service/control-plane/multicast_control_plane.hpp b/capio-server/include/communication-service/control-plane/multicast_control_plane.hpp index a0c1f9b56..431e33e4a 100644 --- a/capio-server/include/communication-service/control-plane/multicast_control_plane.hpp +++ b/capio-server/include/communication-service/control-plane/multicast_control_plane.hpp @@ -2,8 +2,8 @@ #define MULTICAST_CONTROL_PLANE_HPP #include #include +#include #include -#include #include class MulticastControlPlane : public CapioControlPlane { @@ -25,7 +25,7 @@ class MulticastControlPlane : public CapioControlPlane { ~MulticastControlPlane() override; - void notify_all(const event_type event, const std::filesystem::path &path) override; + void notify_all(event_type event, const std::filesystem::path &path) override; }; #endif // MULTICAST_CONTROL_PLANE_HPP diff --git a/capiorun/requirements.txt b/capiorun/requirements.txt deleted file mode 100644 index 66be15d71..000000000 --- a/capiorun/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -loguru==0.7.3 \ No newline at end of file diff --git a/benchmarks/lmbench.sh b/scripts/benchmarks/lmbench.sh similarity index 100% rename from benchmarks/lmbench.sh rename to scripts/benchmarks/lmbench.sh From 5902919f874cc4e4de2962190faf72f8d8ced7d4 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Sat, 30 Aug 2025 09:59:13 +0000 Subject: [PATCH 10/10] cleanup --- .github/workflows/ci-tests.yaml | 1 - capio-common/capio/env.hpp | 2 +- capio-server/CMakeLists.txt | 1 + capio-server/capio_server.cpp | 8 +-- .../include/client-manager/client_manager.hpp | 1 - .../client-manager/request_handler_engine.hpp | 3 +- .../data-plane/transport_unit.hpp | 2 +- .../include/file-manager/file_manager.hpp | 2 +- .../include/file-manager/fs_monitor.hpp | 2 +- .../include/utils/command_line_parser.hpp | 15 ++++ .../{ => include}/utils/configuration.hpp | 0 .../include/utils/distributed_semaphore.hpp | 37 ++++++++++ capio-server/{ => include}/utils/signals.hpp | 0 capio-server/{ => include}/utils/types.hpp | 0 .../src/capio-cl-engine/capio_cl_engine.cpp | 1 - .../capio_communication_service.cpp | 2 +- .../control-plane/fs_control_plane.cpp | 2 +- .../control-plane/multicast_utils.hpp | 2 +- .../src/file-manager/file_manager.cpp | 4 +- capio-server/src/file-manager/fs_monitor.cpp | 2 +- .../utils/command_line_parser.cpp} | 14 ++-- .../src/utils/distributed_semaphore.cpp | 44 ++++++++++++ capio-server/utils/distributed_semaphore.hpp | 69 ------------------- capio-tests/multinode/backend/src/main.cpp | 7 +- .../server/src/CapioCacheSPSCQueueTests.hpp | 2 +- 25 files changed, 120 insertions(+), 103 deletions(-) create mode 100644 capio-server/include/utils/command_line_parser.hpp rename capio-server/{ => include}/utils/configuration.hpp (100%) create mode 100644 capio-server/include/utils/distributed_semaphore.hpp rename capio-server/{ => include}/utils/signals.hpp (100%) rename capio-server/{ => include}/utils/types.hpp (100%) rename capio-server/{utils/parser.hpp => src/utils/command_line_parser.cpp} (97%) create mode 100644 capio-server/src/utils/distributed_semaphore.cpp delete mode 100644 capio-server/utils/distributed_semaphore.hpp diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index ada146961..724b10396 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -91,7 +91,6 @@ jobs: - Debug - Release cxx: - - g++-9 - g++-10 - g++-11 - g++-12 diff --git a/capio-common/capio/env.hpp b/capio-common/capio/env.hpp index 069ee5743..f60e6cfc6 100644 --- a/capio-common/capio/env.hpp +++ b/capio-common/capio/env.hpp @@ -10,7 +10,7 @@ #include #ifndef __CAPIO_POSIX -#include +#include #endif #include "logger.hpp" diff --git a/capio-server/CMakeLists.txt b/capio-server/CMakeLists.txt index a5cc2e6ec..ec4601cc1 100644 --- a/capio-server/CMakeLists.txt +++ b/capio-server/CMakeLists.txt @@ -2,6 +2,7 @@ # Target information ##################################### set(TARGET_NAME capio_server) + set(TARGET_INCLUDE_FOLDER .) file(GLOB_RECURSE TARGET_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" diff --git a/capio-server/capio_server.cpp b/capio-server/capio_server.cpp index 29a80189a..7eefa17f2 100644 --- a/capio-server/capio_server.cpp +++ b/capio-server/capio_server.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -10,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -26,9 +24,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include int main(int argc, char **argv) { std::cout << CAPIO_LOG_SERVER_BANNER; diff --git a/capio-server/include/client-manager/client_manager.hpp b/capio-server/include/client-manager/client_manager.hpp index 60c70878b..e979af0b3 100644 --- a/capio-server/include/client-manager/client_manager.hpp +++ b/capio-server/include/client-manager/client_manager.hpp @@ -2,7 +2,6 @@ #define CLIENT_MANAGER_HPP #include #include -#include #include /** diff --git a/capio-server/include/client-manager/request_handler_engine.hpp b/capio-server/include/client-manager/request_handler_engine.hpp index ec9e26b5b..dcc6dbf6c 100644 --- a/capio-server/include/client-manager/request_handler_engine.hpp +++ b/capio-server/include/client-manager/request_handler_engine.hpp @@ -3,8 +3,7 @@ #include "capio/requests.hpp" -#include -#include +#include /** * @brief Class that handles the system calls received from the posix client application diff --git a/capio-server/include/communication-service/data-plane/transport_unit.hpp b/capio-server/include/communication-service/data-plane/transport_unit.hpp index a0261d378..62ae5abf9 100644 --- a/capio-server/include/communication-service/data-plane/transport_unit.hpp +++ b/capio-server/include/communication-service/data-plane/transport_unit.hpp @@ -1,8 +1,8 @@ #ifndef TRANSPORT_UNIT_HPP #define TRANSPORT_UNIT_HPP +#include #include -#include class TransportUnit { protected: diff --git a/capio-server/include/file-manager/file_manager.hpp b/capio-server/include/file-manager/file_manager.hpp index 13387664a..f26d9a7e7 100644 --- a/capio-server/include/file-manager/file_manager.hpp +++ b/capio-server/include/file-manager/file_manager.hpp @@ -1,10 +1,10 @@ #ifndef FILE_MANAGER_HEADER_HPP #define FILE_MANAGER_HEADER_HPP +#include #include #include #include -#include inline std::mutex creation_mutex; inline std::mutex data_mutex; diff --git a/capio-server/include/file-manager/fs_monitor.hpp b/capio-server/include/file-manager/fs_monitor.hpp index abc2ba402..136933042 100644 --- a/capio-server/include/file-manager/fs_monitor.hpp +++ b/capio-server/include/file-manager/fs_monitor.hpp @@ -2,7 +2,7 @@ #define CAPIO_FS_FILE_SYSTEM_MONITOR_HPP #include #include -#include + /** * @brief Class that monitors the composition of the CAPIO_DIR directory. * diff --git a/capio-server/include/utils/command_line_parser.hpp b/capio-server/include/utils/command_line_parser.hpp new file mode 100644 index 000000000..ec5ec19f5 --- /dev/null +++ b/capio-server/include/utils/command_line_parser.hpp @@ -0,0 +1,15 @@ +#ifndef COMMAND_LINE_PARSER_HPP +#define COMMAND_LINE_PARSER_HPP +#include +#include + +/** + * Parse command line arguments. + * + * @param return value with string that contains the resolve prefix to use when parsing capio_cl + * file + * @return capio_cl configuration path + */ +std::string parseCLI(int argc, char **argv, char *resolve_prefix); + +#endif // COMMAND_LINE_PARSER_HPP diff --git a/capio-server/utils/configuration.hpp b/capio-server/include/utils/configuration.hpp similarity index 100% rename from capio-server/utils/configuration.hpp rename to capio-server/include/utils/configuration.hpp diff --git a/capio-server/include/utils/distributed_semaphore.hpp b/capio-server/include/utils/distributed_semaphore.hpp new file mode 100644 index 000000000..cd73bee5c --- /dev/null +++ b/capio-server/include/utils/distributed_semaphore.hpp @@ -0,0 +1,37 @@ +#ifndef DISTRIBUTEDSEMAPHORE_HPP +#define DISTRIBUTEDSEMAPHORE_HPP + +#include + +/** + * @brief Class to provide mutually exclusive access to files on distributed file systems by + * providing file based locking + */ +class DistributedSemaphore { + std::string name; + timespec sleep{}; + bool locked; + int fp; + + void lock(); + + void unlock() const; + + public: + /** + * @brief Construct a new Distributed Semaphore object. At instantiation of the object, the + * _lock() method is created this locking the resource. If the locking fails, a new attempt is + * done after sleep_time nanoseconds + * + * @param locking The file that is the target to mutual exclusive access + * @param sleep_time Sleep time between lock tries in nano seconds + */ + DistributedSemaphore(std::string locking, int sleep_time); + + /** + * @brief Destroy the Distributed Semaphore object thus unlocking the resource + * + */ + ~DistributedSemaphore(); +}; +#endif // DISTRIBUTEDSEMAPHORE_HPP \ No newline at end of file diff --git a/capio-server/utils/signals.hpp b/capio-server/include/utils/signals.hpp similarity index 100% rename from capio-server/utils/signals.hpp rename to capio-server/include/utils/signals.hpp diff --git a/capio-server/utils/types.hpp b/capio-server/include/utils/types.hpp similarity index 100% rename from capio-server/utils/types.hpp rename to capio-server/include/utils/types.hpp diff --git a/capio-server/src/capio-cl-engine/capio_cl_engine.cpp b/capio-server/src/capio-cl-engine/capio_cl_engine.cpp index af0bfd419..4cb60859e 100644 --- a/capio-server/src/capio-cl-engine/capio_cl_engine.cpp +++ b/capio-server/src/capio-cl-engine/capio_cl_engine.cpp @@ -1,5 +1,4 @@ -#include "utils/configuration.hpp" #include void CapioCLEngine::print() const { diff --git a/capio-server/src/communication-service/capio_communication_service.cpp b/capio-server/src/communication-service/capio_communication_service.cpp index 2c856a097..2ab92397a 100644 --- a/capio-server/src/communication-service/capio_communication_service.cpp +++ b/capio-server/src/communication-service/capio_communication_service.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include CapioCommunicationService::~CapioCommunicationService() { delete capio_control_plane; diff --git a/capio-server/src/communication-service/control-plane/fs_control_plane.cpp b/capio-server/src/communication-service/control-plane/fs_control_plane.cpp index c3ae7285e..47c9fbced 100644 --- a/capio-server/src/communication-service/control-plane/fs_control_plane.cpp +++ b/capio-server/src/communication-service/control-plane/fs_control_plane.cpp @@ -3,8 +3,8 @@ #include #include #include +#include #include -#include void FSControlPlane::generate_aliveness_token(const int port) const { START_LOG(gettid(), "call(port=d)", port); diff --git a/capio-server/src/communication-service/control-plane/multicast_utils.hpp b/capio-server/src/communication-service/control-plane/multicast_utils.hpp index 8684deedf..ee37f800e 100644 --- a/capio-server/src/communication-service/control-plane/multicast_utils.hpp +++ b/capio-server/src/communication-service/control-plane/multicast_utils.hpp @@ -5,9 +5,9 @@ #include #include #include +#include #include #include -#include static int open_outgoing_multicast_socket(const char *address, const int port, sockaddr_in *addr) { int transmission_socket = socket(AF_INET, SOCK_DGRAM, 0); diff --git a/capio-server/src/file-manager/file_manager.cpp b/capio-server/src/file-manager/file_manager.cpp index 56d0eacee..6439b4f52 100644 --- a/capio-server/src/file-manager/file_manager.cpp +++ b/capio-server/src/file-manager/file_manager.cpp @@ -2,12 +2,10 @@ #define FILE_MANAGER_HPP #include "include/file-manager/file_manager.hpp" #include "capio/env.hpp" - -#include "utils/distributed_semaphore.hpp" - #include #include #include +#include std::string CapioFileManager::getMetadataPath(const std::string &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); diff --git a/capio-server/src/file-manager/fs_monitor.cpp b/capio-server/src/file-manager/fs_monitor.cpp index 1bfa5379e..907052f3e 100644 --- a/capio-server/src/file-manager/fs_monitor.cpp +++ b/capio-server/src/file-manager/fs_monitor.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include FileSystemMonitor::FileSystemMonitor() { START_LOG(gettid(), "call()"); diff --git a/capio-server/utils/parser.hpp b/capio-server/src/utils/command_line_parser.cpp similarity index 97% rename from capio-server/utils/parser.hpp rename to capio-server/src/utils/command_line_parser.cpp index efb0180a3..0eba0ad1b 100644 --- a/capio-server/utils/parser.hpp +++ b/capio-server/src/utils/command_line_parser.cpp @@ -1,7 +1,11 @@ -#ifndef PARSER_HPP -#define PARSER_HPP - +#include +#include +#include +#include #include +#include +#include +#include std::string parseCLI(int argc, char **argv, char *resolve_prefix) { Logger *log; @@ -175,6 +179,4 @@ std::string parseCLI(int argc, char **argv, char *resolve_prefix) { return args::get(config); } return ""; -} - -#endif // PARSER_HPP \ No newline at end of file +} \ No newline at end of file diff --git a/capio-server/src/utils/distributed_semaphore.cpp b/capio-server/src/utils/distributed_semaphore.cpp new file mode 100644 index 000000000..f971c7164 --- /dev/null +++ b/capio-server/src/utils/distributed_semaphore.cpp @@ -0,0 +1,44 @@ +#include +#include + +void DistributedSemaphore::lock() { + START_LOG(gettid(), "call(locking=%s)", name.c_str()); + if (!locked) { + while (fp == -1) { + nanosleep(&sleep, nullptr); + fp = open(name.c_str(), O_EXCL | O_CREAT | O_WRONLY, 0777); + } + LOG("Locked %s", name.c_str()); + if (write(fp, capio_global_configuration->node_name, + strlen(capio_global_configuration->node_name)) == -1) { + ERR_EXIT("Unable to insert lock holder %s on lock file %s", + capio_global_configuration->node_name, name.c_str()); + } + } + LOG("Completed spinlock on lock file %s", name.c_str()); + locked = true; +} + +void DistributedSemaphore::unlock() const { + START_LOG(gettid(), "call(unlocking=%s)", name.c_str()); + if (locked) { + close(fp); + unlink(name.c_str()); + } + LOG("Unlocked %s", name.c_str()); +} + +DistributedSemaphore::DistributedSemaphore(std::string locking, int sleep_time) + : name(locking), locked(false), fp(-1) { + START_LOG(gettid(), "call(locking=%s, sleep_time=%ld)", name.c_str(), sleep_time); + sleep.tv_nsec = sleep_time; + + this->lock(); +} + +DistributedSemaphore::~DistributedSemaphore() { + START_LOG(gettid(), "call()"); + if (locked) { + this->unlock(); + } +} \ No newline at end of file diff --git a/capio-server/utils/distributed_semaphore.hpp b/capio-server/utils/distributed_semaphore.hpp deleted file mode 100644 index e7ce1d569..000000000 --- a/capio-server/utils/distributed_semaphore.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef DISTRIBUTEDSEMAPHORE_HPP -#define DISTRIBUTEDSEMAPHORE_HPP - -/** - * @brief Class to provide mutually exclusive access to files on distributed file systems by - * providing file based locking - */ -class DistributedSemaphore { - std::string name; - timespec sleep{}; - bool locked; - int fp; - - void lock() { - START_LOG(gettid(), "call(locking=%s)", name.c_str()); - if (!locked) { - while (fp == -1) { - nanosleep(&sleep, nullptr); - fp = open(name.c_str(), O_EXCL | O_CREAT | O_WRONLY, 0777); - } - LOG("Locked %s", name.c_str()); - if (write(fp, capio_global_configuration->node_name, - strlen(capio_global_configuration->node_name)) == -1) { - ERR_EXIT("Unable to insert lock holder %s on lock file %s", - capio_global_configuration->node_name, name.c_str()); - } - } - LOG("Completed spinlock on lock file %s", name.c_str()); - locked = true; - } - - void unlock() const { - START_LOG(gettid(), "call(unlocking=%s)", name.c_str()); - if (locked) { - close(fp); - unlink(name.c_str()); - } - LOG("Unlocked %s", name.c_str()); - } - - public: - /** - * @brief Construct a new Distributed Semaphore object. At instantiation of the object, the - * _lock() method is created this locking the resource. If the locking fails, a new attempt is - * done after sleep_time nanoseconds - * - * @param locking The file that is the target to mutual exclusive access - * @param sleep_time Sleep time between lock tries in nano seconds - */ - DistributedSemaphore(std::string locking, int sleep_time) - : name(locking), locked(false), fp(-1) { - START_LOG(gettid(), "call(locking=%s, sleep_time=%ld)", name.c_str(), sleep_time); - sleep.tv_nsec = sleep_time; - - this->lock(); - } - - /** - * @brief Destroy the Distributed Semaphore object thus unlocking the resource - * - */ - ~DistributedSemaphore() { - START_LOG(gettid(), "call()"); - if (locked) { - this->unlock(); - } - } -}; -#endif // DISTRIBUTEDSEMAPHORE_HPP \ No newline at end of file diff --git a/capio-tests/multinode/backend/src/main.cpp b/capio-tests/multinode/backend/src/main.cpp index d1145deb2..a23b5bccb 100644 --- a/capio-tests/multinode/backend/src/main.cpp +++ b/capio-tests/multinode/backend/src/main.cpp @@ -1,11 +1,6 @@ -#include -#include - -#include "../capio-server/utils/configuration.hpp" - #include "MTCL.hpp" -#include +#include int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); diff --git a/capio-tests/unit/server/src/CapioCacheSPSCQueueTests.hpp b/capio-tests/unit/server/src/CapioCacheSPSCQueueTests.hpp index b65f777b0..f65f8f385 100644 --- a/capio-tests/unit/server/src/CapioCacheSPSCQueueTests.hpp +++ b/capio-tests/unit/server/src/CapioCacheSPSCQueueTests.hpp @@ -3,7 +3,7 @@ #include -#include "../capio-server/utils/configuration.hpp" +#include "../capio-server/include/utils/configuration.hpp" #include "../capio-posix/utils/env.hpp" #include "../capio-posix/utils/filesystem.hpp"