From e9f968582664c28d409a87f7f9d3740dd889e20f Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 19 May 2026 11:04:47 +0200 Subject: [PATCH 01/16] Began porting SERVER logger to new infrastructure --- capio/common/env.hpp | 2 +- capio/common/logger.hpp | 233 ++++-------------- capio/posix/libcapio_posix.cpp | 2 + capio/posix/utils/PosixLogger.hpp | 128 ++++++++++ capio/posix/utils/cache.hpp | 188 -------------- capio/server/capio_server.cpp | 3 +- .../include/client-manager/client_manager.hpp | 2 + capio/server/include/remote/backend.hpp | 3 +- capio/server/include/remote/handlers/read.hpp | 1 + capio/server/include/remote/handlers/stat.hpp | 1 + capio/server/include/storage/capio_file.hpp | 2 + capio/server/include/utils/ServerLogger.hpp | 74 ++++++ capio/server/include/utils/cli_parser.hpp | 1 + capio/server/include/utils/common.hpp | 1 + capio/server/include/utils/env.hpp | 1 + capio/server/include/utils/location.hpp | 6 +- capio/server/include/utils/signals.hpp | 1 + capio/server/src/backend.cpp | 1 + capio/server/src/cli_parser.cpp | 33 +-- capio/server/src/client_manager.cpp | 4 +- capio/server/src/mpi_backend.cpp | 2 + capio/server/src/none_backend.cpp | 2 + capio/server/src/remote_request.cpp | 2 + capio/server/src/storage_manager.cpp | 5 +- 24 files changed, 281 insertions(+), 417 deletions(-) create mode 100644 capio/posix/utils/PosixLogger.hpp delete mode 100644 capio/posix/utils/cache.hpp create mode 100644 capio/server/include/utils/ServerLogger.hpp diff --git a/capio/common/env.hpp b/capio/common/env.hpp index cbfdc05aa..0e7313772 100644 --- a/capio/common/env.hpp +++ b/capio/common/env.hpp @@ -10,7 +10,7 @@ #include #include "common/syscall.hpp" -#include "logger.hpp" + // TODO: remove forward declaration of function by splitting into header and impl. capio/common inline bool is_forbidden_path(const std::string_view &path); diff --git a/capio/common/logger.hpp b/capio/common/logger.hpp index e507e5959..4616c44cb 100644 --- a/capio/common/logger.hpp +++ b/capio/common/logger.hpp @@ -6,10 +6,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include "constants.hpp" @@ -37,18 +39,6 @@ inline void raise_termination(const bool raise_exception, const std::string &mes #include "syscallnames.h" #endif -#ifndef __CAPIO_POSIX -#include -// FIXME: Remove the inline specifier by splitting into header and source code -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 -inline thread_local bool logfileOpen = false; -inline thread_local int logfileFD = -1; -inline thread_local char logfile_path[PATH_MAX]{'\0'}; -#endif - // FIXME: Remove the inline specifier by splitting into header and source code inline thread_local int current_log_level = 0; @@ -63,97 +53,6 @@ inline thread_local bool logging_syscall = false; // FIXME: Remove the inline specifier by splitting into header and source code inline int CAPIO_LOG_LEVEL = CAPIO_MAX_LOG_LEVEL; -#ifndef __CAPIO_POSIX -inline auto open_server_logfile() { - auto hostname = new char[HOST_NAME_MAX]; - gethostname(hostname, HOST_NAME_MAX); - - if (log_master_dir_name.empty()) { - log_master_dir_name = CAPIO_DEFAULT_LOG_FOLDER; - } - - const std::filesystem::path output_folder = - std::string{log_master_dir_name + "/server/" + hostname}; - - std::filesystem::create_directories(output_folder); - - const std::filesystem::path logfile_name = output_folder.string() + "/" + logfile_prefix + - std::to_string(capio_syscall(SYS_gettid)) + ".log"; - - logfile.open(logfile_name, std::ofstream::out); - delete[] hostname; - - return logfile_name; -} -#else - -inline auto get_hostname() { - static char *hostname_prefix = nullptr; - if (hostname_prefix == nullptr) { - hostname_prefix = new char[HOST_NAME_MAX]; - gethostname(hostname_prefix, HOST_NAME_MAX); - } - return hostname_prefix; -} - -inline auto get_log_dir() { - static char *posix_log_master_dir_name = nullptr; - if (posix_log_master_dir_name == nullptr) { - posix_log_master_dir_name = std::getenv("CAPIO_LOG_DIR"); - if (posix_log_master_dir_name == nullptr) { - posix_log_master_dir_name = new char[strlen(CAPIO_DEFAULT_LOG_FOLDER)]; - strcpy(posix_log_master_dir_name, CAPIO_DEFAULT_LOG_FOLDER); - } - } - return posix_log_master_dir_name; -} - -inline auto get_log_prefix() { - static char *posix_logfile_prefix = nullptr; - if (posix_logfile_prefix == nullptr) { - posix_logfile_prefix = std::getenv("CAPIO_LOG_PREFIX"); - if (posix_logfile_prefix == nullptr) { - posix_logfile_prefix = new char[strlen(CAPIO_LOG_POSIX_DEFAULT_LOG_FILE_PREFIX)]; - strcpy(posix_logfile_prefix, CAPIO_LOG_POSIX_DEFAULT_LOG_FILE_PREFIX); - } - } - return posix_logfile_prefix; -} - -inline auto get_posix_log_dir() { - static char *posix_log_dir_path = nullptr; - if (posix_log_dir_path == nullptr) { - // allocate space for a path in the following structure (including 10 digits for thread id - // max - // log_master_dir_name/posix/hostname/logfile_prefix_.log - auto len = strlen(get_log_dir()) + 7; - posix_log_dir_path = new char[len]{0}; - sprintf(posix_log_dir_path, "%s/posix", get_log_dir()); - } - return posix_log_dir_path; -} - -inline auto get_host_log_dir() { - static char *host_log_dir_path = nullptr; - if (host_log_dir_path == nullptr) { - // allocate space for a path in the following structure (including 10 digits for thread id - // max - // log_master_dir_name/posix/hostname/logfile_prefix_.log - auto len = strlen(get_posix_log_dir()) + HOST_NAME_MAX; - host_log_dir_path = new char[len]{0}; - sprintf(host_log_dir_path, "%s/%s", get_posix_log_dir(), get_hostname()); - } - return host_log_dir_path; -} - -inline void setup_posix_log_filename() { - if (logfile_path[0] == '\0') { - sprintf(logfile_path, "%s/%s%ld.log", get_host_log_dir(), get_log_prefix(), - capio_syscall(SYS_gettid)); - } -} -#endif - inline long long current_time_in_millis() { timespec ts{}; static long long start_time = -1; @@ -166,25 +65,9 @@ inline long long current_time_in_millis() { return time_now - start_time; } -inline void log_write_to(char *buffer, size_t bufflen) { -#ifdef __CAPIO_POSIX - if (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0) { - capio_syscall(SYS_write, logfileFD, buffer, bufflen); - capio_syscall(SYS_write, logfileFD, "\n", 1); - } -#else - if (current_log_level < CAPIO_LOG_LEVEL || CAPIO_LOG_LEVEL < 0) { - logfile << buffer << std::endl; - logfile.flush(); - } - -#endif -} - /** * @brief Class used to suspend the logging capabilities of CAPIO, by setting the logging_syscall * flag to false at instantiation, and restarting the logging at destruction - * */ class SyscallLoggingSuspender { public: @@ -194,50 +77,31 @@ class SyscallLoggingSuspender { /** * @brief Class that provides logging capabilities to CAPIO. - * When compiled with the CAPIO intercepting library, it uses - * direct POSIX system calls. Otherwise, it relies on the STL. * + * Parameterised on a LogWriteAdapter so that the I/O strategy (POSIX + * syscalls vs. STL streams vs. any custom backend) is a compile-time + * choice with no virtual dispatch overhead. + * + * The default adapter (@ref DefaultLogWriteAdapter) mirrors the behaviour + * of the old monolithic Logger class for both the server and POSIX builds. */ -class Logger { - private: +template class TemplateLogger { char invoker[256]{0}; char file[256]{0}; char format[CAPIO_LOG_MAX_MSG_LEN]{0}; + unsigned int line{0}; + long int tid{0}; + + Adapter adapter; public: - inline Logger(const char invoker[], const char file[], int line, long int tid, - const char *message, ...) { -#ifndef __CAPIO_POSIX - if (!logfile.is_open()) { - // NOTE: should never get to this point as capio_server opens up the log file while - // parsing command line arguments. This is only for failsafe purpose - open_server_logfile(); - } -#else - if (!logfileOpen) { - setup_posix_log_filename(); - current_log_level = - 0; // reset log level after clone, avoiding propagation to child threads - - capio_syscall(SYS_mkdirat, AT_FDCWD, get_log_dir(), 0755); - capio_syscall(SYS_mkdirat, AT_FDCWD, get_posix_log_dir(), 0755); - capio_syscall(SYS_mkdirat, AT_FDCWD, get_host_log_dir(), 0755); - - logfileFD = capio_syscall(SYS_openat, AT_FDCWD, logfile_path, - O_CREAT | O_WRONLY | O_TRUNC, 0644); - - if (logfileFD == -1) { - capio_syscall(SYS_write, fileno(stdout), - "Err fopen file: ", strlen("Err fopen file: ")); - capio_syscall(SYS_write, fileno(stdout), logfile_path, strlen(logfile_path)); - capio_syscall(SYS_write, fileno(stdout), " ", 1); - capio_syscall(SYS_write, fileno(stdout), strerror(errno), strlen(strerror(errno))); - capio_syscall(SYS_write, fileno(stdout), "\n", 1); - exit(EXIT_FAILURE); - } - logfileOpen = true; - } -#endif + TemplateLogger(const char invoker[], const char file[], unsigned int line, long int tid, + const char *message, ...) { + + adapter.openLogFile(); + + this->tid = tid; + this->line = line; strncpy(this->invoker, invoker, sizeof(this->invoker)); strncpy(this->file, file, sizeof(this->file)); @@ -245,7 +109,6 @@ class Logger { sprintf(format, CAPIO_LOG_PRE_MSG, current_time_in_millis(), this->invoker); const size_t pre_msg_len = strlen(format); - strcpy(format + pre_msg_len, message); va_start(argp, message); @@ -266,17 +129,17 @@ class Logger { SYS_mmap, nullptr, 50, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); sprintf(buf1, CAPIO_LOG_POSIX_SYSCALL_START, sys_num_to_string(syscallNumber).c_str(), syscallNumber); - log_write_to(buf1, strlen(buf1)); + adapter.writeRaw(buf1, strlen(buf1)); capio_syscall(SYS_munmap, buf1, 50); } #endif - int size = vsnprintf(nullptr, 0U, format, argp); - auto buf = reinterpret_cast(capio_syscall(SYS_mmap, nullptr, size + 1, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); + const int size = vsnprintf(nullptr, 0U, format, argp); + auto buf = reinterpret_cast(capio_syscall(SYS_mmap, nullptr, size + 1, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); vsnprintf(buf, size + 1, format, argpc); - log_write_to(buf, strlen(buf)); + adapter.write(this->invoker, this->file, this->line, this->tid, buf, strlen(buf)); va_end(argp); va_end(argpc); @@ -284,41 +147,34 @@ class Logger { current_log_level++; } - Logger(const Logger &) = delete; - Logger &operator=(const Logger &) = delete; + TemplateLogger(const TemplateLogger &) = delete; + TemplateLogger &operator=(const TemplateLogger &) = delete; - inline ~Logger() { + ~TemplateLogger() { current_log_level--; sprintf(format, CAPIO_LOG_PRE_MSG, current_time_in_millis(), this->invoker); - size_t pre_msg_len = strlen(format); + const size_t pre_msg_len = strlen(format); strcpy(format + pre_msg_len, "returned"); - log_write_to(format, strlen(format)); -#ifdef __CAPIO_POSIX + adapter.writeRaw(format, strlen(format)); + if (current_log_level == 0 && logging_syscall) { - log_write_to(const_cast(CAPIO_LOG_POSIX_SYSCALL_END), - strlen(CAPIO_LOG_POSIX_SYSCALL_END)); + adapter.writeSyscallEnd(); } -#endif } - inline void log(const char *message, ...) { + void log(const char *message, ...) { va_list argp, argpc; sprintf(format, CAPIO_LOG_PRE_MSG, current_time_in_millis(), this->invoker); const size_t pre_msg_len = strlen(format); - strcpy(format + pre_msg_len, message); -#ifndef __CAPIO_POSIX - // if the log message to serve a new request or concludes, add new spaces - if (strcmp(invoker, "capio_server") == 0 && - (strcmp(CAPIO_LOG_SERVER_REQUEST_START, message) == 0 || - strcmp(CAPIO_LOG_SERVER_REQUEST_END, message) == 0)) { - logfile << message << std::endl; + // Delegate the server request start/end special case to the adapter + if (adapter.isServerInvoker(this->invoker, message)) { + adapter.writeRaw(format, strlen(format)); return; } -#endif va_start(argp, message); va_copy(argpc, argp); @@ -327,24 +183,27 @@ class Logger { capio_syscall(SYS_mmap, nullptr, size + 1, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); vsnprintf(buf, size + 1, format, argpc); - log_write_to(buf, strlen(buf)); + adapter.write(this->invoker, this->file, this->line, this->tid, buf, strlen(buf)); va_end(argp); va_end(argpc); capio_syscall(SYS_munmap, buf, size); } + + std::string getLogFileName() { return adapter.getLogFileName(); } }; +// --------------------------------------------------------------------------- +// Macros — identical surface to the old ones; Logger is now a template +// --------------------------------------------------------------------------- #ifdef CAPIO_LOG #define ERR_EXIT_EXCEPT_CHOICE(raise_exception, message, ...) \ log.log(message, ##__VA_ARGS__); \ if (!continue_on_error) { \ - if (!continue_on_error) { \ - char err_msg[CAPIO_LOG_MAX_MSG_LEN]; \ - snprintf(err_msg, CAPIO_LOG_MAX_MSG_LEN, message, ##__VA_ARGS__); \ - raise_termination(raise_exception, err_msg); \ - } \ + char err_msg[CAPIO_LOG_MAX_MSG_LEN]; \ + snprintf(err_msg, CAPIO_LOG_MAX_MSG_LEN, message, ##__VA_ARGS__); \ + raise_termination(raise_exception, err_msg); \ } #define ERR_EXIT(message, ...) ERR_EXIT_EXCEPT_CHOICE(true, message, ##__VA_ARGS__) diff --git a/capio/posix/libcapio_posix.cpp b/capio/posix/libcapio_posix.cpp index 3aedd1a46..d6bf64396 100644 --- a/capio/posix/libcapio_posix.cpp +++ b/capio/posix/libcapio_posix.cpp @@ -7,6 +7,8 @@ #include #include +#include "utils/PosixLogger.hpp" + #include "common/syscall.hpp" #include "utils/clone.hpp" diff --git a/capio/posix/utils/PosixLogger.hpp b/capio/posix/utils/PosixLogger.hpp new file mode 100644 index 000000000..d3ea59f03 --- /dev/null +++ b/capio/posix/utils/PosixLogger.hpp @@ -0,0 +1,128 @@ +#ifndef CAPIO_POSIXLOGGER_HPP +#define CAPIO_POSIXLOGGER_HPP + +#include "common/logger.hpp" + + +struct PosixLogWriteAdapter { + private: + bool fileOpen{false}; + int fileFD{-1}; + char filePath[PATH_MAX]{'\0'}; + + static const char *getHostname() { + static char hostname[HOST_NAME_MAX]{'\0'}; + if (hostname[0] == '\0') { + gethostname(hostname, HOST_NAME_MAX); + } + return hostname; + } + + static const char *getLogDir() { + static char *dir = nullptr; + if (dir == nullptr) { + dir = std::getenv("CAPIO_LOG_DIR"); + if (dir == nullptr) { + dir = new char[strlen(CAPIO_DEFAULT_LOG_FOLDER) + 1]; + strcpy(dir, CAPIO_DEFAULT_LOG_FOLDER); + } + } + return dir; + } + + static const char *getLogPrefix() { + static char *prefix = nullptr; + if (prefix == nullptr) { + prefix = std::getenv("CAPIO_LOG_PREFIX"); + if (prefix == nullptr) { + prefix = new char[strlen(CAPIO_LOG_POSIX_DEFAULT_LOG_FILE_PREFIX) + 1]; + strcpy(prefix, CAPIO_LOG_POSIX_DEFAULT_LOG_FILE_PREFIX); + } + } + return prefix; + } + + static const char *getPosixLogDir() { + static char *dir = nullptr; + if (dir == nullptr) { + const char *base = getLogDir(); + dir = new char[strlen(base) + 7]{0}; // "/posix\0" + sprintf(dir, "%s/posix", base); + } + return dir; + } + + static const char *getHostLogDir() { + static char *dir = nullptr; + if (dir == nullptr) { + const char *posixDir = getPosixLogDir(); + dir = new char[strlen(posixDir) + HOST_NAME_MAX]{0}; + sprintf(dir, "%s/%s", posixDir, getHostname()); + } + return dir; + } + + void setupLogFilename() { + if (filePath[0] == '\0') { + sprintf(filePath, "%s/%s%ld.log", getHostLogDir(), getLogPrefix(), + capio_syscall(SYS_gettid)); + } + } + + // ---- write helper ------------------------------------------------------ + + void writeToFD(const char *buf, size_t len) const { + capio_syscall(SYS_write, fileFD, buf, len); + capio_syscall(SYS_write, fileFD, "\n", 1); + } + + public: + [[nodiscard]] bool isFileOpened() const { return fileOpen; } + + void openLogFile() { + setupLogFilename(); + current_log_level = 0; // reset log level after clone, avoiding propagation to child threads + + capio_syscall(SYS_mkdirat, AT_FDCWD, getLogDir(), 0755); + capio_syscall(SYS_mkdirat, AT_FDCWD, getPosixLogDir(), 0755); + capio_syscall(SYS_mkdirat, AT_FDCWD, getHostLogDir(), 0755); + + fileFD = capio_syscall(SYS_openat, AT_FDCWD, filePath, O_CREAT | O_WRONLY | O_TRUNC, 0644); + + if (fileFD == -1) { + capio_syscall(SYS_write, fileno(stdout), + "Err fopen file: ", strlen("Err fopen file: ")); + capio_syscall(SYS_write, fileno(stdout), filePath, strlen(filePath)); + capio_syscall(SYS_write, fileno(stdout), " ", 1); + capio_syscall(SYS_write, fileno(stdout), strerror(errno), strlen(strerror(errno))); + capio_syscall(SYS_write, fileno(stdout), "\n", 1); + exit(EXIT_FAILURE); + } + fileOpen = true; + } + + void write(const char * /*invoker*/, const char * /*file*/, unsigned int /*line*/, + long int /*tid*/, const char *buf, size_t len) const { + if (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0) { + writeToFD(buf, len); + } + } + + void writeRaw(const char *buf, size_t len) const { + if (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0) { + writeToFD(buf, len); + } + } + + void writeSyscallEnd() const { + writeRaw(CAPIO_LOG_POSIX_SYSCALL_END, strlen(CAPIO_LOG_POSIX_SYSCALL_END)); + } + + static bool isServerInvoker(const char * /*invoker*/, const char * /*message*/) { + return false; + } +}; + +using Logger = TemplateLogger; + +#endif // CAPIO_POSIXLOGGER_HPP diff --git a/capio/posix/utils/cache.hpp b/capio/posix/utils/cache.hpp deleted file mode 100644 index 597d644a5..000000000 --- a/capio/posix/utils/cache.hpp +++ /dev/null @@ -1,188 +0,0 @@ -#ifndef CAPIO_SERVER_UTILS_CACHE -#define CAPIO_SERVER_UTILS_CACHE - -#include "common/dirent.hpp" -#include "common/queue.hpp" - -#include "requests.hpp" - -class ReadCache { - private: - char *_cache; - long _tid; - int _last_fd; - off64_t _max_line_size, _actual_size, _cache_offset; - SPSCQueue _queue; - - inline void _read(void *buffer, off64_t count) { - START_LOG(capio_syscall(SYS_gettid), "call(count=%ld)", count); - - if (count > 0) { - memcpy(buffer, _cache + _cache_offset, count); - LOG("Read %ld. adding it to _cache_offset of value %ld", count, _cache_offset); - _cache_offset += count; - } - } - - public: - ReadCache(long tid, off64_t lines, off64_t line_size, const std::string &workflow_name) - : _cache(nullptr), _tid(tid), _last_fd(-1), _max_line_size(line_size), _actual_size(0), - _cache_offset(0), - _queue(SHM_SPSC_PREFIX_READ + std::to_string(tid), lines, line_size, workflow_name) {} - - inline void flush() { - START_LOG(capio_syscall(SYS_gettid), "call()"); - - if (_cache_offset != _actual_size) { - _actual_size = _cache_offset = 0; - seek_request(_last_fd, get_capio_fd_offset(_last_fd), _tid); - } - } - - inline off64_t read(int fd, void *buffer, off64_t count, bool is_getdents, bool is64bit) { - START_LOG(capio_syscall(SYS_gettid), "call(fd=%d, count=%ld, is_getdents=%s, is64bit=%s)", - fd, count, is_getdents ? "true" : "false", is64bit ? "true" : "false"); - - if (_last_fd != fd) { - LOG("changed fd from %d to %d: flushing", _last_fd, fd); - flush(); - _last_fd = fd; - } - - off64_t remaining_bytes = _actual_size - _cache_offset; - off64_t file_offset = get_capio_fd_offset(fd); - off64_t bytes_read; - - if (is_getdents) { - auto dirent_size = static_cast(sizeof(linux_dirent64)); - count = (count / dirent_size) * dirent_size; - } - - auto read_size = count - remaining_bytes; - LOG("Read() will need to read %ld bytes", read_size); - - if (count <= remaining_bytes) { - LOG("count %ld <= remaining_bytes %ld", count, remaining_bytes); - _read(buffer, count); - bytes_read = count; - } else { - LOG("count %ld > remaining_bytes %ld", count, remaining_bytes); - _read(buffer, remaining_bytes); - buffer = reinterpret_cast(buffer) + remaining_bytes; - - // NOTE: if getdents send a request for exactly the correct amount of data. - if (read_size > _max_line_size || is_getdents) { - LOG("count - remaining_bytes %ld > _max_line_size %ld", read_size, _max_line_size); - LOG("Reading exactly requested size"); - off64_t end_of_read = is_getdents ? getdents_request(fd, read_size, is64bit, _tid) - : read_request(fd, read_size, _tid); - bytes_read = end_of_read - file_offset; - _queue.read(reinterpret_cast(buffer), bytes_read); - } else { - LOG("count - remaining_bytes %ld <= _max_line_size %ld", read_size, _max_line_size); - LOG("Reading more to use pre fetching and caching"); - off64_t end_of_read = is_getdents - ? getdents_request(fd, _max_line_size, is64bit, _tid) - : read_request(fd, _max_line_size, _tid); - LOG("request return value is %ld", end_of_read); - _actual_size = end_of_read - file_offset - remaining_bytes; - LOG("ReaderCache actual size, after requested read is: %ld bytes", _actual_size); - _cache_offset = 0; - if (_actual_size > 0) { - LOG("Fetching data from shm _queue"); - _cache = _queue.fetch(); - } - if (read_size < _actual_size) { - LOG("count - remaining_bytes %ld < _actual_size %ld", read_size, _actual_size); - _read(buffer, read_size); - bytes_read = count; - } else { - LOG("count - remaining_bytes %ld >= _actual_size %ld", read_size, _actual_size); - _read(buffer, _actual_size); - bytes_read = remaining_bytes + _actual_size; - } - } - } - LOG("%ld bytes have been read. setting fd offset to %ld", bytes_read, - file_offset + bytes_read); - set_capio_fd_offset(fd, file_offset + bytes_read); - return bytes_read; - } -}; - -class WriteCache { - private: - char *_cache; - long _tid; - int _fd; - off64_t _max_line_size, _actual_size; - SPSCQueue _queue; - - inline void _write(off64_t count, const void *buffer) { - START_LOG(capio_syscall(SYS_gettid), "call(count=%ld)", count); - - if (count > 0) { - if (_cache == nullptr) { - _cache = _queue.reserve(); - } - memcpy(_cache + _actual_size, buffer, count); - _actual_size += count; - if (_actual_size == _max_line_size) { - flush(); - } - } - } - - public: - WriteCache(long tid, off64_t lines, off64_t line_size, const std::string &workflow_name) - : _cache(nullptr), _tid(tid), _fd(-1), _max_line_size(line_size), _actual_size(0), - _queue(SHM_SPSC_PREFIX_WRITE + std::to_string(tid), lines, line_size, workflow_name) {} - - inline void flush() { - START_LOG(capio_syscall(SYS_gettid), "call()"); - - if (_actual_size != 0) { - write_request(_fd, _actual_size, _tid); - _cache = nullptr; - _actual_size = 0; - } - } - - inline void write(int fd, const void *buffer, off64_t count) { - START_LOG(capio_syscall(SYS_gettid), "call(fd=%d, buffer=0x%08x, count=%ld)", fd, buffer, - count); - - if (_fd != fd) { - LOG("changed fd from %d to %d: flushing", _fd, fd); - flush(); - _fd = fd; - } - - if (count <= _max_line_size - _actual_size) { - LOG("count %ld <= _max_line_size - _actual_size %ld", count, - _max_line_size - _actual_size); - _write(count, buffer); - } else { - LOG("count %ld > _max_line_size - _actual_size %ld", count, - _max_line_size - _actual_size); - flush(); - if (count - _actual_size > _max_line_size) { - LOG("count - _actual_size %ld > _max_line_size %ld", count - _actual_size, - _max_line_size); - write_request(_fd, count, _tid); - _queue.write(reinterpret_cast(buffer), count); - } else { - LOG("count - _actual_size %ld <= _max_line_size %ld", count - _actual_size, - _max_line_size); - _write(count, buffer); - } - } - - set_capio_fd_offset(fd, get_capio_fd_offset(fd) + count); - } -}; - -inline thread_local WriteCache *write_cache; -inline thread_local ReadCache *read_cache; - -#endif // CAPIO_SERVER_UTILS_CACHE diff --git a/capio/server/capio_server.cpp b/capio/server/capio_server.cpp index 403ec8f49..971ae6c5c 100644 --- a/capio/server/capio_server.cpp +++ b/capio/server/capio_server.cpp @@ -17,6 +17,8 @@ #include #include +#include "utils/ServerLogger.hpp" + #include "capiocl.hpp" #include "capiocl/engine.h" #include "capiocl/parser.h" @@ -24,7 +26,6 @@ #include "client-manager/client_manager.hpp" #include "common/env.hpp" -#include "common/logger.hpp" #include "common/requests.hpp" #include "common/semaphore.hpp" #include "remote/backend.hpp" diff --git a/capio/server/include/client-manager/client_manager.hpp b/capio/server/include/client-manager/client_manager.hpp index 3c91eb705..53af1c9cc 100644 --- a/capio/server/include/client-manager/client_manager.hpp +++ b/capio/server/include/client-manager/client_manager.hpp @@ -5,6 +5,8 @@ #include #include +#include "utils/ServerLogger.hpp" + #include "common/queue.hpp" /** * @brief Class to handle libcapio_posix clients applications diff --git a/capio/server/include/remote/backend.hpp b/capio/server/include/remote/backend.hpp index f1c827821..02622f0b5 100644 --- a/capio/server/include/remote/backend.hpp +++ b/capio/server/include/remote/backend.hpp @@ -2,8 +2,7 @@ #define CAPIO_SERVER_REMOTE_BACKEND_HPP #include #include - -#include "common/logger.hpp" +#include class RemoteRequest { char *_buf_recv; diff --git a/capio/server/include/remote/handlers/read.hpp b/capio/server/include/remote/handlers/read.hpp index d4a4f6cd2..19483f756 100644 --- a/capio/server/include/remote/handlers/read.hpp +++ b/capio/server/include/remote/handlers/read.hpp @@ -4,6 +4,7 @@ #include "remote/backend.hpp" #include "remote/requests.hpp" #include "storage/manager.hpp" +#include "utils/ServerLogger.hpp" extern StorageManager *storage_manager; diff --git a/capio/server/include/remote/handlers/stat.hpp b/capio/server/include/remote/handlers/stat.hpp index 80cd4cc47..9ea22e336 100644 --- a/capio/server/include/remote/handlers/stat.hpp +++ b/capio/server/include/remote/handlers/stat.hpp @@ -5,6 +5,7 @@ #include "remote/backend.hpp" #include "remote/requests.hpp" #include "storage/manager.hpp" +#include "utils/ServerLogger.hpp" extern StorageManager *storage_manager; extern ClientManager *client_manager; diff --git a/capio/server/include/storage/capio_file.hpp b/capio/server/include/storage/capio_file.hpp index aca4ff842..5605fbe97 100644 --- a/capio/server/include/storage/capio_file.hpp +++ b/capio/server/include/storage/capio_file.hpp @@ -10,6 +10,8 @@ #include #include +#include "utils/ServerLogger.hpp" + #include "common/queue.hpp" /** diff --git a/capio/server/include/utils/ServerLogger.hpp b/capio/server/include/utils/ServerLogger.hpp new file mode 100644 index 000000000..f4c9d8322 --- /dev/null +++ b/capio/server/include/utils/ServerLogger.hpp @@ -0,0 +1,74 @@ +#ifndef CAPIO_SERVERLOGGER_HPP +#define CAPIO_SERVERLOGGER_HPP + +#include + +struct ServerLogWriteAdapter { + private: + std::ofstream logfile; + std::string logMasterDirName; + std::string logfilePrefix; + std::string logFileName; + + void writeToStream(const char *buf) { + if (current_log_level < CAPIO_LOG_LEVEL || CAPIO_LOG_LEVEL < 0) { + logfile << buf << std::endl; + logfile.flush(); + } + } + + public: + explicit ServerLogWriteAdapter() { + if (const char *tmp = std::getenv("CAPIO_LOGGER_MASTER_DIR_NAME"); tmp == nullptr) { + logMasterDirName = CAPIO_DEFAULT_LOG_FOLDER; + } else { + logMasterDirName = tmp; + } + + if (const char *tmp = std::getenv("CAPIO_LOGGER_FILE_PREFIX"); tmp == nullptr) { + logfilePrefix = CAPIO_SERVER_DEFAULT_LOG_FILE_PREFIX; + } else { + logfilePrefix = tmp; + } + } + + void openLogFile() { + if (this->logfile.is_open()) { + return; + } + + char hostname[HOST_NAME_MAX]; + gethostname(hostname, HOST_NAME_MAX); + + const std::filesystem::path outputFolder{logMasterDirName + "/server/" + hostname}; + std::filesystem::create_directories(outputFolder); + + const std::filesystem::path logfileName = outputFolder.string() + "/" + logfilePrefix + + std::to_string(capio_syscall(SYS_gettid)) + + ".log"; + + logfile.open(logfileName, std::ofstream::out); + this->logFileName = logfileName; + } + + void write(const char * /*invoker*/, const char * /*file*/, unsigned int /*line*/, + long int /*tid*/, const char *buf, size_t /*len*/) { + writeToStream(buf); + } + + void writeRaw(const char *buf, size_t /*len*/) { writeToStream(buf); } + + static void writeSyscallEnd() {} + + static bool isServerInvoker(const char *invoker, const char *message) { + return strcmp(invoker, "capio_server") == 0 && + (strcmp(CAPIO_LOG_SERVER_REQUEST_START, message) == 0 || + strcmp(CAPIO_LOG_SERVER_REQUEST_END, message) == 0); + } + + const std::string &getLogFileName() { return logFileName; } +}; + +using Logger = TemplateLogger; + +#endif // CAPIO_SERVERLOGGER_HPP diff --git a/capio/server/include/utils/cli_parser.hpp b/capio/server/include/utils/cli_parser.hpp index be588b994..73022d203 100644 --- a/capio/server/include/utils/cli_parser.hpp +++ b/capio/server/include/utils/cli_parser.hpp @@ -1,6 +1,7 @@ #ifndef CAPIO_CLI_PARSER_HPP #define CAPIO_CLI_PARSER_HPP #include +#include "utils/ServerLogger.hpp" struct CapioParsedConfig { std::string backend_name; diff --git a/capio/server/include/utils/common.hpp b/capio/server/include/utils/common.hpp index a0f90cdbb..95a9ca467 100644 --- a/capio/server/include/utils/common.hpp +++ b/capio/server/include/utils/common.hpp @@ -10,6 +10,7 @@ #include "common/dirent.hpp" #include "storage/capio_file.hpp" #include "storage/manager.hpp" +#include "utils/ServerLogger.hpp" extern ClientManager *client_manager; extern StorageManager *storage_manager; diff --git a/capio/server/include/utils/env.hpp b/capio/server/include/utils/env.hpp index ca41cb36d..1b0fa7af7 100644 --- a/capio/server/include/utils/env.hpp +++ b/capio/server/include/utils/env.hpp @@ -4,6 +4,7 @@ #include #include "common/constants.hpp" +#include "utils/ServerLogger.hpp" off64_t get_file_initial_size() { START_LOG(gettid(), "call()"); diff --git a/capio/server/include/utils/location.hpp b/capio/server/include/utils/location.hpp index 3a14af685..522321b77 100644 --- a/capio/server/include/utils/location.hpp +++ b/capio/server/include/utils/location.hpp @@ -1,11 +1,11 @@ #ifndef CAPIO_SERVER_UTILS_LOCATIONS_HPP #define CAPIO_SERVER_UTILS_LOCATIONS_HPP - -#include "remote/backend.hpp" - #include #include +#include "remote/backend.hpp" + +#include "utils/ServerLogger.hpp" #include "utils/types.hpp" extern Backend *backend; diff --git a/capio/server/include/utils/signals.hpp b/capio/server/include/utils/signals.hpp index 94660c0a1..1027ac4f2 100644 --- a/capio/server/include/utils/signals.hpp +++ b/capio/server/include/utils/signals.hpp @@ -5,6 +5,7 @@ #include "remote/backend.hpp" #include "server_println.hpp" +#include "utils/ServerLogger.hpp" #ifdef CAPIO_COVERAGE extern "C" void __gcov_dump(void); diff --git a/capio/server/src/backend.cpp b/capio/server/src/backend.cpp index 269893eae..f6da19b0a 100644 --- a/capio/server/src/backend.cpp +++ b/capio/server/src/backend.cpp @@ -1,5 +1,6 @@ #include "remote/backend.hpp" +#include "utils/ServerLogger.hpp" #include "utils/common.hpp" #include "utils/server_println.hpp" diff --git a/capio/server/src/cli_parser.cpp b/capio/server/src/cli_parser.cpp index a4f55cfa8..50f2b9693 100644 --- a/capio/server/src/cli_parser.cpp +++ b/capio/server/src/cli_parser.cpp @@ -9,7 +9,6 @@ CapioParsedConfig parseCLI(int argc, char **argv) { CapioParsedConfig capio_config; - Logger *log; args::ArgumentParser parser(CAPIO_SERVER_ARG_PARSER_PRE, CAPIO_SERVER_ARG_PARSER_EPILOGUE); parser.LongSeparator(" "); @@ -18,10 +17,6 @@ CapioParsedConfig parseCLI(int argc, char **argv) { args::Group arguments(parser, "Arguments"); args::HelpFlag help(arguments, "help", "Display this help menu", {'h', "help"}); - args::ValueFlag logfile_src(arguments, "filename", - CAPIO_SERVER_ARG_PARSER_LOGILE_OPT_HELP, {'l', "log"}); - args::ValueFlag logfile_folder( - arguments, "filename", CAPIO_SERVER_ARG_PARSER_LOGILE_DIR_OPT_HELP, {'d', "log-dir"}); args::ValueFlag resolve_prefix(arguments, "resolve-prefix", CAPIO_SERVER_ARG_PARSER_RESOLVE_PREFIX_OPT_HELP, {'r', "resolve-prefix"}); @@ -69,33 +64,9 @@ CapioParsedConfig parseCLI(int argc, char **argv) { #endif } - if (logfile_folder) { #ifdef CAPIO_LOG - log_master_dir_name = args::get(logfile_folder); -#else - server_println("Capio logfile folder, but logging capabilities not compiled into capio!", - get_capio_workflow_name(), CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, "parseCLI"); -#endif - } - - if (logfile_src) { -#ifdef CAPIO_LOG - // log file was given - std::string token = args::get(logfile_src); - if (token.find(".log") != std::string::npos) { - token.erase(token.length() - 4); // delete .log if for some reason - // is given as parameter - } - logfile_prefix = token; -#else - server_println("Capio logfile provided, but logging capabilities not compiled into capio!", - get_capio_workflow_name(), CAPIO_LOG_SERVER_CLI_LEVEL_WARNING, "parseCLI"); -#endif - } -#ifdef CAPIO_LOG - auto logname = open_server_logfile(); - log = new Logger(__func__, __FILE__, __LINE__, gettid(), "Created new log file"); - server_println("started logging to logfile " + logname.string(), get_capio_workflow_name(), + auto log = new Logger(__func__, __FILE__, __LINE__, gettid(), "Created new log file"); + server_println("started logging to logfile " + log->getLogFileName(), get_capio_workflow_name(), CAPIO_LOG_SERVER_CLI_LEVEL_INFO, "parseCLI"); #endif diff --git a/capio/server/src/client_manager.cpp b/capio/server/src/client_manager.cpp index f8000c9a7..296180d6c 100644 --- a/capio/server/src/client_manager.cpp +++ b/capio/server/src/client_manager.cpp @@ -1,10 +1,10 @@ #include -#include "utils/capiocl_adapter.hpp" - #include "client-manager/client_manager.hpp" + #include "common/constants.hpp" #include "common/queue.hpp" +#include "utils/ServerLogger.hpp" #include "utils/capiocl_adapter.hpp" #include "utils/common.hpp" #include "utils/server_println.hpp" diff --git a/capio/server/src/mpi_backend.cpp b/capio/server/src/mpi_backend.cpp index ead84a42c..9c73994f5 100644 --- a/capio/server/src/mpi_backend.cpp +++ b/capio/server/src/mpi_backend.cpp @@ -1,4 +1,6 @@ #include "remote/backend/mpi.hpp" + +#include "utils/ServerLogger.hpp" #include "utils/capiocl_adapter.hpp" #include "utils/server_println.hpp" diff --git a/capio/server/src/none_backend.cpp b/capio/server/src/none_backend.cpp index e0e8e3208..a5c90bf55 100644 --- a/capio/server/src/none_backend.cpp +++ b/capio/server/src/none_backend.cpp @@ -1,6 +1,8 @@ #include #include "remote/backend/none.hpp" + +#include "utils/ServerLogger.hpp" #include "utils/capiocl_adapter.hpp" #include "utils/server_println.hpp" diff --git a/capio/server/src/remote_request.cpp b/capio/server/src/remote_request.cpp index a15bab108..dce981e91 100644 --- a/capio/server/src/remote_request.cpp +++ b/capio/server/src/remote_request.cpp @@ -1,5 +1,7 @@ #include "remote/backend.hpp" +#include "utils/ServerLogger.hpp" + RemoteRequest::RemoteRequest(char *buf_recv, const std::string &source) : _source(source) { START_LOG(gettid(), "call(buf_recv=%s, source=%s)", buf_recv, source.c_str()); int code; diff --git a/capio/server/src/storage_manager.cpp b/capio/server/src/storage_manager.cpp index 4b866bd27..b5f5c01d5 100644 --- a/capio/server/src/storage_manager.cpp +++ b/capio/server/src/storage_manager.cpp @@ -3,11 +3,12 @@ #include #include +#include "storage/manager.hpp" + #include "common/dirent.hpp" #include "common/filesystem.hpp" -#include "common/logger.hpp" #include "storage/capio_file.hpp" -#include "storage/manager.hpp" +#include "utils/ServerLogger.hpp" #include "utils/capiocl_adapter.hpp" #include "utils/common.hpp" #include "utils/location.hpp" From e60358af811adb43076be9650a67d7cc92dfdbbb Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 19 May 2026 11:14:10 +0200 Subject: [PATCH 02/16] Moved POSIX to new logger infrastructure --- capio/posix/handlers/exit_group.hpp | 2 - capio/posix/utils/cache.hpp | 188 ++++++++++++++++++++++++ capio/posix/utils/clone.hpp | 1 + capio/posix/utils/common.hpp | 5 +- capio/posix/utils/env.hpp | 3 - capio/posix/utils/filesystem.hpp | 2 +- capio/posix/utils/requests.hpp | 1 + capio/posix/utils/snapshot.hpp | 3 +- capio/tests/unit/posix/src/realpath.cpp | 2 + 9 files changed, 197 insertions(+), 10 deletions(-) create mode 100644 capio/posix/utils/cache.hpp diff --git a/capio/posix/handlers/exit_group.hpp b/capio/posix/handlers/exit_group.hpp index 6c4acb454..498622dc0 100644 --- a/capio/posix/handlers/exit_group.hpp +++ b/capio/posix/handlers/exit_group.hpp @@ -3,8 +3,6 @@ #if defined(SYS_exit) || defined(SYS_exit_group) -#include "common/logger.hpp" - #include "utils/requests.hpp" /* diff --git a/capio/posix/utils/cache.hpp b/capio/posix/utils/cache.hpp new file mode 100644 index 000000000..7a4f4d0f8 --- /dev/null +++ b/capio/posix/utils/cache.hpp @@ -0,0 +1,188 @@ +#ifndef CAPIO_SERVER_UTILS_CACHE +#define CAPIO_SERVER_UTILS_CACHE + +#include "common/dirent.hpp" +#include "common/queue.hpp" + +#include "requests.hpp" + +class ReadCache { + private: + char *_cache; + long _tid; + int _last_fd; + off64_t _max_line_size, _actual_size, _cache_offset; + SPSCQueue _queue; + + inline void _read(void *buffer, off64_t count) { + START_LOG(capio_syscall(SYS_gettid), "call(count=%ld)", count); + + if (count > 0) { + memcpy(buffer, _cache + _cache_offset, count); + LOG("Read %ld. adding it to _cache_offset of value %ld", count, _cache_offset); + _cache_offset += count; + } + } + + public: + ReadCache(long tid, off64_t lines, off64_t line_size, const std::string &workflow_name) + : _cache(nullptr), _tid(tid), _last_fd(-1), _max_line_size(line_size), _actual_size(0), + _cache_offset(0), + _queue(SHM_SPSC_PREFIX_READ + std::to_string(tid), lines, line_size, workflow_name) {} + + inline void flush() { + START_LOG(capio_syscall(SYS_gettid), "call()"); + + if (_cache_offset != _actual_size) { + _actual_size = _cache_offset = 0; + seek_request(_last_fd, get_capio_fd_offset(_last_fd), _tid); + } + } + + inline off64_t read(int fd, void *buffer, off64_t count, bool is_getdents, bool is64bit) { + START_LOG(capio_syscall(SYS_gettid), "call(fd=%d, count=%ld, is_getdents=%s, is64bit=%s)", + fd, count, is_getdents ? "true" : "false", is64bit ? "true" : "false"); + + if (_last_fd != fd) { + LOG("changed fd from %d to %d: flushing", _last_fd, fd); + flush(); + _last_fd = fd; + } + + off64_t remaining_bytes = _actual_size - _cache_offset; + off64_t file_offset = get_capio_fd_offset(fd); + off64_t bytes_read; + + if (is_getdents) { + auto dirent_size = static_cast(sizeof(linux_dirent64)); + count = (count / dirent_size) * dirent_size; + } + + auto read_size = count - remaining_bytes; + LOG("Read() will need to read %ld bytes", read_size); + + if (count <= remaining_bytes) { + LOG("count %ld <= remaining_bytes %ld", count, remaining_bytes); + _read(buffer, count); + bytes_read = count; + } else { + LOG("count %ld > remaining_bytes %ld", count, remaining_bytes); + _read(buffer, remaining_bytes); + buffer = reinterpret_cast(buffer) + remaining_bytes; + + // NOTE: if getdents send a request for exactly the correct amount of data. + if (read_size > _max_line_size || is_getdents) { + LOG("count - remaining_bytes %ld > _max_line_size %ld", read_size, _max_line_size); + LOG("Reading exactly requested size"); + off64_t end_of_read = is_getdents ? getdents_request(fd, read_size, is64bit, _tid) + : read_request(fd, read_size, _tid); + bytes_read = end_of_read - file_offset; + _queue.read(reinterpret_cast(buffer), bytes_read); + } else { + LOG("count - remaining_bytes %ld <= _max_line_size %ld", read_size, _max_line_size); + LOG("Reading more to use pre fetching and caching"); + off64_t end_of_read = is_getdents + ? getdents_request(fd, _max_line_size, is64bit, _tid) + : read_request(fd, _max_line_size, _tid); + LOG("request return value is %ld", end_of_read); + _actual_size = end_of_read - file_offset - remaining_bytes; + LOG("ReaderCache actual size, after requested read is: %ld bytes", _actual_size); + _cache_offset = 0; + if (_actual_size > 0) { + LOG("Fetching data from shm _queue"); + _cache = _queue.fetch(); + } + if (read_size < _actual_size) { + LOG("count - remaining_bytes %ld < _actual_size %ld", read_size, _actual_size); + _read(buffer, read_size); + bytes_read = count; + } else { + LOG("count - remaining_bytes %ld >= _actual_size %ld", read_size, _actual_size); + _read(buffer, _actual_size); + bytes_read = remaining_bytes + _actual_size; + } + } + } + LOG("%ld bytes have been read. setting fd offset to %ld", bytes_read, + file_offset + bytes_read); + set_capio_fd_offset(fd, file_offset + bytes_read); + return bytes_read; + } +}; + +class WriteCache { + private: + char *_cache; + long _tid; + int _fd; + off64_t _max_line_size, _actual_size; + SPSCQueue _queue; + + inline void _write(off64_t count, const void *buffer) { + START_LOG(capio_syscall(SYS_gettid), "call(count=%ld)", count); + + if (count > 0) { + if (_cache == nullptr) { + _cache = _queue.reserve(); + } + memcpy(_cache + _actual_size, buffer, count); + _actual_size += count; + if (_actual_size == _max_line_size) { + flush(); + } + } + } + + public: + WriteCache(long tid, off64_t lines, off64_t line_size, const std::string &workflow_name) + : _cache(nullptr), _tid(tid), _fd(-1), _max_line_size(line_size), _actual_size(0), + _queue(SHM_SPSC_PREFIX_WRITE + std::to_string(tid), lines, line_size, workflow_name) {} + + inline void flush() { + START_LOG(capio_syscall(SYS_gettid), "call()"); + + if (_actual_size != 0) { + write_request(_fd, _actual_size, _tid); + _cache = nullptr; + _actual_size = 0; + } + } + + inline void write(int fd, const void *buffer, off64_t count) { + START_LOG(capio_syscall(SYS_gettid), "call(fd=%d, buffer=0x%08x, count=%ld)", fd, buffer, + count); + + if (_fd != fd) { + LOG("changed fd from %d to %d: flushing", _fd, fd); + flush(); + _fd = fd; + } + + if (count <= _max_line_size - _actual_size) { + LOG("count %ld <= _max_line_size - _actual_size %ld", count, + _max_line_size - _actual_size); + _write(count, buffer); + } else { + LOG("count %ld > _max_line_size - _actual_size %ld", count, + _max_line_size - _actual_size); + flush(); + if (count - _actual_size > _max_line_size) { + LOG("count - _actual_size %ld > _max_line_size %ld", count - _actual_size, + _max_line_size); + write_request(_fd, count, _tid); + _queue.write(reinterpret_cast(buffer), count); + } else { + LOG("count - _actual_size %ld <= _max_line_size %ld", count - _actual_size, + _max_line_size); + _write(count, buffer); + } + } + + set_capio_fd_offset(fd, get_capio_fd_offset(fd) + count); + } +}; + +inline thread_local WriteCache *write_cache; +inline thread_local ReadCache *read_cache; + +#endif // CAPIO_SERVER_UTILS_CACHE \ No newline at end of file diff --git a/capio/posix/utils/clone.hpp b/capio/posix/utils/clone.hpp index 54cd24b72..6673a1c24 100644 --- a/capio/posix/utils/clone.hpp +++ b/capio/posix/utils/clone.hpp @@ -4,6 +4,7 @@ #include "common/syscall.hpp" #include "data.hpp" #include "requests.hpp" +#include "utils/PosixLogger.hpp" /** * Initialize the required data structures for the new child thread, and then proceed to execute a diff --git a/capio/posix/utils/common.hpp b/capio/posix/utils/common.hpp index 9727b334f..83c2c27e2 100644 --- a/capio/posix/utils/common.hpp +++ b/capio/posix/utils/common.hpp @@ -1,7 +1,8 @@ -#include - #ifndef CAPIO_FUNCTIONS_H #define CAPIO_FUNCTIONS_H +#include + +#include "utils/PosixLogger.hpp" int posix_return_value(long res, long *result) { START_LOG(capio_syscall(SYS_gettid), "cal(res=%ld)", res); diff --git a/capio/posix/utils/env.hpp b/capio/posix/utils/env.hpp index c43f56fcb..0893ef500 100644 --- a/capio/posix/utils/env.hpp +++ b/capio/posix/utils/env.hpp @@ -2,9 +2,6 @@ #define CAPIO_POSIX_UTILS_ENV_HPP #include -#include - -#include "common/logger.hpp" inline const char *get_capio_app_name() { static char *capio_app_name = std::getenv("CAPIO_APP_NAME"); diff --git a/capio/posix/utils/filesystem.hpp b/capio/posix/utils/filesystem.hpp index 6ba6921e8..fdbde2e4a 100644 --- a/capio/posix/utils/filesystem.hpp +++ b/capio/posix/utils/filesystem.hpp @@ -12,8 +12,8 @@ #include "common/env.hpp" #include "common/filesystem.hpp" -#include "common/logger.hpp" #include "common/syscall.hpp" +#include "utils/PosixLogger.hpp" #include "types.hpp" diff --git a/capio/posix/utils/requests.hpp b/capio/posix/utils/requests.hpp index 4867e6117..c41dabce7 100644 --- a/capio/posix/utils/requests.hpp +++ b/capio/posix/utils/requests.hpp @@ -6,6 +6,7 @@ #include "env.hpp" #include "filesystem.hpp" #include "types.hpp" +#include "utils/PosixLogger.hpp" inline thread_local CircularBuffer *buf_requests; inline thread_local CircularBuffer *buff_response; diff --git a/capio/posix/utils/snapshot.hpp b/capio/posix/utils/snapshot.hpp index 55a85553b..016481032 100644 --- a/capio/posix/utils/snapshot.hpp +++ b/capio/posix/utils/snapshot.hpp @@ -5,9 +5,8 @@ #include #include -#include "common/logger.hpp" - #include "types.hpp" +#include "utils/PosixLogger.hpp" inline int *get_fd_snapshot(long tid) { return static_cast(get_shm_if_exist("capio_snapshot_" + std::to_string(tid))); diff --git a/capio/tests/unit/posix/src/realpath.cpp b/capio/tests/unit/posix/src/realpath.cpp index cfa38e8ae..11a17b55b 100644 --- a/capio/tests/unit/posix/src/realpath.cpp +++ b/capio/tests/unit/posix/src/realpath.cpp @@ -4,6 +4,8 @@ #include +#include "posix/utils/PosixLogger.hpp" + #include "utils/filesystem.hpp" class RealpathPosixTest : public testing::Test { From e240a7f0d1a0c9c931beb665df11c6001e08b253 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 19 May 2026 14:02:37 +0200 Subject: [PATCH 03/16] Fixed segfaults --- capio/common/logger.hpp | 53 ++++++++----------- capio/posix/libcapio_posix.cpp | 2 +- capio/posix/utils/PosixLogger.hpp | 56 ++++++++++++++------- capio/server/capio_server.cpp | 1 + capio/server/include/utils/ServerLogger.hpp | 32 ++++++------ 5 files changed, 78 insertions(+), 66 deletions(-) diff --git a/capio/common/logger.hpp b/capio/common/logger.hpp index 4616c44cb..dcd6c0083 100644 --- a/capio/common/logger.hpp +++ b/capio/common/logger.hpp @@ -45,7 +45,7 @@ inline thread_local int current_log_level = 0; // this variable tells the logger that syscall logging // has started, and we are not in setup phase // FIXME: Remove the inline specifier by splitting into header and source code -inline thread_local bool logging_syscall = false; +inline thread_local bool enable_logger = false; #ifndef CAPIO_MAX_LOG_LEVEL // capio max log level. defaults to -1, where everything is logged #define CAPIO_MAX_LOG_LEVEL -1 @@ -71,8 +71,8 @@ inline long long current_time_in_millis() { */ class SyscallLoggingSuspender { public: - SyscallLoggingSuspender() { logging_syscall = false; } - ~SyscallLoggingSuspender() { logging_syscall = true; } + SyscallLoggingSuspender() { enable_logger = false; } + ~SyscallLoggingSuspender() { enable_logger = true; } }; /** @@ -98,42 +98,27 @@ template class TemplateLogger { TemplateLogger(const char invoker[], const char file[], unsigned int line, long int tid, const char *message, ...) { - adapter.openLogFile(); - this->tid = tid; this->line = line; strncpy(this->invoker, invoker, sizeof(this->invoker)); strncpy(this->file, file, sizeof(this->file)); va_list argp, argpc; - - sprintf(format, CAPIO_LOG_PRE_MSG, current_time_in_millis(), this->invoker); - const size_t pre_msg_len = strlen(format); - strcpy(format + pre_msg_len, message); - va_start(argp, message); va_copy(argpc, argp); -#if defined(CAPIO_LOG) && defined(__CAPIO_POSIX) - if (current_log_level == 0 && logging_syscall) { - int syscallNumber; - if (strcmp(invoker, "hook_clone_child") == 0) { - // Explicitly propagate SYS_clone to child thread after clone - // to avoid spurious unknown syscall logs - syscallNumber = SYS_clone; - } else { - syscallNumber = va_arg(argp, int); - } - - auto buf1 = reinterpret_cast(capio_syscall( - SYS_mmap, nullptr, 50, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); - sprintf(buf1, CAPIO_LOG_POSIX_SYSCALL_START, sys_num_to_string(syscallNumber).c_str(), - syscallNumber); - adapter.writeRaw(buf1, strlen(buf1)); - capio_syscall(SYS_munmap, buf1, 50); + adapter.openLogFile(); + +#ifdef __CAPIO_POSIX + if (!enable_logger) { + return; } #endif + sprintf(format, CAPIO_LOG_PRE_MSG, current_time_in_millis(), this->invoker); + const size_t pre_msg_len = strlen(format); + strcpy(format + pre_msg_len, message); + const int size = vsnprintf(nullptr, 0U, format, argp); auto buf = reinterpret_cast(capio_syscall(SYS_mmap, nullptr, size + 1, PROT_READ | PROT_WRITE, @@ -158,20 +143,24 @@ template class TemplateLogger { adapter.writeRaw(format, strlen(format)); - if (current_log_level == 0 && logging_syscall) { + if (current_log_level == 0 && enable_logger) { adapter.writeSyscallEnd(); } } void log(const char *message, ...) { +#ifdef __CAPIO_POSIX + if (!enable_logger) { + return; + } +#endif va_list argp, argpc; sprintf(format, CAPIO_LOG_PRE_MSG, current_time_in_millis(), this->invoker); const size_t pre_msg_len = strlen(format); strcpy(format + pre_msg_len, message); - // Delegate the server request start/end special case to the adapter - if (adapter.isServerInvoker(this->invoker, message)) { + if (adapter.isSTLSafe()) { adapter.writeRaw(format, strlen(format)); return; } @@ -210,7 +199,7 @@ template class TemplateLogger { #define LOG(message, ...) log.log(message, ##__VA_ARGS__) #define START_LOG(tid, message, ...) \ Logger log(__func__, __FILE__, __LINE__, tid, message, ##__VA_ARGS__) -#define START_SYSCALL_LOGGING() logging_syscall = true +#define START_SYSCALL_LOGGING() enable_logger = true #define SUSPEND_SYSCALL_LOGGING() SyscallLoggingSuspender sls{}; /** @@ -257,6 +246,8 @@ template class TemplateLogger { __SHM_CHECK_CLI_MSG; \ } #define DBG(tid, lambda) +#define START_SYSCALL_LOGGING() +#define SUSPEND_SYSCALL_LOGGING() #endif diff --git a/capio/posix/libcapio_posix.cpp b/capio/posix/libcapio_posix.cpp index d6bf64396..0a63fc1c8 100644 --- a/capio/posix/libcapio_posix.cpp +++ b/capio/posix/libcapio_posix.cpp @@ -411,4 +411,4 @@ static __attribute__((constructor)) void init() { intercept_hook_point_clone_parent = hook_clone_parent; intercept_hook_point = hook; START_SYSCALL_LOGGING(); -} +} \ No newline at end of file diff --git a/capio/posix/utils/PosixLogger.hpp b/capio/posix/utils/PosixLogger.hpp index d3ea59f03..cc4b49788 100644 --- a/capio/posix/utils/PosixLogger.hpp +++ b/capio/posix/utils/PosixLogger.hpp @@ -3,12 +3,24 @@ #include "common/logger.hpp" - struct PosixLogWriteAdapter { private: - bool fileOpen{false}; - int fileFD{-1}; - char filePath[PATH_MAX]{'\0'}; + // These three fields MUST be thread_local static rather than instance + // members. The adapter is constructed inside Logger, which is a stack + // variable instantiated at the first intercepted syscall — potentially + // before the C++ runtime has finished setting up TLS for the new thread + // (dl_init fires before __cxa_thread_atexit is live). The linker + // pre-allocates thread_local storage in the TLS block for every thread + // before any user code runs, so reading/writing these is always safe, + // even at the earliest possible call site. + static thread_local bool fileOpen; + static thread_local int fileFD; + static thread_local char filePath[PATH_MAX]; + + // ---- path helpers ------------------------------------------------------ + // Kept as static methods so they have no dependency on 'this' and their + // internal statics are initialised lazily on first call from a stable + // context, not during struct construction. static const char *getHostname() { static char hostname[HOST_NAME_MAX]{'\0'}; @@ -62,7 +74,7 @@ struct PosixLogWriteAdapter { return dir; } - void setupLogFilename() { + static void setupLogFilename() { if (filePath[0] == '\0') { sprintf(filePath, "%s/%s%ld.log", getHostLogDir(), getLogPrefix(), capio_syscall(SYS_gettid)); @@ -71,15 +83,18 @@ struct PosixLogWriteAdapter { // ---- write helper ------------------------------------------------------ - void writeToFD(const char *buf, size_t len) const { + static void writeToFD(const char *buf, const size_t len) { + if (!fileOpen) { + return; + } capio_syscall(SYS_write, fileFD, buf, len); capio_syscall(SYS_write, fileFD, "\n", 1); } public: - [[nodiscard]] bool isFileOpened() const { return fileOpen; } + [[nodiscard]] static bool isFileOpened() { return fileOpen; } - void openLogFile() { + static void openLogFile() { setupLogFilename(); current_log_level = 0; // reset log level after clone, avoiding propagation to child threads @@ -87,7 +102,8 @@ struct PosixLogWriteAdapter { capio_syscall(SYS_mkdirat, AT_FDCWD, getPosixLogDir(), 0755); capio_syscall(SYS_mkdirat, AT_FDCWD, getHostLogDir(), 0755); - fileFD = capio_syscall(SYS_openat, AT_FDCWD, filePath, O_CREAT | O_WRONLY | O_TRUNC, 0644); + fileFD = capio_syscall(SYS_openat, AT_FDCWD, filePath, + O_CREAT | O_WRONLY | O_APPEND, 0644); if (fileFD == -1) { capio_syscall(SYS_write, fileno(stdout), @@ -101,28 +117,34 @@ struct PosixLogWriteAdapter { fileOpen = true; } - void write(const char * /*invoker*/, const char * /*file*/, unsigned int /*line*/, - long int /*tid*/, const char *buf, size_t len) const { + static void write(const char * /*invoker*/, const char * /*file*/, unsigned int /*line*/, + long int /*tid*/, const char *buf, size_t len) { if (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0) { writeToFD(buf, len); } } - void writeRaw(const char *buf, size_t len) const { + static void writeRaw(const char *buf, size_t len) { if (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0) { writeToFD(buf, len); } } - void writeSyscallEnd() const { + static void writeSyscallEnd() { writeRaw(CAPIO_LOG_POSIX_SYSCALL_END, strlen(CAPIO_LOG_POSIX_SYSCALL_END)); } - static bool isServerInvoker(const char * /*invoker*/, const char * /*message*/) { - return false; - } + static bool isSTLSafe() { return false; } }; +// Definitions of the thread_local static members. +// 'inline' (C++17) ensures a single definition across all translation units +// that include this header, while thread_local gives each thread its own copy +// pre-allocated in the TLS block before any user code runs. +inline thread_local bool PosixLogWriteAdapter::fileOpen{false}; +inline thread_local int PosixLogWriteAdapter::fileFD{-1}; +inline thread_local char PosixLogWriteAdapter::filePath[PATH_MAX]{'\0'}; + using Logger = TemplateLogger; -#endif // CAPIO_POSIXLOGGER_HPP +#endif // CAPIO_POSIXLOGGER_HPP \ No newline at end of file diff --git a/capio/server/capio_server.cpp b/capio/server/capio_server.cpp index 971ae6c5c..739214004 100644 --- a/capio/server/capio_server.cpp +++ b/capio/server/capio_server.cpp @@ -114,6 +114,7 @@ static constexpr std::array build_request_handle } int main(int argc, char **argv) { + START_SYSCALL_LOGGING(); Semaphore internal_server_sem(0); diff --git a/capio/server/include/utils/ServerLogger.hpp b/capio/server/include/utils/ServerLogger.hpp index f4c9d8322..05a4a877c 100644 --- a/capio/server/include/utils/ServerLogger.hpp +++ b/capio/server/include/utils/ServerLogger.hpp @@ -6,11 +6,13 @@ struct ServerLogWriteAdapter { private: std::ofstream logfile; - std::string logMasterDirName; - std::string logfilePrefix; std::string logFileName; void writeToStream(const char *buf) { + if (!logfile.is_open()) { + return; + } + if (current_log_level < CAPIO_LOG_LEVEL || CAPIO_LOG_LEVEL < 0) { logfile << buf << std::endl; logfile.flush(); @@ -18,24 +20,24 @@ struct ServerLogWriteAdapter { } public: - explicit ServerLogWriteAdapter() { - if (const char *tmp = std::getenv("CAPIO_LOGGER_MASTER_DIR_NAME"); tmp == nullptr) { + void openLogFile() { + if (this->logfile.is_open()) { + return; + } + std::string logMasterDirName; + std::string logfilePrefix; + + if (const char *tmp = std::getenv("CAPIO_LOG_DIR"); tmp == nullptr) { logMasterDirName = CAPIO_DEFAULT_LOG_FOLDER; } else { logMasterDirName = tmp; } - if (const char *tmp = std::getenv("CAPIO_LOGGER_FILE_PREFIX"); tmp == nullptr) { + if (const char *tmp = std::getenv("CAPIO_LOG_PREFIX"); tmp == nullptr) { logfilePrefix = CAPIO_SERVER_DEFAULT_LOG_FILE_PREFIX; } else { logfilePrefix = tmp; } - } - - void openLogFile() { - if (this->logfile.is_open()) { - return; - } char hostname[HOST_NAME_MAX]; gethostname(hostname, HOST_NAME_MAX); @@ -47,7 +49,7 @@ struct ServerLogWriteAdapter { std::to_string(capio_syscall(SYS_gettid)) + ".log"; - logfile.open(logfileName, std::ofstream::out); + logfile.open(logfileName, std::ofstream::app); this->logFileName = logfileName; } @@ -60,11 +62,7 @@ struct ServerLogWriteAdapter { static void writeSyscallEnd() {} - static bool isServerInvoker(const char *invoker, const char *message) { - return strcmp(invoker, "capio_server") == 0 && - (strcmp(CAPIO_LOG_SERVER_REQUEST_START, message) == 0 || - strcmp(CAPIO_LOG_SERVER_REQUEST_END, message) == 0); - } + static bool isSTLSafe() { return true; } const std::string &getLogFileName() { return logFileName; } }; From a8555096b77a4739311b23648c547a65df3dbd00 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 19 May 2026 15:05:19 +0200 Subject: [PATCH 04/16] Fixed logger --- capio/common/constants.hpp | 2 +- capio/common/logger.hpp | 40 +++++++++------ capio/posix/libcapio_posix.cpp | 3 +- capio/posix/utils/PosixLogger.hpp | 57 +++++++-------------- capio/server/include/utils/ServerLogger.hpp | 15 +++--- 5 files changed, 52 insertions(+), 65 deletions(-) diff --git a/capio/common/constants.hpp b/capio/common/constants.hpp index 3a230f4bc..e775dfd81 100644 --- a/capio/common/constants.hpp +++ b/capio/common/constants.hpp @@ -68,7 +68,7 @@ constexpr char CAPIO_SHM_OPEN_ERROR[] = // CAPIO logger - POSIX constexpr char CAPIO_LOG_POSIX_DEFAULT_LOG_FILE_PREFIX[] = "posix_thread_\0"; -constexpr char CAPIO_LOG_POSIX_SYSCALL_START[] = "\n+++++++++ SYSCALL %s (%d) +++++++++"; +constexpr char CAPIO_LOG_POSIX_SYSCALL_START[] = "\n+++++++++ START SYSCALL +++++++++"; constexpr char CAPIO_LOG_POSIX_SYSCALL_END[] = "~~~~~~~~~ END SYSCALL ~~~~~~~~~\n"; // CAPIO logger - server diff --git a/capio/common/logger.hpp b/capio/common/logger.hpp index dcd6c0083..b0bbd745a 100644 --- a/capio/common/logger.hpp +++ b/capio/common/logger.hpp @@ -39,9 +39,6 @@ inline void raise_termination(const bool raise_exception, const std::string &mes #include "syscallnames.h" #endif -// FIXME: Remove the inline specifier by splitting into header and source code -inline thread_local int current_log_level = 0; - // this variable tells the logger that syscall logging // has started, and we are not in setup phase // FIXME: Remove the inline specifier by splitting into header and source code @@ -86,6 +83,7 @@ class SyscallLoggingSuspender { * of the old monolithic Logger class for both the server and POSIX builds. */ template class TemplateLogger { + static thread_local int current_log_level; char invoker[256]{0}; char file[256]{0}; char format[CAPIO_LOG_MAX_MSG_LEN]{0}; @@ -97,7 +95,7 @@ template class TemplateLogger { public: TemplateLogger(const char invoker[], const char file[], unsigned int line, long int tid, const char *message, ...) { - + current_log_level++; this->tid = tid; this->line = line; strncpy(this->invoker, invoker, sizeof(this->invoker)); @@ -107,8 +105,6 @@ template class TemplateLogger { va_start(argp, message); va_copy(argpc, argp); - adapter.openLogFile(); - #ifdef __CAPIO_POSIX if (!enable_logger) { return; @@ -124,28 +120,34 @@ template class TemplateLogger { PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); vsnprintf(buf, size + 1, format, argpc); - adapter.write(this->invoker, this->file, this->line, this->tid, buf, strlen(buf)); + + if (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0) { + if (current_log_level == 1) { + adapter.writeOpening(); + } + adapter.write(this->invoker, this->file, this->line, this->tid, buf, strlen(buf)); + } va_end(argp); va_end(argpc); capio_syscall(SYS_munmap, buf, size); - current_log_level++; } TemplateLogger(const TemplateLogger &) = delete; TemplateLogger &operator=(const TemplateLogger &) = delete; ~TemplateLogger() { - current_log_level--; sprintf(format, CAPIO_LOG_PRE_MSG, current_time_in_millis(), this->invoker); const size_t pre_msg_len = strlen(format); strcpy(format + pre_msg_len, "returned"); adapter.writeRaw(format, strlen(format)); - if (current_log_level == 0 && enable_logger) { - adapter.writeSyscallEnd(); + if (current_log_level == 1 && enable_logger && + (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0)) { + adapter.writeEpilogue(); } + current_log_level--; } void log(const char *message, ...) { @@ -160,11 +162,6 @@ template class TemplateLogger { const size_t pre_msg_len = strlen(format); strcpy(format + pre_msg_len, message); - if (adapter.isSTLSafe()) { - adapter.writeRaw(format, strlen(format)); - return; - } - va_start(argp, message); va_copy(argpc, argp); const int size = vsnprintf(nullptr, 0U, format, argp); @@ -172,7 +169,14 @@ template class TemplateLogger { capio_syscall(SYS_mmap, nullptr, size + 1, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); vsnprintf(buf, size + 1, format, argpc); - adapter.write(this->invoker, this->file, this->line, this->tid, buf, strlen(buf)); + + if (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0) { + if (adapter.isSTLSafe()) { + adapter.writeRaw(format, strlen(format)); + } else { + adapter.write(this->invoker, this->file, this->line, this->tid, buf, strlen(buf)); + } + } va_end(argp); va_end(argpc); @@ -182,6 +186,8 @@ template class TemplateLogger { std::string getLogFileName() { return adapter.getLogFileName(); } }; +template inline thread_local int TemplateLogger::current_log_level = 0; + // --------------------------------------------------------------------------- // Macros — identical surface to the old ones; Logger is now a template // --------------------------------------------------------------------------- diff --git a/capio/posix/libcapio_posix.cpp b/capio/posix/libcapio_posix.cpp index 0a63fc1c8..1114155f6 100644 --- a/capio/posix/libcapio_posix.cpp +++ b/capio/posix/libcapio_posix.cpp @@ -353,7 +353,8 @@ static int hook(long syscall_number, long arg0, long arg1, long arg2, long arg3, CAPIO_LOG_LEVEL = get_capio_log_level(); #endif - START_LOG(syscall_no_intercept(SYS_gettid), "call(syscall_number=%ld)", syscall_number); + START_LOG(syscall_no_intercept(SYS_gettid), "call(syscall_number=%ld, syscall_name=%s)", + syscall_number, sys_num_to_string(syscall_number).c_str()); // If the syscall_number is higher than the maximum // syscall captured by CAPIO, simply return diff --git a/capio/posix/utils/PosixLogger.hpp b/capio/posix/utils/PosixLogger.hpp index cc4b49788..a5634f538 100644 --- a/capio/posix/utils/PosixLogger.hpp +++ b/capio/posix/utils/PosixLogger.hpp @@ -5,23 +5,10 @@ struct PosixLogWriteAdapter { private: - // These three fields MUST be thread_local static rather than instance - // members. The adapter is constructed inside Logger, which is a stack - // variable instantiated at the first intercepted syscall — potentially - // before the C++ runtime has finished setting up TLS for the new thread - // (dl_init fires before __cxa_thread_atexit is live). The linker - // pre-allocates thread_local storage in the TLS block for every thread - // before any user code runs, so reading/writing these is always safe, - // even at the earliest possible call site. static thread_local bool fileOpen; - static thread_local int fileFD; + static thread_local int fileFD; static thread_local char filePath[PATH_MAX]; - // ---- path helpers ------------------------------------------------------ - // Kept as static methods so they have no dependency on 'this' and their - // internal statics are initialised lazily on first call from a stable - // context, not during struct construction. - static const char *getHostname() { static char hostname[HOST_NAME_MAX]{'\0'}; if (hostname[0] == '\0') { @@ -74,15 +61,6 @@ struct PosixLogWriteAdapter { return dir; } - static void setupLogFilename() { - if (filePath[0] == '\0') { - sprintf(filePath, "%s/%s%ld.log", getHostLogDir(), getLogPrefix(), - capio_syscall(SYS_gettid)); - } - } - - // ---- write helper ------------------------------------------------------ - static void writeToFD(const char *buf, const size_t len) { if (!fileOpen) { return; @@ -94,16 +72,18 @@ struct PosixLogWriteAdapter { public: [[nodiscard]] static bool isFileOpened() { return fileOpen; } - static void openLogFile() { - setupLogFilename(); - current_log_level = 0; // reset log level after clone, avoiding propagation to child threads + explicit PosixLogWriteAdapter() { + + if (filePath[0] == '\0') { + sprintf(filePath, "%s/%s%ld.log", getHostLogDir(), getLogPrefix(), + capio_syscall(SYS_gettid)); + } capio_syscall(SYS_mkdirat, AT_FDCWD, getLogDir(), 0755); capio_syscall(SYS_mkdirat, AT_FDCWD, getPosixLogDir(), 0755); capio_syscall(SYS_mkdirat, AT_FDCWD, getHostLogDir(), 0755); - fileFD = capio_syscall(SYS_openat, AT_FDCWD, filePath, - O_CREAT | O_WRONLY | O_APPEND, 0644); + fileFD = capio_syscall(SYS_openat, AT_FDCWD, filePath, O_CREAT | O_WRONLY | O_APPEND, 0644); if (fileFD == -1) { capio_syscall(SYS_write, fileno(stdout), @@ -119,22 +99,21 @@ struct PosixLogWriteAdapter { static void write(const char * /*invoker*/, const char * /*file*/, unsigned int /*line*/, long int /*tid*/, const char *buf, size_t len) { - if (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0) { - writeToFD(buf, len); - } + writeToFD(buf, len); } - static void writeRaw(const char *buf, size_t len) { - if (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0) { - writeToFD(buf, len); - } + static void writeRaw(const char *buf, size_t len) { writeToFD(buf, len); } + + static bool isSTLSafe() { return false; } + + static void writeOpening() { + + writeRaw(CAPIO_LOG_POSIX_SYSCALL_START, strlen(CAPIO_LOG_POSIX_SYSCALL_START)); } - static void writeSyscallEnd() { + static void writeEpilogue() { writeRaw(CAPIO_LOG_POSIX_SYSCALL_END, strlen(CAPIO_LOG_POSIX_SYSCALL_END)); } - - static bool isSTLSafe() { return false; } }; // Definitions of the thread_local static members. @@ -142,7 +121,7 @@ struct PosixLogWriteAdapter { // that include this header, while thread_local gives each thread its own copy // pre-allocated in the TLS block before any user code runs. inline thread_local bool PosixLogWriteAdapter::fileOpen{false}; -inline thread_local int PosixLogWriteAdapter::fileFD{-1}; +inline thread_local int PosixLogWriteAdapter::fileFD{-1}; inline thread_local char PosixLogWriteAdapter::filePath[PATH_MAX]{'\0'}; using Logger = TemplateLogger; diff --git a/capio/server/include/utils/ServerLogger.hpp b/capio/server/include/utils/ServerLogger.hpp index 05a4a877c..e6f5363ff 100644 --- a/capio/server/include/utils/ServerLogger.hpp +++ b/capio/server/include/utils/ServerLogger.hpp @@ -13,14 +13,13 @@ struct ServerLogWriteAdapter { return; } - if (current_log_level < CAPIO_LOG_LEVEL || CAPIO_LOG_LEVEL < 0) { - logfile << buf << std::endl; - logfile.flush(); - } + logfile << buf << std::endl; + logfile.flush(); } public: - void openLogFile() { + explicit ServerLogWriteAdapter() { + if (this->logfile.is_open()) { return; } @@ -60,11 +59,13 @@ struct ServerLogWriteAdapter { void writeRaw(const char *buf, size_t /*len*/) { writeToStream(buf); } - static void writeSyscallEnd() {} - static bool isSTLSafe() { return true; } const std::string &getLogFileName() { return logFileName; } + + static void writeOpening() {} + + static void writeEpilogue() {} }; using Logger = TemplateLogger; From 81baa2735678d14a56f190b47a4db72fce358d91 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 19 May 2026 15:23:50 +0200 Subject: [PATCH 05/16] Fixed bug in server unit tests --- capio/tests/unit/server/src/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/capio/tests/unit/server/src/main.cpp b/capio/tests/unit/server/src/main.cpp index 28cb277e4..dc4c24dc1 100644 --- a/capio/tests/unit/server/src/main.cpp +++ b/capio/tests/unit/server/src/main.cpp @@ -3,6 +3,7 @@ #include "capiocl.hpp" #include "capiocl/engine.h" #include "client-manager/client_manager.hpp" +#include "remote/backend/none.hpp" #include "storage/manager.hpp" #include "utils/capiocl_adapter.hpp" #include "utils/location.hpp" @@ -22,12 +23,15 @@ class ServerUnitTestEnvironment : public testing::Environment { capio_cl_engine = new capiocl::engine::Engine(false); client_manager = new ClientManager(); storage_manager = new StorageManager(); + backend = new NoneBackend(0, nullptr); + open_files_location(); } void TearDown() override { delete storage_manager; delete client_manager; delete capio_cl_engine; + delete backend; } }; From 4bb5111ec97a8066dbf0882792042ed937230e58 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 19 May 2026 15:33:12 +0200 Subject: [PATCH 06/16] Fixed unit tests --- capio/server/capio_server.cpp | 1 - capio/tests/unit/server/src/capio_file.cpp | 31 ++-------------------- capio/tests/unit/server/src/main.cpp | 19 ++++++++++++- 3 files changed, 20 insertions(+), 31 deletions(-) diff --git a/capio/server/capio_server.cpp b/capio/server/capio_server.cpp index 739214004..971ae6c5c 100644 --- a/capio/server/capio_server.cpp +++ b/capio/server/capio_server.cpp @@ -114,7 +114,6 @@ static constexpr std::array build_request_handle } int main(int argc, char **argv) { - START_SYSCALL_LOGGING(); Semaphore internal_server_sem(0); diff --git a/capio/tests/unit/server/src/capio_file.cpp b/capio/tests/unit/server/src/capio_file.cpp index db7ead849..3dfc8cb77 100644 --- a/capio/tests/unit/server/src/capio_file.cpp +++ b/capio/tests/unit/server/src/capio_file.cpp @@ -323,34 +323,7 @@ TEST(ServerTest, TestFileSetCommitToFalse) { EXPECT_FALSE(file.isCommitted()); } -class MockBackend : public Backend { - public: - MockBackend() : Backend(HOST_NAME_MAX) {} - - void recv_file(char *shm, const std::string &source, const long int bytes_expected) override { - for (long int i = 0; i < bytes_expected; ++i) { - shm[i] = 33 + (i % 93); - } - } - - const std::set get_nodes() override { return {node_name}; } - void handshake_servers() override {} - RemoteRequest read_next_request() override { return {nullptr, ""}; } - void send_file(char *shm, long int nbytes, const std::string &target) override {} - void send_request(const char *message, int message_len, const std::string &target) override {} -}; - -class MockBackendTestFixture : public ::testing::Test { - protected: - void SetUp() override { - backend = new MockBackend(); - open_files_location(); - } - - void TearDown() override { delete backend; } -}; - -TEST_F(MockBackendTestFixture, TestReadFromNodeMockBackend) { +TEST(ServerTest, TestReadFromNodeMockBackend) { CapioFile file1; file1.createBuffer("testDir", true); @@ -377,7 +350,7 @@ TEST(ServerTest, TestGetSectorEnd) { EXPECT_EQ(file.getSectorEnd(12000), -1); } -TEST_F(MockBackendTestFixture, TestSimulateDirectoryStreaming) { +TEST(ServerTest, TestSimulateDirectoryStreaming) { constexpr int NUM_FILES_EXPECTED = 10; diff --git a/capio/tests/unit/server/src/main.cpp b/capio/tests/unit/server/src/main.cpp index dc4c24dc1..ec4620798 100644 --- a/capio/tests/unit/server/src/main.cpp +++ b/capio/tests/unit/server/src/main.cpp @@ -15,6 +15,23 @@ Backend *backend = nullptr; const capiocl::engine::Engine &CapioCLEngine::get() { return *capio_cl_engine; } +class MockBackend : public Backend { +public: + MockBackend() : Backend(HOST_NAME_MAX) {} + + void recv_file(char *shm, const std::string &source, const long int bytes_expected) override { + for (long int i = 0; i < bytes_expected; ++i) { + shm[i] = 33 + (i % 93); + } + } + + const std::set get_nodes() override { return {node_name}; } + void handshake_servers() override {} + RemoteRequest read_next_request() override { return {nullptr, ""}; } + void send_file(char *shm, long int nbytes, const std::string &target) override {} + void send_request(const char *message, int message_len, const std::string &target) override {} +}; + class ServerUnitTestEnvironment : public testing::Environment { public: explicit ServerUnitTestEnvironment() = default; @@ -23,7 +40,7 @@ class ServerUnitTestEnvironment : public testing::Environment { capio_cl_engine = new capiocl::engine::Engine(false); client_manager = new ClientManager(); storage_manager = new StorageManager(); - backend = new NoneBackend(0, nullptr); + backend = new MockBackend(); open_files_location(); } From 01b74460b6d9cec4329d3c431923dda7cda4be22 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 19 May 2026 16:57:17 +0200 Subject: [PATCH 07/16] Boh --- capio/posix/utils/PosixLogger.hpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/capio/posix/utils/PosixLogger.hpp b/capio/posix/utils/PosixLogger.hpp index a5634f538..e8332c724 100644 --- a/capio/posix/utils/PosixLogger.hpp +++ b/capio/posix/utils/PosixLogger.hpp @@ -2,13 +2,12 @@ #define CAPIO_POSIXLOGGER_HPP #include "common/logger.hpp" +static thread_local bool fileOpen = false; +static thread_local int fileFD = -1; +static thread_local char filePath[PATH_MAX]; struct PosixLogWriteAdapter { private: - static thread_local bool fileOpen; - static thread_local int fileFD; - static thread_local char filePath[PATH_MAX]; - static const char *getHostname() { static char hostname[HOST_NAME_MAX]{'\0'}; if (hostname[0] == '\0') { @@ -120,9 +119,9 @@ struct PosixLogWriteAdapter { // 'inline' (C++17) ensures a single definition across all translation units // that include this header, while thread_local gives each thread its own copy // pre-allocated in the TLS block before any user code runs. -inline thread_local bool PosixLogWriteAdapter::fileOpen{false}; -inline thread_local int PosixLogWriteAdapter::fileFD{-1}; -inline thread_local char PosixLogWriteAdapter::filePath[PATH_MAX]{'\0'}; +// inline thread_local bool PosixLogWriteAdapter::fileOpen{false}; +// inline thread_local int PosixLogWriteAdapter::fileFD{-1}; +// inline thread_local char PosixLogWriteAdapter::filePath[PATH_MAX]{'\0'}; using Logger = TemplateLogger; From de6757a47aa01afbbf727585c26affa12faafc20 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 19 May 2026 17:03:06 +0200 Subject: [PATCH 08/16] Boh --- capio/posix/utils/PosixLogger.hpp | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/capio/posix/utils/PosixLogger.hpp b/capio/posix/utils/PosixLogger.hpp index e8332c724..20d6a6c54 100644 --- a/capio/posix/utils/PosixLogger.hpp +++ b/capio/posix/utils/PosixLogger.hpp @@ -2,9 +2,9 @@ #define CAPIO_POSIXLOGGER_HPP #include "common/logger.hpp" -static thread_local bool fileOpen = false; -static thread_local int fileFD = -1; -static thread_local char filePath[PATH_MAX]; +inline thread_local bool fileOpen = false; +inline thread_local int fileFD = -1; +inline thread_local char filePath[PATH_MAX]; struct PosixLogWriteAdapter { private: @@ -69,15 +69,15 @@ struct PosixLogWriteAdapter { } public: - [[nodiscard]] static bool isFileOpened() { return fileOpen; } - explicit PosixLogWriteAdapter() { - if (filePath[0] == '\0') { - sprintf(filePath, "%s/%s%ld.log", getHostLogDir(), getLogPrefix(), - capio_syscall(SYS_gettid)); + if (fileOpen) { + return; } + sprintf(filePath, "%s/%s%ld.log", getHostLogDir(), getLogPrefix(), + capio_syscall(SYS_gettid)); + capio_syscall(SYS_mkdirat, AT_FDCWD, getLogDir(), 0755); capio_syscall(SYS_mkdirat, AT_FDCWD, getPosixLogDir(), 0755); capio_syscall(SYS_mkdirat, AT_FDCWD, getHostLogDir(), 0755); @@ -115,14 +115,6 @@ struct PosixLogWriteAdapter { } }; -// Definitions of the thread_local static members. -// 'inline' (C++17) ensures a single definition across all translation units -// that include this header, while thread_local gives each thread its own copy -// pre-allocated in the TLS block before any user code runs. -// inline thread_local bool PosixLogWriteAdapter::fileOpen{false}; -// inline thread_local int PosixLogWriteAdapter::fileFD{-1}; -// inline thread_local char PosixLogWriteAdapter::filePath[PATH_MAX]{'\0'}; - using Logger = TemplateLogger; #endif // CAPIO_POSIXLOGGER_HPP \ No newline at end of file From afdb77daf639f888c1c1bf9e2d09eed5c56edb6c Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 19 May 2026 17:18:55 +0200 Subject: [PATCH 09/16] refactor --- capio/common/logger.hpp | 4 ++-- capio/posix/libcapio_posix.cpp | 2 +- capio/posix/utils/clone.hpp | 2 +- capio/posix/utils/common.hpp | 2 +- capio/posix/utils/filesystem.hpp | 2 +- .../utils/{PosixLogger.hpp => posix_logger.hpp} | 12 ++++-------- capio/posix/utils/requests.hpp | 2 +- capio/posix/utils/snapshot.hpp | 2 +- capio/tests/unit/posix/src/realpath.cpp | 2 +- 9 files changed, 13 insertions(+), 17 deletions(-) rename capio/posix/utils/{PosixLogger.hpp => posix_logger.hpp} (90%) diff --git a/capio/common/logger.hpp b/capio/common/logger.hpp index b0bbd745a..34c16e29a 100644 --- a/capio/common/logger.hpp +++ b/capio/common/logger.hpp @@ -141,7 +141,7 @@ template class TemplateLogger { const size_t pre_msg_len = strlen(format); strcpy(format + pre_msg_len, "returned"); - adapter.writeRaw(format, strlen(format)); + adapter.write(format, strlen(format)); if (current_log_level == 1 && enable_logger && (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0)) { @@ -172,7 +172,7 @@ template class TemplateLogger { if (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0) { if (adapter.isSTLSafe()) { - adapter.writeRaw(format, strlen(format)); + adapter.write(format, strlen(format)); } else { adapter.write(this->invoker, this->file, this->line, this->tid, buf, strlen(buf)); } diff --git a/capio/posix/libcapio_posix.cpp b/capio/posix/libcapio_posix.cpp index 1114155f6..67121f8c8 100644 --- a/capio/posix/libcapio_posix.cpp +++ b/capio/posix/libcapio_posix.cpp @@ -7,7 +7,7 @@ #include #include -#include "utils/PosixLogger.hpp" +#include "utils/posix_logger.hpp" #include "common/syscall.hpp" diff --git a/capio/posix/utils/clone.hpp b/capio/posix/utils/clone.hpp index 6673a1c24..97bc869bf 100644 --- a/capio/posix/utils/clone.hpp +++ b/capio/posix/utils/clone.hpp @@ -4,7 +4,7 @@ #include "common/syscall.hpp" #include "data.hpp" #include "requests.hpp" -#include "utils/PosixLogger.hpp" +#include "utils/posix_logger.hpp" /** * Initialize the required data structures for the new child thread, and then proceed to execute a diff --git a/capio/posix/utils/common.hpp b/capio/posix/utils/common.hpp index 83c2c27e2..d8abba1e7 100644 --- a/capio/posix/utils/common.hpp +++ b/capio/posix/utils/common.hpp @@ -2,7 +2,7 @@ #define CAPIO_FUNCTIONS_H #include -#include "utils/PosixLogger.hpp" +#include "utils/posix_logger.hpp" int posix_return_value(long res, long *result) { START_LOG(capio_syscall(SYS_gettid), "cal(res=%ld)", res); diff --git a/capio/posix/utils/filesystem.hpp b/capio/posix/utils/filesystem.hpp index fdbde2e4a..99c7ba257 100644 --- a/capio/posix/utils/filesystem.hpp +++ b/capio/posix/utils/filesystem.hpp @@ -13,7 +13,7 @@ #include "common/env.hpp" #include "common/filesystem.hpp" #include "common/syscall.hpp" -#include "utils/PosixLogger.hpp" +#include "utils/posix_logger.hpp" #include "types.hpp" diff --git a/capio/posix/utils/PosixLogger.hpp b/capio/posix/utils/posix_logger.hpp similarity index 90% rename from capio/posix/utils/PosixLogger.hpp rename to capio/posix/utils/posix_logger.hpp index 20d6a6c54..ca4266784 100644 --- a/capio/posix/utils/PosixLogger.hpp +++ b/capio/posix/utils/posix_logger.hpp @@ -4,7 +4,7 @@ #include "common/logger.hpp" inline thread_local bool fileOpen = false; inline thread_local int fileFD = -1; -inline thread_local char filePath[PATH_MAX]; +inline thread_local char filePath[PATH_MAX]{'\0'}; struct PosixLogWriteAdapter { private: @@ -61,9 +61,6 @@ struct PosixLogWriteAdapter { } static void writeToFD(const char *buf, const size_t len) { - if (!fileOpen) { - return; - } capio_syscall(SYS_write, fileFD, buf, len); capio_syscall(SYS_write, fileFD, "\n", 1); } @@ -101,17 +98,16 @@ struct PosixLogWriteAdapter { writeToFD(buf, len); } - static void writeRaw(const char *buf, size_t len) { writeToFD(buf, len); } + static void write(const char *buf, size_t len) { writeToFD(buf, len); } static bool isSTLSafe() { return false; } static void writeOpening() { - - writeRaw(CAPIO_LOG_POSIX_SYSCALL_START, strlen(CAPIO_LOG_POSIX_SYSCALL_START)); + writeToFD(CAPIO_LOG_POSIX_SYSCALL_START, strlen(CAPIO_LOG_POSIX_SYSCALL_START)); } static void writeEpilogue() { - writeRaw(CAPIO_LOG_POSIX_SYSCALL_END, strlen(CAPIO_LOG_POSIX_SYSCALL_END)); + writeToFD(CAPIO_LOG_POSIX_SYSCALL_END, strlen(CAPIO_LOG_POSIX_SYSCALL_END)); } }; diff --git a/capio/posix/utils/requests.hpp b/capio/posix/utils/requests.hpp index c41dabce7..da04be22c 100644 --- a/capio/posix/utils/requests.hpp +++ b/capio/posix/utils/requests.hpp @@ -6,7 +6,7 @@ #include "env.hpp" #include "filesystem.hpp" #include "types.hpp" -#include "utils/PosixLogger.hpp" +#include "utils/posix_logger.hpp" inline thread_local CircularBuffer *buf_requests; inline thread_local CircularBuffer *buff_response; diff --git a/capio/posix/utils/snapshot.hpp b/capio/posix/utils/snapshot.hpp index 016481032..1f06142ba 100644 --- a/capio/posix/utils/snapshot.hpp +++ b/capio/posix/utils/snapshot.hpp @@ -6,7 +6,7 @@ #include #include "types.hpp" -#include "utils/PosixLogger.hpp" +#include "utils/posix_logger.hpp" inline int *get_fd_snapshot(long tid) { return static_cast(get_shm_if_exist("capio_snapshot_" + std::to_string(tid))); diff --git a/capio/tests/unit/posix/src/realpath.cpp b/capio/tests/unit/posix/src/realpath.cpp index 11a17b55b..004f9e62c 100644 --- a/capio/tests/unit/posix/src/realpath.cpp +++ b/capio/tests/unit/posix/src/realpath.cpp @@ -4,7 +4,7 @@ #include -#include "posix/utils/PosixLogger.hpp" +#include "posix/utils/posix_logger.hpp" #include "utils/filesystem.hpp" From 3b6309b99914da8d265d45b7b4778375b4c9ba0f Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 19 May 2026 17:21:37 +0200 Subject: [PATCH 10/16] boh --- capio/common/logger.hpp | 4 ++-- capio/posix/utils/posix_logger.hpp | 13 +++++++++---- capio/server/include/utils/ServerLogger.hpp | 4 ++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/capio/common/logger.hpp b/capio/common/logger.hpp index 34c16e29a..2f250d9a0 100644 --- a/capio/common/logger.hpp +++ b/capio/common/logger.hpp @@ -125,7 +125,7 @@ template class TemplateLogger { if (current_log_level == 1) { adapter.writeOpening(); } - adapter.write(this->invoker, this->file, this->line, this->tid, buf, strlen(buf)); + adapter.writeFormatted(this->invoker, this->file, this->line, this->tid, buf, strlen(buf)); } va_end(argp); @@ -174,7 +174,7 @@ template class TemplateLogger { if (adapter.isSTLSafe()) { adapter.write(format, strlen(format)); } else { - adapter.write(this->invoker, this->file, this->line, this->tid, buf, strlen(buf)); + adapter.writeFormatted(this->invoker, this->file, this->line, this->tid, buf, strlen(buf)); } } diff --git a/capio/posix/utils/posix_logger.hpp b/capio/posix/utils/posix_logger.hpp index ca4266784..657132165 100644 --- a/capio/posix/utils/posix_logger.hpp +++ b/capio/posix/utils/posix_logger.hpp @@ -2,11 +2,12 @@ #define CAPIO_POSIXLOGGER_HPP #include "common/logger.hpp" -inline thread_local bool fileOpen = false; -inline thread_local int fileFD = -1; -inline thread_local char filePath[PATH_MAX]{'\0'}; struct PosixLogWriteAdapter { + static thread_local bool fileOpen; + static thread_local int fileFD; + static thread_local char filePath[PATH_MAX]; + private: static const char *getHostname() { static char hostname[HOST_NAME_MAX]{'\0'}; @@ -93,7 +94,7 @@ struct PosixLogWriteAdapter { fileOpen = true; } - static void write(const char * /*invoker*/, const char * /*file*/, unsigned int /*line*/, + static void writeFormatted(const char * /*invoker*/, const char * /*file*/, unsigned int /*line*/, long int /*tid*/, const char *buf, size_t len) { writeToFD(buf, len); } @@ -111,6 +112,10 @@ struct PosixLogWriteAdapter { } }; +thread_local bool PosixLogWriteAdapter::fileOpen = false; +thread_local int PosixLogWriteAdapter::fileFD = -1; +thread_local char PosixLogWriteAdapter::filePath[PATH_MAX] = {'\0'}; + using Logger = TemplateLogger; #endif // CAPIO_POSIXLOGGER_HPP \ No newline at end of file diff --git a/capio/server/include/utils/ServerLogger.hpp b/capio/server/include/utils/ServerLogger.hpp index e6f5363ff..a6f9b761d 100644 --- a/capio/server/include/utils/ServerLogger.hpp +++ b/capio/server/include/utils/ServerLogger.hpp @@ -52,12 +52,12 @@ struct ServerLogWriteAdapter { this->logFileName = logfileName; } - void write(const char * /*invoker*/, const char * /*file*/, unsigned int /*line*/, + void writeFormatted(const char * /*invoker*/, const char * /*file*/, unsigned int /*line*/, long int /*tid*/, const char *buf, size_t /*len*/) { writeToStream(buf); } - void writeRaw(const char *buf, size_t /*len*/) { writeToStream(buf); } + void write(const char *buf, size_t /*len*/) { writeToStream(buf); } static bool isSTLSafe() { return true; } From 3e91607e6bc81732e8de7de8964140e0f0889ce7 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 19 May 2026 17:32:09 +0200 Subject: [PATCH 11/16] refactor --- capio/server/capio_server.cpp | 2 +- capio/server/include/client-manager/client_manager.hpp | 2 +- capio/server/include/remote/handlers/read.hpp | 2 +- capio/server/include/remote/handlers/stat.hpp | 2 +- capio/server/include/storage/capio_file.hpp | 2 +- capio/server/include/utils/cli_parser.hpp | 2 +- capio/server/include/utils/common.hpp | 2 +- capio/server/include/utils/env.hpp | 2 +- capio/server/include/utils/location.hpp | 2 +- .../include/utils/{ServerLogger.hpp => server_logger.hpp} | 0 capio/server/include/utils/signals.hpp | 2 +- capio/server/src/backend.cpp | 2 +- capio/server/src/client_manager.cpp | 2 +- capio/server/src/mpi_backend.cpp | 2 +- capio/server/src/none_backend.cpp | 2 +- capio/server/src/remote_request.cpp | 2 +- capio/server/src/storage_manager.cpp | 2 +- 17 files changed, 16 insertions(+), 16 deletions(-) rename capio/server/include/utils/{ServerLogger.hpp => server_logger.hpp} (100%) diff --git a/capio/server/capio_server.cpp b/capio/server/capio_server.cpp index 971ae6c5c..ef70188d6 100644 --- a/capio/server/capio_server.cpp +++ b/capio/server/capio_server.cpp @@ -17,7 +17,7 @@ #include #include -#include "utils/ServerLogger.hpp" +#include "utils/server_logger.hpp" #include "capiocl.hpp" #include "capiocl/engine.h" diff --git a/capio/server/include/client-manager/client_manager.hpp b/capio/server/include/client-manager/client_manager.hpp index 53af1c9cc..4ea53b70d 100644 --- a/capio/server/include/client-manager/client_manager.hpp +++ b/capio/server/include/client-manager/client_manager.hpp @@ -5,7 +5,7 @@ #include #include -#include "utils/ServerLogger.hpp" +#include "utils/server_logger.hpp" #include "common/queue.hpp" /** diff --git a/capio/server/include/remote/handlers/read.hpp b/capio/server/include/remote/handlers/read.hpp index 19483f756..8c56321b9 100644 --- a/capio/server/include/remote/handlers/read.hpp +++ b/capio/server/include/remote/handlers/read.hpp @@ -4,7 +4,7 @@ #include "remote/backend.hpp" #include "remote/requests.hpp" #include "storage/manager.hpp" -#include "utils/ServerLogger.hpp" +#include "utils/server_logger.hpp" extern StorageManager *storage_manager; diff --git a/capio/server/include/remote/handlers/stat.hpp b/capio/server/include/remote/handlers/stat.hpp index 9ea22e336..28219760c 100644 --- a/capio/server/include/remote/handlers/stat.hpp +++ b/capio/server/include/remote/handlers/stat.hpp @@ -5,7 +5,7 @@ #include "remote/backend.hpp" #include "remote/requests.hpp" #include "storage/manager.hpp" -#include "utils/ServerLogger.hpp" +#include "utils/server_logger.hpp" extern StorageManager *storage_manager; extern ClientManager *client_manager; diff --git a/capio/server/include/storage/capio_file.hpp b/capio/server/include/storage/capio_file.hpp index 5605fbe97..58f3a8afa 100644 --- a/capio/server/include/storage/capio_file.hpp +++ b/capio/server/include/storage/capio_file.hpp @@ -10,7 +10,7 @@ #include #include -#include "utils/ServerLogger.hpp" +#include "utils/server_logger.hpp" #include "common/queue.hpp" diff --git a/capio/server/include/utils/cli_parser.hpp b/capio/server/include/utils/cli_parser.hpp index 73022d203..aec16d35f 100644 --- a/capio/server/include/utils/cli_parser.hpp +++ b/capio/server/include/utils/cli_parser.hpp @@ -1,7 +1,7 @@ #ifndef CAPIO_CLI_PARSER_HPP #define CAPIO_CLI_PARSER_HPP +#include "utils/server_logger.hpp" #include -#include "utils/ServerLogger.hpp" struct CapioParsedConfig { std::string backend_name; diff --git a/capio/server/include/utils/common.hpp b/capio/server/include/utils/common.hpp index 95a9ca467..067507617 100644 --- a/capio/server/include/utils/common.hpp +++ b/capio/server/include/utils/common.hpp @@ -10,7 +10,7 @@ #include "common/dirent.hpp" #include "storage/capio_file.hpp" #include "storage/manager.hpp" -#include "utils/ServerLogger.hpp" +#include "utils/server_logger.hpp" extern ClientManager *client_manager; extern StorageManager *storage_manager; diff --git a/capio/server/include/utils/env.hpp b/capio/server/include/utils/env.hpp index 1b0fa7af7..98a9b3a61 100644 --- a/capio/server/include/utils/env.hpp +++ b/capio/server/include/utils/env.hpp @@ -4,7 +4,7 @@ #include #include "common/constants.hpp" -#include "utils/ServerLogger.hpp" +#include "utils/server_logger.hpp" off64_t get_file_initial_size() { START_LOG(gettid(), "call()"); diff --git a/capio/server/include/utils/location.hpp b/capio/server/include/utils/location.hpp index 522321b77..9bb4bf8df 100644 --- a/capio/server/include/utils/location.hpp +++ b/capio/server/include/utils/location.hpp @@ -5,7 +5,7 @@ #include "remote/backend.hpp" -#include "utils/ServerLogger.hpp" +#include "utils/server_logger.hpp" #include "utils/types.hpp" extern Backend *backend; diff --git a/capio/server/include/utils/ServerLogger.hpp b/capio/server/include/utils/server_logger.hpp similarity index 100% rename from capio/server/include/utils/ServerLogger.hpp rename to capio/server/include/utils/server_logger.hpp diff --git a/capio/server/include/utils/signals.hpp b/capio/server/include/utils/signals.hpp index 1027ac4f2..030924d23 100644 --- a/capio/server/include/utils/signals.hpp +++ b/capio/server/include/utils/signals.hpp @@ -5,7 +5,7 @@ #include "remote/backend.hpp" #include "server_println.hpp" -#include "utils/ServerLogger.hpp" +#include "utils/server_logger.hpp" #ifdef CAPIO_COVERAGE extern "C" void __gcov_dump(void); diff --git a/capio/server/src/backend.cpp b/capio/server/src/backend.cpp index f6da19b0a..96f69a0cf 100644 --- a/capio/server/src/backend.cpp +++ b/capio/server/src/backend.cpp @@ -1,7 +1,7 @@ #include "remote/backend.hpp" -#include "utils/ServerLogger.hpp" #include "utils/common.hpp" +#include "utils/server_logger.hpp" #include "utils/server_println.hpp" #include diff --git a/capio/server/src/client_manager.cpp b/capio/server/src/client_manager.cpp index 296180d6c..3548f1a21 100644 --- a/capio/server/src/client_manager.cpp +++ b/capio/server/src/client_manager.cpp @@ -4,9 +4,9 @@ #include "common/constants.hpp" #include "common/queue.hpp" -#include "utils/ServerLogger.hpp" #include "utils/capiocl_adapter.hpp" #include "utils/common.hpp" +#include "utils/server_logger.hpp" #include "utils/server_println.hpp" ClientManager::ClientDataBuffers::ClientDataBuffers(const std::string &clientToServerName, diff --git a/capio/server/src/mpi_backend.cpp b/capio/server/src/mpi_backend.cpp index 9c73994f5..57093f1ce 100644 --- a/capio/server/src/mpi_backend.cpp +++ b/capio/server/src/mpi_backend.cpp @@ -1,7 +1,7 @@ #include "remote/backend/mpi.hpp" -#include "utils/ServerLogger.hpp" #include "utils/capiocl_adapter.hpp" +#include "utils/server_logger.hpp" #include "utils/server_println.hpp" MPIBackend::MPIBackend(int argc, char **argv) : Backend(MPI_MAX_PROCESSOR_NAME) { diff --git a/capio/server/src/none_backend.cpp b/capio/server/src/none_backend.cpp index a5c90bf55..5f6327584 100644 --- a/capio/server/src/none_backend.cpp +++ b/capio/server/src/none_backend.cpp @@ -2,8 +2,8 @@ #include "remote/backend/none.hpp" -#include "utils/ServerLogger.hpp" #include "utils/capiocl_adapter.hpp" +#include "utils/server_logger.hpp" #include "utils/server_println.hpp" NoneBackend::NoneBackend(int argc, char **argv) : Backend(HOST_NAME_MAX) { diff --git a/capio/server/src/remote_request.cpp b/capio/server/src/remote_request.cpp index dce981e91..60bab8db5 100644 --- a/capio/server/src/remote_request.cpp +++ b/capio/server/src/remote_request.cpp @@ -1,6 +1,6 @@ #include "remote/backend.hpp" -#include "utils/ServerLogger.hpp" +#include "utils/server_logger.hpp" RemoteRequest::RemoteRequest(char *buf_recv, const std::string &source) : _source(source) { START_LOG(gettid(), "call(buf_recv=%s, source=%s)", buf_recv, source.c_str()); diff --git a/capio/server/src/storage_manager.cpp b/capio/server/src/storage_manager.cpp index b5f5c01d5..13f7517eb 100644 --- a/capio/server/src/storage_manager.cpp +++ b/capio/server/src/storage_manager.cpp @@ -8,10 +8,10 @@ #include "common/dirent.hpp" #include "common/filesystem.hpp" #include "storage/capio_file.hpp" -#include "utils/ServerLogger.hpp" #include "utils/capiocl_adapter.hpp" #include "utils/common.hpp" #include "utils/location.hpp" +#include "utils/server_logger.hpp" #include "utils/shared_mutex.hpp" #include "utils/types.hpp" From c60b8beeac75db44d3357ef1cd52e0b281fee746 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 19 May 2026 17:48:27 +0200 Subject: [PATCH 12/16] cleanup --- capio/common/logger.hpp | 11 ++--------- capio/posix/utils/posix_logger.hpp | 9 +-------- capio/server/include/utils/server_logger.hpp | 7 ------- 3 files changed, 3 insertions(+), 24 deletions(-) diff --git a/capio/common/logger.hpp b/capio/common/logger.hpp index 2f250d9a0..1255feccc 100644 --- a/capio/common/logger.hpp +++ b/capio/common/logger.hpp @@ -125,7 +125,7 @@ template class TemplateLogger { if (current_log_level == 1) { adapter.writeOpening(); } - adapter.writeFormatted(this->invoker, this->file, this->line, this->tid, buf, strlen(buf)); + adapter.write(buf, strlen(buf)); } va_end(argp); @@ -171,11 +171,7 @@ template class TemplateLogger { vsnprintf(buf, size + 1, format, argpc); if (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0) { - if (adapter.isSTLSafe()) { - adapter.write(format, strlen(format)); - } else { - adapter.writeFormatted(this->invoker, this->file, this->line, this->tid, buf, strlen(buf)); - } + adapter.write(buf, strlen(buf)); } va_end(argp); @@ -188,9 +184,6 @@ template class TemplateLogger { template inline thread_local int TemplateLogger::current_log_level = 0; -// --------------------------------------------------------------------------- -// Macros — identical surface to the old ones; Logger is now a template -// --------------------------------------------------------------------------- #ifdef CAPIO_LOG #define ERR_EXIT_EXCEPT_CHOICE(raise_exception, message, ...) \ diff --git a/capio/posix/utils/posix_logger.hpp b/capio/posix/utils/posix_logger.hpp index 657132165..19eb16635 100644 --- a/capio/posix/utils/posix_logger.hpp +++ b/capio/posix/utils/posix_logger.hpp @@ -94,14 +94,7 @@ struct PosixLogWriteAdapter { fileOpen = true; } - static void writeFormatted(const char * /*invoker*/, const char * /*file*/, unsigned int /*line*/, - long int /*tid*/, const char *buf, size_t len) { - writeToFD(buf, len); - } - - static void write(const char *buf, size_t len) { writeToFD(buf, len); } - - static bool isSTLSafe() { return false; } + static void write(const char *buf, const size_t len) { writeToFD(buf, len); } static void writeOpening() { writeToFD(CAPIO_LOG_POSIX_SYSCALL_START, strlen(CAPIO_LOG_POSIX_SYSCALL_START)); diff --git a/capio/server/include/utils/server_logger.hpp b/capio/server/include/utils/server_logger.hpp index a6f9b761d..a31ecb462 100644 --- a/capio/server/include/utils/server_logger.hpp +++ b/capio/server/include/utils/server_logger.hpp @@ -52,15 +52,8 @@ struct ServerLogWriteAdapter { this->logFileName = logfileName; } - void writeFormatted(const char * /*invoker*/, const char * /*file*/, unsigned int /*line*/, - long int /*tid*/, const char *buf, size_t /*len*/) { - writeToStream(buf); - } - void write(const char *buf, size_t /*len*/) { writeToStream(buf); } - static bool isSTLSafe() { return true; } - const std::string &getLogFileName() { return logFileName; } static void writeOpening() {} From 8918e8c22a900bca1c78f5f55a03b4b83b7f4dea Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 19 May 2026 18:16:51 +0200 Subject: [PATCH 13/16] format --- capio/common/env.hpp | 1 - capio/tests/unit/server/src/main.cpp | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/capio/common/env.hpp b/capio/common/env.hpp index 0e7313772..2b76a538c 100644 --- a/capio/common/env.hpp +++ b/capio/common/env.hpp @@ -11,7 +11,6 @@ #include "common/syscall.hpp" - // TODO: remove forward declaration of function by splitting into header and impl. capio/common inline bool is_forbidden_path(const std::string_view &path); diff --git a/capio/tests/unit/server/src/main.cpp b/capio/tests/unit/server/src/main.cpp index ec4620798..b57f22e41 100644 --- a/capio/tests/unit/server/src/main.cpp +++ b/capio/tests/unit/server/src/main.cpp @@ -3,7 +3,6 @@ #include "capiocl.hpp" #include "capiocl/engine.h" #include "client-manager/client_manager.hpp" -#include "remote/backend/none.hpp" #include "storage/manager.hpp" #include "utils/capiocl_adapter.hpp" #include "utils/location.hpp" @@ -16,7 +15,7 @@ Backend *backend = nullptr; const capiocl::engine::Engine &CapioCLEngine::get() { return *capio_cl_engine; } class MockBackend : public Backend { -public: + public: MockBackend() : Backend(HOST_NAME_MAX) {} void recv_file(char *shm, const std::string &source, const long int bytes_expected) override { From 56ca3547c1183f19f3eee17962c9653d911a85de Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 19 May 2026 19:00:37 +0200 Subject: [PATCH 14/16] refactor --- capio/posix/utils/posix_logger.hpp | 75 +++++++++++++++--------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/capio/posix/utils/posix_logger.hpp b/capio/posix/utils/posix_logger.hpp index 19eb16635..2de8e11a7 100644 --- a/capio/posix/utils/posix_logger.hpp +++ b/capio/posix/utils/posix_logger.hpp @@ -8,6 +8,43 @@ struct PosixLogWriteAdapter { static thread_local int fileFD; static thread_local char filePath[PATH_MAX]; + explicit PosixLogWriteAdapter() { + + if (fileOpen) { + return; + } + + sprintf(filePath, "%s/%s%ld.log", getHostLogDir(), getLogPrefix(), + capio_syscall(SYS_gettid)); + + capio_syscall(SYS_mkdirat, AT_FDCWD, getLogDir(), 0755); + capio_syscall(SYS_mkdirat, AT_FDCWD, getPosixLogDir(), 0755); + capio_syscall(SYS_mkdirat, AT_FDCWD, getHostLogDir(), 0755); + + fileFD = capio_syscall(SYS_openat, AT_FDCWD, filePath, O_CREAT | O_WRONLY | O_APPEND, 0644); + + if (fileFD == -1) { + capio_syscall(SYS_write, fileno(stdout), + "Err fopen file: ", strlen("Err fopen file: ")); + capio_syscall(SYS_write, fileno(stdout), filePath, strlen(filePath)); + capio_syscall(SYS_write, fileno(stdout), " ", 1); + capio_syscall(SYS_write, fileno(stdout), strerror(errno), strlen(strerror(errno))); + capio_syscall(SYS_write, fileno(stdout), "\n", 1); + exit(EXIT_FAILURE); + } + fileOpen = true; + } + + static void write(const char *buf, const size_t len) { writeToFD(buf, len); } + + static void writeOpening() { + writeToFD(CAPIO_LOG_POSIX_SYSCALL_START, strlen(CAPIO_LOG_POSIX_SYSCALL_START)); + } + + static void writeEpilogue() { + writeToFD(CAPIO_LOG_POSIX_SYSCALL_END, strlen(CAPIO_LOG_POSIX_SYSCALL_END)); + } + private: static const char *getHostname() { static char hostname[HOST_NAME_MAX]{'\0'}; @@ -65,44 +102,6 @@ struct PosixLogWriteAdapter { capio_syscall(SYS_write, fileFD, buf, len); capio_syscall(SYS_write, fileFD, "\n", 1); } - - public: - explicit PosixLogWriteAdapter() { - - if (fileOpen) { - return; - } - - sprintf(filePath, "%s/%s%ld.log", getHostLogDir(), getLogPrefix(), - capio_syscall(SYS_gettid)); - - capio_syscall(SYS_mkdirat, AT_FDCWD, getLogDir(), 0755); - capio_syscall(SYS_mkdirat, AT_FDCWD, getPosixLogDir(), 0755); - capio_syscall(SYS_mkdirat, AT_FDCWD, getHostLogDir(), 0755); - - fileFD = capio_syscall(SYS_openat, AT_FDCWD, filePath, O_CREAT | O_WRONLY | O_APPEND, 0644); - - if (fileFD == -1) { - capio_syscall(SYS_write, fileno(stdout), - "Err fopen file: ", strlen("Err fopen file: ")); - capio_syscall(SYS_write, fileno(stdout), filePath, strlen(filePath)); - capio_syscall(SYS_write, fileno(stdout), " ", 1); - capio_syscall(SYS_write, fileno(stdout), strerror(errno), strlen(strerror(errno))); - capio_syscall(SYS_write, fileno(stdout), "\n", 1); - exit(EXIT_FAILURE); - } - fileOpen = true; - } - - static void write(const char *buf, const size_t len) { writeToFD(buf, len); } - - static void writeOpening() { - writeToFD(CAPIO_LOG_POSIX_SYSCALL_START, strlen(CAPIO_LOG_POSIX_SYSCALL_START)); - } - - static void writeEpilogue() { - writeToFD(CAPIO_LOG_POSIX_SYSCALL_END, strlen(CAPIO_LOG_POSIX_SYSCALL_END)); - } }; thread_local bool PosixLogWriteAdapter::fileOpen = false; From 2986cd1e31b4c054eb10d448175a7b6339a6f8cd Mon Sep 17 00:00:00 2001 From: marcoSanti Date: Wed, 20 May 2026 09:14:08 +0200 Subject: [PATCH 15/16] Refactor logger macro --- capio/common/logger.hpp | 17 +++++++---------- capio/posix/libcapio_posix.cpp | 2 +- capio/server/capio_server.cpp | 1 + 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/capio/common/logger.hpp b/capio/common/logger.hpp index 1255feccc..d37daef2f 100644 --- a/capio/common/logger.hpp +++ b/capio/common/logger.hpp @@ -105,11 +105,10 @@ template class TemplateLogger { va_start(argp, message); va_copy(argpc, argp); -#ifdef __CAPIO_POSIX if (!enable_logger) { return; } -#endif + sprintf(format, CAPIO_LOG_PRE_MSG, current_time_in_millis(), this->invoker); const size_t pre_msg_len = strlen(format); @@ -151,11 +150,11 @@ template class TemplateLogger { } void log(const char *message, ...) { -#ifdef __CAPIO_POSIX + if (!enable_logger) { return; } -#endif + va_list argp, argpc; sprintf(format, CAPIO_LOG_PRE_MSG, current_time_in_millis(), this->invoker); @@ -198,8 +197,8 @@ template inline thread_local int TemplateLogger::current_log_lev #define LOG(message, ...) log.log(message, ##__VA_ARGS__) #define START_LOG(tid, message, ...) \ Logger log(__func__, __FILE__, __LINE__, tid, message, ##__VA_ARGS__) -#define START_SYSCALL_LOGGING() enable_logger = true -#define SUSPEND_SYSCALL_LOGGING() SyscallLoggingSuspender sls{}; +#define ENABLE_LOGGER() enable_logger = true +#define DISABLE_LOGGER() SyscallLoggingSuspender sls{}; /** * This macro is used to inject code into debug mode. It needs a self calling lambda function, @@ -238,15 +237,13 @@ template inline thread_local int TemplateLogger::current_log_lev #define ERR_EXIT(message, ...) ERR_EXIT_EXCEPT_CHOICE(true, message, ##__VA_ARGS__) #define LOG(message, ...) #define START_LOG(tid, message, ...) -#define START_SYSCALL_LOGGING() -#define SUSPEND_SYSCALL_LOGGING() #define SEM_CREATE_CHECK(sem, source) \ if (sem == SEM_FAILED) { \ __SHM_CHECK_CLI_MSG; \ } #define DBG(tid, lambda) -#define START_SYSCALL_LOGGING() -#define SUSPEND_SYSCALL_LOGGING() +#define ENABLE_LOGGER() +#define DISABLE_LOGGER() #endif diff --git a/capio/posix/libcapio_posix.cpp b/capio/posix/libcapio_posix.cpp index 67121f8c8..45b3d9fa7 100644 --- a/capio/posix/libcapio_posix.cpp +++ b/capio/posix/libcapio_posix.cpp @@ -411,5 +411,5 @@ static __attribute__((constructor)) void init() { intercept_hook_point_clone_child = hook_clone_child; intercept_hook_point_clone_parent = hook_clone_parent; intercept_hook_point = hook; - START_SYSCALL_LOGGING(); + ENABLE_LOGGER(); } \ No newline at end of file diff --git a/capio/server/capio_server.cpp b/capio/server/capio_server.cpp index ef70188d6..e98ef9504 100644 --- a/capio/server/capio_server.cpp +++ b/capio/server/capio_server.cpp @@ -114,6 +114,7 @@ static constexpr std::array build_request_handle } int main(int argc, char **argv) { + ENABLE_LOGGER(); Semaphore internal_server_sem(0); From c3357c963fcccc0b3c796230ea5789de054e62e5 Mon Sep 17 00:00:00 2001 From: marcoSanti Date: Wed, 20 May 2026 10:38:45 +0200 Subject: [PATCH 16/16] Ported log to use JSON based logfiles --- capio/common/json_base_logger.hpp | 276 +++++++++++++++++++ capio/common/logger.hpp | 180 ++++++------ capio/posix/utils/posix_logger.hpp | 83 +++--- capio/server/capio_server.cpp | 1 - capio/server/include/utils/server_logger.hpp | 82 +++--- 5 files changed, 454 insertions(+), 168 deletions(-) create mode 100644 capio/common/json_base_logger.hpp diff --git a/capio/common/json_base_logger.hpp b/capio/common/json_base_logger.hpp new file mode 100644 index 000000000..bd1fd5066 --- /dev/null +++ b/capio/common/json_base_logger.hpp @@ -0,0 +1,276 @@ +#ifndef CAPIO_LOGGER_JSON_BASE_HPP +#define CAPIO_LOGGER_JSON_BASE_HPP + +// Pull in everything this header needs directly so it is self-contained +// regardless of include order. +#include // va_list, va_copy, va_end +#include // snprintf, vsnprintf +#include // strlen +#include // std::string (used in expandAndEscape) + +#include "constants.hpp" // CAPIO_LOG_MAX_MSG_LEN, CAPIO_DEFAULT_LOG_FOLDER, … +#include "syscall.hpp" // current_time_in_millis (declared in logger.hpp which + // includes syscall.hpp; guard against double-include + // by relying on header guards in logger.hpp) + +/** + * @file logger_json_base.hpp + * + * CRTP mixin that implements the full structured-JSON adapter interface + * required by TemplateLogger. Derived adapters only need to supply two + * I/O primitives as *static* methods: + * + * static void rawWriteBytes(const char *buf, int len); + * static void rawWriteStr (const char *buf); // NUL-terminated + * + * All JSON structure, indentation, pending-comma handling, and string + * escaping live here, shared between PosixLogWriteAdapter and + * ServerLogWriteAdapter. + */ +template +struct JsonLogBase { + + // ------------------------------------------------------------------ // + // Thread-local JSON state + // ------------------------------------------------------------------ // + + static thread_local int nestingDepth; + static thread_local bool rootArrayOpen; + + // Pending-line buffer: holds the last event/closing-brace WITHOUT its + // trailing newline. Flushed with ",\n" when a sibling follows, plain + // "\n" when the enclosing array closes. Avoids trailing commas on an + // append-only stream without any seek-back. + static thread_local int pendingLen; + static thread_local char pendingBuf[CAPIO_LOG_MAX_MSG_LEN * 6 + 256]; + + // ------------------------------------------------------------------ // + // TemplateLogger adapter interface + // ------------------------------------------------------------------ // + + static void write(const char * /*legacy*/, const size_t /*legacy*/) { + // ts_exit is written by writeEpilogue; nothing to do here. + } + + /** + * Called for every LOG(...) inside a syscall scope. + * Flushes the previous pending entry with a comma, then buffers this + * event object WITHOUT a trailing newline. + */ + static void printFormatted(unsigned long int timestamp, + const char *invoker, const char *file, int line, + const char * /*output_template*/, + const char *message_format, va_list args) { + + char escaped_args[CAPIO_LOG_MAX_MSG_LEN * 6]; + expandAndEscape(message_format, args, escaped_args, + static_cast(sizeof(escaped_args))); + + char escaped_invoker[512]; + jsonEscape(invoker, static_cast(::strlen(invoker)), + escaped_invoker, static_cast(sizeof(escaped_invoker))); + + char escaped_file[512]; + jsonEscape(file, static_cast(::strlen(file)), + escaped_file, static_cast(sizeof(escaped_file))); + + flushPending(true); // previous sibling gets a comma + + const int indent = indentSize(); + char *p = JsonLogBase::pendingBuf; + for (int i = 0; i < indent; ++i) { *p++ = ' '; } + p += ::snprintf(p, + sizeof(JsonLogBase::pendingBuf) - static_cast(indent) - 1, + "{ \"ts\": %lu, \"invoker\": \"%s\"," + " \"file\": \"%s\", \"line\": %d, \"args\": \"%s\" }", + timestamp, escaped_invoker, escaped_file, line, escaped_args); + JsonLogBase::pendingLen = static_cast( + p - JsonLogBase::pendingBuf); + } + + /** + * Called by TemplateLogger constructor (current_log_level == 1). + * + * Emits the opening of one syscall object: + * { + * "invoker": "...", + * "file": "...", + * "line": N, + * "ts_enter": T, + * "args": "...", + * "events": [ + */ + static void writeOpening(unsigned long int timestamp, + const char *invoker, const char *file, int line, + const char *message_format, va_list args) { + + if (!JsonLogBase::rootArrayOpen) { + Derived::rawWriteStr("[\n"); + JsonLogBase::rootArrayOpen = true; + JsonLogBase::nestingDepth = 1; + } + + char escaped_args[CAPIO_LOG_MAX_MSG_LEN * 6]; + expandAndEscape(message_format, args, escaped_args, + static_cast(sizeof(escaped_args))); + + char escaped_invoker[512]; + jsonEscape(invoker, static_cast(::strlen(invoker)), + escaped_invoker, static_cast(sizeof(escaped_invoker))); + + char escaped_file[512]; + jsonEscape(file, static_cast(::strlen(file)), + escaped_file, static_cast(sizeof(escaped_file))); + + flushPending(true); // flush previous top-level "}" with comma if present + + writeImmediate("{"); + JsonLogBase::nestingDepth++; + + writeField ("\"invoker\"", "\"%s\",", escaped_invoker); + writeField ("\"file\"", "\"%s\",", escaped_file); + writeFieldInt("\"line\"", "%d,", line); + writeFieldUL ("\"ts_enter\"", "%lu,", timestamp); + writeField ("\"args\"", "\"%s\",", escaped_args); + + writeImmediate("\"events\": ["); + JsonLogBase::nestingDepth++; + + JsonLogBase::pendingLen = 0; + } + + /** + * Called by TemplateLogger destructor (current_log_level == 1). + * Closes the events array, emits ts_exit, and stores the closing "}" + * as a new pending line so the next sibling gets a leading comma. + * Receives the timestamp captured at destructor time by TemplateLogger. + */ + static void writeEpilogue(unsigned long int timestamp) { + if (JsonLogBase::nestingDepth < 2) { return; } + + flushPending(false); // last event — no trailing comma + + JsonLogBase::nestingDepth--; + writeImmediate("],"); // close "events" array with trailing comma for ts_exit + + { + char buf[64]; + ::snprintf(buf, sizeof(buf), "\"ts_exit\": %lu", timestamp); + writeImmediate(buf); + } + + JsonLogBase::nestingDepth--; + char *p = JsonLogBase::pendingBuf; + const int indent = indentSize(); + for (int i = 0; i < indent; ++i) { *p++ = ' '; } + *p++ = '}'; + JsonLogBase::pendingLen = static_cast( + p - JsonLogBase::pendingBuf); + } + + protected: + // ------------------------------------------------------------------ // + // Pending-line management + // ------------------------------------------------------------------ // + + static void flushPending(bool withComma) { + if (JsonLogBase::pendingLen <= 0) { return; } + Derived::rawWriteBytes(JsonLogBase::pendingBuf, + JsonLogBase::pendingLen); + Derived::rawWriteStr(withComma ? ",\n" : "\n"); + JsonLogBase::pendingLen = 0; + } + + static void writeImmediate(const char *buf, int len = -1) { + if (len < 0) { len = static_cast(::strlen(buf)); } + const int indent = indentSize(); + char spaces[65] = {0}; + for (int i = 0; i < indent; ++i) { spaces[i] = ' '; } + Derived::rawWriteBytes(spaces, indent); + Derived::rawWriteBytes(buf, len); + Derived::rawWriteStr("\n"); + } + + static void writeField(const char *key, const char *fmt, const char *val) { + char tmp[768]; ::snprintf(tmp, sizeof(tmp), fmt, val); + char buf[1024]; ::snprintf(buf, sizeof(buf), "%s: %s", key, tmp); + writeImmediate(buf); + } + static void writeFieldInt(const char *key, const char *fmt, int val) { + char tmp[64]; ::snprintf(tmp, sizeof(tmp), fmt, val); + char buf[128]; ::snprintf(buf, sizeof(buf), "%s: %s", key, tmp); + writeImmediate(buf); + } + static void writeFieldUL(const char *key, const char *fmt, unsigned long val) { + char tmp[64]; ::snprintf(tmp, sizeof(tmp), fmt, val); + char buf[128]; ::snprintf(buf, sizeof(buf), "%s: %s", key, tmp); + writeImmediate(buf); + } + + static int indentSize() { + const int n = JsonLogBase::nestingDepth * 2; + return n < 64 ? n : 64; + } + + // ------------------------------------------------------------------ // + // String helpers + // ------------------------------------------------------------------ // + + static void expandAndEscape(const char *fmt, va_list args, + char *dst, int dst_size) { + va_list copy; + va_copy(copy, args); + const int raw_len = ::vsnprintf(nullptr, 0, fmt, copy); + va_end(copy); + + std::string raw(static_cast(raw_len) + 1, '\0'); + va_copy(copy, args); + ::vsnprintf(&raw[0], static_cast(raw_len) + 1, fmt, copy); + va_end(copy); + + jsonEscape(raw.c_str(), raw_len, dst, dst_size); + } + + static void jsonEscape(const char *src, int src_len, + char *dst, int dst_size) { + int di = 0; + for (int si = 0; si < src_len && di + 7 < dst_size; ++si) { + const unsigned char c = static_cast(src[si]); + if (c == '"' || c == '\\') { + dst[di++] = '\\'; dst[di++] = static_cast(c); + } else if (c == '\n') { dst[di++] = '\\'; dst[di++] = 'n'; + } else if (c == '\r') { dst[di++] = '\\'; dst[di++] = 'r'; + } else if (c == '\t') { dst[di++] = '\\'; dst[di++] = 't'; + } else if (c < 0x20 || c == 0x7f) { + dst[di++] = '\\'; dst[di++] = 'u'; + dst[di++] = '0'; dst[di++] = '0'; + dst[di++] = hexChar(c >> 4); + dst[di++] = hexChar(c & 0x0fu); + } else { + dst[di++] = static_cast(c); + } + } + dst[di] = '\0'; + } + + static char hexChar(unsigned int n) { + return static_cast(n < 10u ? '0' + n : 'a' + n - 10u); + } +}; + +// Out-of-class definitions for thread_local statics. +// The template parameter ensures PosixLogWriteAdapter and +// ServerLogWriteAdapter each get independent storage. +template +thread_local int JsonLogBase::nestingDepth = 0; + +template +thread_local bool JsonLogBase::rootArrayOpen = false; + +template +thread_local int JsonLogBase::pendingLen = 0; + +template +thread_local char JsonLogBase::pendingBuf[CAPIO_LOG_MAX_MSG_LEN * 6 + 256] = {'\0'}; + +#endif // CAPIO_LOGGER_JSON_BASE_HPP \ No newline at end of file diff --git a/capio/common/logger.hpp b/capio/common/logger.hpp index d37daef2f..43a1b78bd 100644 --- a/capio/common/logger.hpp +++ b/capio/common/logger.hpp @@ -25,7 +25,7 @@ template std::string demangled_name(const T &obj) { return status == 0 ? demangled.get() : mangled; } -inline bool continue_on_error = false; // if set to true, CAPIO does not terminate on ERR_EXIT +inline bool continue_on_error = false; inline void raise_termination(const bool raise_exception, const std::string &message) { if (raise_exception) { @@ -39,15 +39,18 @@ inline void raise_termination(const bool raise_exception, const std::string &mes #include "syscallnames.h" #endif -// this variable tells the logger that syscall logging -// has started, and we are not in setup phase -// FIXME: Remove the inline specifier by splitting into header and source code +#ifdef __CAPIO_POSIX +// POSIX interceptor: logging starts disabled and is enabled explicitly +// after setup to prevent re-entrancy into the interceptor itself. inline thread_local bool enable_logger = false; +#else +// Server / non-POSIX: logging is always active from the first call. +inline thread_local bool enable_logger = true; +#endif -#ifndef CAPIO_MAX_LOG_LEVEL // capio max log level. defaults to -1, where everything is logged +#ifndef CAPIO_MAX_LOG_LEVEL #define CAPIO_MAX_LOG_LEVEL -1 #endif -// FIXME: Remove the inline specifier by splitting into header and source code inline int CAPIO_LOG_LEVEL = CAPIO_MAX_LOG_LEVEL; inline long long current_time_in_millis() { @@ -58,14 +61,9 @@ inline long long current_time_in_millis() { start_time = static_cast(ts.tv_sec) * 1000 + (ts.tv_nsec) / 1000000; } capio_syscall(SYS_clock_gettime, CLOCK_REALTIME, &ts); - const auto time_now = static_cast(ts.tv_sec) * 1000 + (ts.tv_nsec) / 1000000; - return time_now - start_time; + return static_cast(ts.tv_sec) * 1000 + (ts.tv_nsec) / 1000000 - start_time; } -/** - * @brief Class used to suspend the logging capabilities of CAPIO, by setting the logging_syscall - * flag to false at instantiation, and restarting the logging at destruction - */ class SyscallLoggingSuspender { public: SyscallLoggingSuspender() { enable_logger = false; } @@ -73,20 +71,33 @@ class SyscallLoggingSuspender { }; /** - * @brief Class that provides logging capabilities to CAPIO. + * @brief Logging front-end, parameterised on an Adapter for the I/O backend. + * + * Adapter contract + * ---------------- + * // Called once on entry (current_log_level == 1 after increment). + * // Receives all metadata so the adapter can open a structured record. + * static void writeOpening(unsigned long ts, const char *invoker, + * const char *file, int line, + * const char *message_format, va_list args); * - * Parameterised on a LogWriteAdapter so that the I/O strategy (POSIX - * syscalls vs. STL streams vs. any custom backend) is a compile-time - * choice with no virtual dispatch overhead. + * // Called for every LOG() inside a scope. + * static void printFormatted(unsigned long ts, const char *invoker, + * const char *file, int line, + * const char *output_template, + * const char *message_format, va_list args); * - * The default adapter (@ref DefaultLogWriteAdapter) mirrors the behaviour - * of the old monolithic Logger class for both the server and POSIX builds. + * // Called on scope exit to close the structured record. + * static void writeEpilogue(); + * + * // Legacy write — kept for ERR_EXIT paths; adapters may ignore it. + * static void write(const char *buf, size_t len); */ template class TemplateLogger { static thread_local int current_log_level; + char invoker[256]{0}; char file[256]{0}; - char format[CAPIO_LOG_MAX_MSG_LEN]{0}; unsigned int line{0}; long int tid{0}; @@ -95,90 +106,83 @@ template class TemplateLogger { public: TemplateLogger(const char invoker[], const char file[], unsigned int line, long int tid, const char *message, ...) { - current_log_level++; this->tid = tid; this->line = line; - strncpy(this->invoker, invoker, sizeof(this->invoker)); - strncpy(this->file, file, sizeof(this->file)); - - va_list argp, argpc; - va_start(argp, message); - va_copy(argpc, argp); - + strncpy(this->invoker, invoker, sizeof(this->invoker) - 1); + strncpy(this->file, file, sizeof(this->file) - 1); + + // Only track nesting when logging is actually active on this thread. + // If we incremented unconditionally, a START_LOG during the setup + // phase (before ENABLE_LOGGER) would leave current_log_level at 1 + // for the rest of the thread's lifetime, making every subsequent + // top-level call look like a nested one. if (!enable_logger) { return; } - - sprintf(format, CAPIO_LOG_PRE_MSG, current_time_in_millis(), this->invoker); - const size_t pre_msg_len = strlen(format); - strcpy(format + pre_msg_len, message); - - const int size = vsnprintf(nullptr, 0U, format, argp); - auto buf = reinterpret_cast(capio_syscall(SYS_mmap, nullptr, size + 1, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); - vsnprintf(buf, size + 1, format, argpc); + current_log_level++; if (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0) { + va_list argp; + va_start(argp, message); + if (current_log_level == 1) { - adapter.writeOpening(); + adapter.writeOpening(current_time_in_millis(), this->invoker, this->file, + this->line, message, argp); + } else { + adapter.printFormatted(current_time_in_millis(), this->invoker, this->file, + this->line, CAPIO_LOG_PRE_MSG, message, argp); } - adapter.write(buf, strlen(buf)); - } - va_end(argp); - va_end(argpc); - capio_syscall(SYS_munmap, buf, size); + va_end(argp); + } } TemplateLogger(const TemplateLogger &) = delete; TemplateLogger &operator=(const TemplateLogger &) = delete; ~TemplateLogger() { - sprintf(format, CAPIO_LOG_PRE_MSG, current_time_in_millis(), this->invoker); - const size_t pre_msg_len = strlen(format); - strcpy(format + pre_msg_len, "returned"); - - adapter.write(format, strlen(format)); + if (!enable_logger) { + return; // level was never incremented for this instance + } - if (current_log_level == 1 && enable_logger && + if (current_log_level == 1 && (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0)) { - adapter.writeEpilogue(); + // Capture the exit timestamp here, as close to the actual return + // as possible, and pass it into the adapter so it doesn't need + // to call current_time_in_millis() itself. + adapter.writeEpilogue(static_cast(current_time_in_millis())); } current_log_level--; } void log(const char *message, ...) { - if (!enable_logger) { return; } - va_list argp, argpc; - - sprintf(format, CAPIO_LOG_PRE_MSG, current_time_in_millis(), this->invoker); - const size_t pre_msg_len = strlen(format); - strcpy(format + pre_msg_len, message); - - va_start(argp, message); - va_copy(argpc, argp); - const int size = vsnprintf(nullptr, 0U, format, argp); - const auto buf = reinterpret_cast( - capio_syscall(SYS_mmap, nullptr, size + 1, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); - vsnprintf(buf, size + 1, format, argpc); - + // current_log_level is only incremented when enable_logger is true, + // so this check is always consistent with the constructor. if (current_log_level < CAPIO_MAX_LOG_LEVEL || CAPIO_MAX_LOG_LEVEL < 0) { - adapter.write(buf, strlen(buf)); + va_list argp; + va_start(argp, message); + adapter.printFormatted(current_time_in_millis(), this->invoker, this->file, this->line, + CAPIO_LOG_PRE_MSG, message, argp); + va_end(argp); } - - va_end(argp); - va_end(argpc); - capio_syscall(SYS_munmap, buf, size); } std::string getLogFileName() { return adapter.getLogFileName(); } + + /** + * Resets the per-thread nesting counter to zero. + * Called by the server-side START_LOG macro before constructing a new + * Logger, so that every top-level server call always opens a fresh + * JSON object even when invoked from inside an existing Logger scope + * (e.g. the server main loop calling helper functions that also use + * START_LOG). Not used in the POSIX build where nesting is meaningful. + */ + static void reset_log_level() { current_log_level = 0; } }; template inline thread_local int TemplateLogger::current_log_level = 0; @@ -195,30 +199,26 @@ template inline thread_local int TemplateLogger::current_log_lev #define ERR_EXIT(message, ...) ERR_EXIT_EXCEPT_CHOICE(true, message, ##__VA_ARGS__) #define LOG(message, ...) log.log(message, ##__VA_ARGS__) + +// On the POSIX build, enable_logger starts false and is flipped explicitly; +// nesting is meaningful so current_log_level is never reset. +// On the server build, enable_logger starts true (see declaration above) and +// current_log_level is reset to 0 on every START_LOG so that each top-level +// request handler always opens its own JSON object, even when called from +// inside an outer Logger scope. +#ifdef __CAPIO_POSIX +#define START_LOG(tid, message, ...) \ + Logger log(__func__, __FILE__, __LINE__, tid, message, ##__VA_ARGS__) +#else #define START_LOG(tid, message, ...) \ + Logger::reset_log_level(); \ Logger log(__func__, __FILE__, __LINE__, tid, message, ##__VA_ARGS__) +#endif + #define ENABLE_LOGGER() enable_logger = true -#define DISABLE_LOGGER() SyscallLoggingSuspender sls{}; +#define DISABLE_LOGGER() \ + SyscallLoggingSuspender sls {} -/** - * This macro is used to inject code into debug mode. It needs a self calling lambda function, - * that is a lambda in the following form: - * - * [](){}() - * - * For example, a debug code to print a value might be injected in this way: - * - * int value = 10; - * DBG(tid, [](int i){printf("%d", i);}(value) ); - * - * This is useful to print or run debug actions with variables defined outside - * of the scope of the given lambda function Be careful that the code defined inside the DBG - * macro is not compiled when building in Release. - * - * Be even MORE CAREFUL to not use any STL code inside the DBG lambda function as it could be - * captured by syscall_intercept (ie do not use std::cout unless you are 100% sure of what you are - * doing) - */ #define DBG(tid, lambda) \ { \ START_LOG(tid, "[ DBG ]~~~~~~~~~~~~ START ~~~~~~~~~~~~~~[ DBG ]"); \ diff --git a/capio/posix/utils/posix_logger.hpp b/capio/posix/utils/posix_logger.hpp index 2de8e11a7..224bab459 100644 --- a/capio/posix/utils/posix_logger.hpp +++ b/capio/posix/utils/posix_logger.hpp @@ -2,55 +2,68 @@ #define CAPIO_POSIXLOGGER_HPP #include "common/logger.hpp" +#include "common/json_base_logger.hpp" -struct PosixLogWriteAdapter { - static thread_local bool fileOpen; - static thread_local int fileFD; +struct PosixLogWriteAdapter : JsonLogBase { + + static thread_local int fileFD; static thread_local char filePath[PATH_MAX]; - explicit PosixLogWriteAdapter() { + // The constructor is called every time a Logger is constructed (i.e. + // on every START_LOG). It opens the per-thread log file on first call + // and is a no-op on subsequent calls. + explicit PosixLogWriteAdapter() { ensureFileOpen(); } + + // ------------------------------------------------------------------ // + // I/O primitives required by JsonLogBase + // + // These are static because JsonLogBase calls them as Derived::xxx(). + // They call ensureFileOpen() so that even if a new thread reaches a + // static write path before its first constructor call, the file is + // always valid. + // ------------------------------------------------------------------ // + + static void rawWriteBytes(const char *buf, int len) { + ensureFileOpen(); + capio_syscall(SYS_write, fileFD, buf, len); + } - if (fileOpen) { - return; - } + static void rawWriteStr(const char *buf) { + ensureFileOpen(); + capio_syscall(SYS_write, fileFD, buf, strlen(buf)); + } - sprintf(filePath, "%s/%s%ld.log", getHostLogDir(), getLogPrefix(), + private: + // Opens the per-thread log file exactly once per thread. + // Safe to call from both instance constructor and static write paths. + static void ensureFileOpen() { + if (fileFD != -1) { return; } + + sprintf(filePath, "%s/%s%ld.log", + getHostLogDir(), getLogPrefix(), capio_syscall(SYS_gettid)); - capio_syscall(SYS_mkdirat, AT_FDCWD, getLogDir(), 0755); + capio_syscall(SYS_mkdirat, AT_FDCWD, getLogDir(), 0755); capio_syscall(SYS_mkdirat, AT_FDCWD, getPosixLogDir(), 0755); - capio_syscall(SYS_mkdirat, AT_FDCWD, getHostLogDir(), 0755); + capio_syscall(SYS_mkdirat, AT_FDCWD, getHostLogDir(), 0755); - fileFD = capio_syscall(SYS_openat, AT_FDCWD, filePath, O_CREAT | O_WRONLY | O_APPEND, 0644); + fileFD = capio_syscall(SYS_openat, AT_FDCWD, filePath, + O_CREAT | O_WRONLY | O_APPEND, 0644); if (fileFD == -1) { capio_syscall(SYS_write, fileno(stdout), "Err fopen file: ", strlen("Err fopen file: ")); capio_syscall(SYS_write, fileno(stdout), filePath, strlen(filePath)); - capio_syscall(SYS_write, fileno(stdout), " ", 1); + capio_syscall(SYS_write, fileno(stdout), " ", 1); capio_syscall(SYS_write, fileno(stdout), strerror(errno), strlen(strerror(errno))); - capio_syscall(SYS_write, fileno(stdout), "\n", 1); + capio_syscall(SYS_write, fileno(stdout), "\n", 1); exit(EXIT_FAILURE); } - fileOpen = true; } - static void write(const char *buf, const size_t len) { writeToFD(buf, len); } - - static void writeOpening() { - writeToFD(CAPIO_LOG_POSIX_SYSCALL_START, strlen(CAPIO_LOG_POSIX_SYSCALL_START)); - } - - static void writeEpilogue() { - writeToFD(CAPIO_LOG_POSIX_SYSCALL_END, strlen(CAPIO_LOG_POSIX_SYSCALL_END)); - } - - private: static const char *getHostname() { static char hostname[HOST_NAME_MAX]{'\0'}; - if (hostname[0] == '\0') { - gethostname(hostname, HOST_NAME_MAX); - } + if (hostname[0] == '\0') { gethostname(hostname, HOST_NAME_MAX); } return hostname; } @@ -82,7 +95,7 @@ struct PosixLogWriteAdapter { static char *dir = nullptr; if (dir == nullptr) { const char *base = getLogDir(); - dir = new char[strlen(base) + 7]{0}; // "/posix\0" + dir = new char[strlen(base) + 7]{0}; sprintf(dir, "%s/posix", base); } return dir; @@ -92,21 +105,15 @@ struct PosixLogWriteAdapter { static char *dir = nullptr; if (dir == nullptr) { const char *posixDir = getPosixLogDir(); - dir = new char[strlen(posixDir) + HOST_NAME_MAX]{0}; + dir = new char[strlen(posixDir) + HOST_NAME_MAX]{0}; sprintf(dir, "%s/%s", posixDir, getHostname()); } return dir; } - - static void writeToFD(const char *buf, const size_t len) { - capio_syscall(SYS_write, fileFD, buf, len); - capio_syscall(SYS_write, fileFD, "\n", 1); - } }; -thread_local bool PosixLogWriteAdapter::fileOpen = false; -thread_local int PosixLogWriteAdapter::fileFD = -1; -thread_local char PosixLogWriteAdapter::filePath[PATH_MAX] = {'\0'}; +inline thread_local int PosixLogWriteAdapter::fileFD = -1; +inline thread_local char PosixLogWriteAdapter::filePath[PATH_MAX] = {'\0'}; using Logger = TemplateLogger; diff --git a/capio/server/capio_server.cpp b/capio/server/capio_server.cpp index e98ef9504..ef70188d6 100644 --- a/capio/server/capio_server.cpp +++ b/capio/server/capio_server.cpp @@ -114,7 +114,6 @@ static constexpr std::array build_request_handle } int main(int argc, char **argv) { - ENABLE_LOGGER(); Semaphore internal_server_sem(0); diff --git a/capio/server/include/utils/server_logger.hpp b/capio/server/include/utils/server_logger.hpp index a31ecb462..a8ed5db65 100644 --- a/capio/server/include/utils/server_logger.hpp +++ b/capio/server/include/utils/server_logger.hpp @@ -1,66 +1,70 @@ #ifndef CAPIO_SERVERLOGGER_HPP #define CAPIO_SERVERLOGGER_HPP -#include +#include "common/logger.hpp" +#include "common/json_base_logger.hpp" -struct ServerLogWriteAdapter { - private: - std::ofstream logfile; - std::string logFileName; +struct ServerLogWriteAdapter : JsonLogBase { - void writeToStream(const char *buf) { - if (!logfile.is_open()) { - return; - } + static thread_local std::ofstream *logfile; + static thread_local std::string *logFileName; - logfile << buf << std::endl; - logfile.flush(); + explicit ServerLogWriteAdapter() { ensureFileOpen(); } + + std::string getLogFileName() const { + return logFileName ? *logFileName : std::string{}; } - public: - explicit ServerLogWriteAdapter() { + // ------------------------------------------------------------------ // + // I/O primitives required by JsonLogBase + // ------------------------------------------------------------------ // - if (this->logfile.is_open()) { - return; - } - std::string logMasterDirName; - std::string logfilePrefix; + static void rawWriteBytes(const char *buf, int len) { + ensureFileOpen(); + logfile->write(buf, len); + logfile->flush(); + } + + static void rawWriteStr(const char *buf) { + rawWriteBytes(buf, static_cast(strlen(buf))); + } - if (const char *tmp = std::getenv("CAPIO_LOG_DIR"); tmp == nullptr) { - logMasterDirName = CAPIO_DEFAULT_LOG_FOLDER; + private: + static void ensureFileOpen() { + if (logfile != nullptr && logfile->is_open()) { return; } + + std::string logDir; + std::string prefix; + + if (const char *tmp = std::getenv("CAPIO_LOG_DIR"); tmp != nullptr) { + logDir = tmp; } else { - logMasterDirName = tmp; + logDir = CAPIO_DEFAULT_LOG_FOLDER; } - if (const char *tmp = std::getenv("CAPIO_LOG_PREFIX"); tmp == nullptr) { - logfilePrefix = CAPIO_SERVER_DEFAULT_LOG_FILE_PREFIX; + if (const char *tmp = std::getenv("CAPIO_LOG_PREFIX"); tmp != nullptr) { + prefix = tmp; } else { - logfilePrefix = tmp; + prefix = CAPIO_SERVER_DEFAULT_LOG_FILE_PREFIX; } char hostname[HOST_NAME_MAX]; gethostname(hostname, HOST_NAME_MAX); - const std::filesystem::path outputFolder{logMasterDirName + "/server/" + hostname}; + const std::filesystem::path outputFolder{logDir + "/server/" + hostname}; std::filesystem::create_directories(outputFolder); - const std::filesystem::path logfileName = outputFolder.string() + "/" + logfilePrefix + - std::to_string(capio_syscall(SYS_gettid)) + - ".log"; + const std::filesystem::path path = + outputFolder / (prefix + std::to_string(capio_syscall(SYS_gettid)) + ".log"); - logfile.open(logfileName, std::ofstream::app); - this->logFileName = logfileName; + logfile = new std::ofstream(path, std::ofstream::app); + logFileName = new std::string(path.string()); } - - void write(const char *buf, size_t /*len*/) { writeToStream(buf); } - - const std::string &getLogFileName() { return logFileName; } - - static void writeOpening() {} - - static void writeEpilogue() {} }; +inline thread_local std::ofstream *ServerLogWriteAdapter::logfile = nullptr; +inline thread_local std::string *ServerLogWriteAdapter::logFileName = nullptr; + using Logger = TemplateLogger; -#endif // CAPIO_SERVERLOGGER_HPP +#endif // CAPIO_SERVERLOGGER_HPP \ No newline at end of file