diff --git a/CHANGELOG.md b/CHANGELOG.md index 40a68d26653e1b68f3ba1c31d0910229365fafdd..cc028bc4f4cc9527ef740bcf278fbabacbda7bd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ### New +- Added a directory cache for the file system client to improve `ls -l` type operations by avoiding consecutive stat calls + ([!194](https://storage.bsc.es/gitlab/hpc/gekkofs/-/merge_requests/194)). + - The cache is experimental and thus disabled by default and can be enabled with the env variable `LIBGKFS_DISABLE_DIR_CACHE` set to `ON`. - Added file system expansion support ([!196](https://storage.bsc.es/gitlab/hpc/gekkofs/-/merge_requests/196)). - Added the tool `gkfs_malleability` to steer start, status, and finalize requests for expansion operations. - `-DGKFS_BUILD_TOOLS=ON` must be set for CMake to build the tool. diff --git a/CMakeLists.txt b/CMakeLists.txt index a8b9cd4304bf4102e83b9bab23256d0b27b0dfc3..a7f6b347d62283ea98a84570578ee2095305a1fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,7 +84,7 @@ if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git) OUTPUT_VARIABLE GIT_VERSION ERROR_VARIABLE GIT_ERR OUTPUT_STRIP_TRAILING_WHITESPACE - ) + ) if ("${GIT_RET}" STREQUAL "0") string(REGEX MATCH "^v([0-9]+)\.([0-9]+)\.([0-9]+)-([0-9]+)-(.*)$" @@ -165,7 +165,7 @@ find_package(Syscall_intercept REQUIRED) if (GKFS_ENABLE_AGIOS) message(STATUS "[${PROJECT_NAME}] Checking for Agios") find_package(AGIOS REQUIRED) -endif() +endif () if (GKFS_ENABLE_CLIENT_METRICS) ### zeromq: required for sending client metrics to FTIO @@ -174,15 +174,15 @@ if (GKFS_ENABLE_CLIENT_METRICS) endif () ### Metadata backends -if(GKFS_ENABLE_ROCKSDB) +if (GKFS_ENABLE_ROCKSDB) message(STATUS "[${PROJECT_NAME}] Checking for RocksDB") add_compile_definitions(GKFS_ENABLE_ROCKSDB) find_package(RocksDB REQUIRED) message(STATUS "[${PROJECT_NAME}] RocksDB version ${RocksDB_VERSION}") message(STATUS "[${PROJECT_NAME}] RocksDB location ${RocksDB_DIR}") -endif() +endif () -if(GKFS_ENABLE_PARALLAX) +if (GKFS_ENABLE_PARALLAX) add_compile_definitions(GKFS_ENABLE_PARALLAX) # The current version of Parallax has a direct dependency on libyaml and librt. # Make sure that we find them and add them as link dependencies.. @@ -196,15 +196,15 @@ if(GKFS_ENABLE_PARALLAX) message(STATUS "[${PROJECT_NAME}] Checking for Parallax") find_package(Parallax REQUIRED) target_link_libraries(Parallax::parallax INTERFACE yaml AIO::AIO) -endif() +endif () ### Prometheus-cpp: required for the collection of GekkoFS stats ### (these expose the prometheus-cpp::pull, prometheus-cpp::push, ### prometheus-cpp::core, and curl imported targets -if(GKFS_ENABLE_PROMETHEUS) +if (GKFS_ENABLE_PROMETHEUS) find_package(CURL 7.68.0 REQUIRED) find_package(prometheus-cpp REQUIRED) # >= 1.0.0 -endif() +endif () ### Other stuff that can be found out using find_package: @@ -226,10 +226,10 @@ set(GKFS_DEPENDENCIES_PATH ${CMAKE_SOURCE_DIR}/external) ### {fmt}: required for sensible output formatting set(FMT_INSTALL OFF) include_from_source(fmt - MESSAGE "[${PROJECT_NAME}] Searching for {fmt}" - SOURCE_DIR ${GKFS_DEPENDENCIES_PATH}/fmt - GIT_REPOSITORY https://github.com/fmtlib/fmt - GIT_TAG e57ca2e3685b160617d3d95fcd9e789c4e06ca88 # v10.1.0 + MESSAGE "[${PROJECT_NAME}] Searching for {fmt}" + SOURCE_DIR ${GKFS_DEPENDENCIES_PATH}/fmt + GIT_REPOSITORY https://github.com/fmtlib/fmt + GIT_TAG e57ca2e3685b160617d3d95fcd9e789c4e06ca88 # v10.1.0 ) # ensure that fmt is linked as PIC @@ -237,19 +237,19 @@ set_property(TARGET fmt PROPERTY POSITION_INDEPENDENT_CODE ON) ### spdlog: required for logging include_from_source(spdlog - MESSAGE "[${PROJECT_NAME}] Searching for spdlog" - SOURCE_DIR ${GKFS_DEPENDENCIES_PATH}/spdlog - GIT_REPOSITORY https://github.com/gabime/spdlog.git - GIT_TAG eb3220622e73a4889eee355ffa37972b3cac3df5 # v1.9.2 - ) + MESSAGE "[${PROJECT_NAME}] Searching for spdlog" + SOURCE_DIR ${GKFS_DEPENDENCIES_PATH}/spdlog + GIT_REPOSITORY https://github.com/gabime/spdlog.git + GIT_TAG eb3220622e73a4889eee355ffa37972b3cac3df5 # v1.9.2 +) ### CLI11: used for parsing command-line options include_from_source(cli11 - MESSAGE "[${PROJECT_NAME}] Searching for CLI11" - SOURCE_DIR ${GKFS_DEPENDENCIES_PATH}/CLI11 - GIT_REPOSITORY https://github.com/CLIUtils/CLI11 - GIT_TAG v2.2.0 - ) + MESSAGE "[${PROJECT_NAME}] Searching for CLI11" + SOURCE_DIR ${GKFS_DEPENDENCIES_PATH}/CLI11 + GIT_REPOSITORY https://github.com/CLIUtils/CLI11 + GIT_TAG v2.2.0 +) if (GKFS_ENABLE_CLIENT_METRICS) ### MessagePack: used for monitoring information on the client @@ -264,9 +264,9 @@ endif () ################################################################################ ## Check configured variables/options and act accordingly ################################################################################ -if(GKFS_BUILD_DOCUMENTATION) +if (GKFS_BUILD_DOCUMENTATION) add_subdirectory(docs) -endif() +endif () if (GKFS_SYMLINK_SUPPORT) add_definitions(-DHAS_SYMLINKS) @@ -287,30 +287,30 @@ if (GKFS_RENAME_SUPPORT) add_definitions(-DHAS_RENAME) endif () -if(GKFS_MAX_INTERNAL_FDS) +if (GKFS_MAX_INTERNAL_FDS) add_definitions(-DGKFS_MAX_INTERNAL_FDS=${GKFS_MAX_INTERNAL_FDS}) -endif() +endif () -if(GKFS_MAX_OPEN_FDS) +if (GKFS_MAX_OPEN_FDS) add_definitions(-DGKFS_MAX_OPEN_FDS=${GKFS_MAX_OPEN_FDS}) -endif() +endif () -if(GKFS_ENABLE_CLIENT_LOG) +if (GKFS_ENABLE_CLIENT_LOG) add_definitions(-DGKFS_ENABLE_LOGGING) add_definitions(-DLIBGKFS_LOG_MESSAGE_SIZE=${GKFS_CLIENT_LOG_MESSAGE_SIZE}) endif () -if(GKFS_ENABLE_UNUSED_FUNCTIONS) +if (GKFS_ENABLE_UNUSED_FUNCTIONS) add_definitions(-DGKFS_ENABLE_UNUSED_FUNCTIONS) endif () -if(GKFS_ENABLE_PROMETHEUS) +if (GKFS_ENABLE_PROMETHEUS) add_definitions(-DGKFS_ENABLE_PROMETHEUS) endif () configure_file(include/common/cmake_configure.hpp.in include/common/cmake_configure.hpp) -if(GKFS_ENABLE_CLIENT_LOG) +if (GKFS_ENABLE_CLIENT_LOG) option(HERMES_LOGGING "" ON) option(HERMES_LOGGING_FMT_USE_BUNDLED "" OFF) option(HERMES_LOGGING_FMT_HEADER_ONLY "" OFF) @@ -369,15 +369,15 @@ if (GKFS_BUILD_TESTS) message(STATUS "[gekkofs] Check for guided distributor tests...") if (GKFS_USE_GUIDED_DISTRIBUTION) set(GKFS_TESTS_GUIDED_DISTRIBUTION "ON" CACHE STRING "Enable guided distributor tests (default: OFF)") - else() + else () set(GKFS_TESTS_GUIDED_DISTRIBUTION "OFF" CACHE STRING "Enable guided distributor tests (default: OFF)") - endif() + endif () message(STATUS "[gekkofs] Guided distributor tests: ${GKFS_TESTS_GUIDED_DISTRIBUTION}") add_subdirectory(tests) -else() +else () unset(GKFS_TESTS_INTERFACE CACHE) -endif() +endif () ################################################################################ ## Print GekkoFS configuration summary diff --git a/README.md b/README.md index 0343fff7951c10a9e21e5188f6492057e02badec..6201fa9642b70350cc0f9149ab817d90d4df0bd2 100644 --- a/README.md +++ b/README.md @@ -517,6 +517,9 @@ Client-metrics require the CMake argument `-DGKFS_ENABLE_CLIENT_METRICS=ON` (see - `LIBGKFS_METRICS_IP_PORT` - Enable flushing to a set ZeroMQ server (replaces `LIBGKFS_METRICS_PATH`). - `LIBGKFS_PROXY_PID_FILE` - Path to the proxy pid file (when using the GekkoFS proxy). - `LIBGKFS_NUM_REPL` - Number of replicas for data. +#### Caching +- `LIBGKFS_DENTRY_CACHE` - Enable caching directory entries until closing the directory (default: OFF). +Improves performance for `ls -l` type operations. Further compile-time settings available at `include/config.hpp`. ### Daemon #### Logging diff --git a/include/client/CMakeLists.txt b/include/client/CMakeLists.txt index e4ce8983c2f1d91a77ea76ed9523b74f35696e32..6d3594b0ae6b420b642dd0ae250198964556cc8e 100644 --- a/include/client/CMakeLists.txt +++ b/include/client/CMakeLists.txt @@ -29,56 +29,58 @@ # common sources to both gkfs_intercept and gkfwd_intercept target_sources( - gkfs_intercept - PUBLIC gkfs_functions.hpp - env.hpp - hooks.hpp - intercept.hpp - logging.hpp - make_array.hpp - open_file_map.hpp - open_dir.hpp - path.hpp - preload.hpp - preload_context.hpp - preload_util.hpp - rpc/rpc_types.hpp - rpc/forward_management.hpp - rpc/forward_metadata.hpp - rpc/forward_data.hpp - syscalls/args.hpp - syscalls/decoder.hpp - syscalls/errno.hpp - syscalls/rets.hpp - syscalls/syscall.hpp - syscalls/detail/syscall_info.h + gkfs_intercept + PUBLIC gkfs_functions.hpp + env.hpp + hooks.hpp + intercept.hpp + logging.hpp + make_array.hpp + open_file_map.hpp + open_dir.hpp + path.hpp + preload.hpp + preload_context.hpp + preload_util.hpp + cache.hpp + rpc/rpc_types.hpp + rpc/forward_management.hpp + rpc/forward_metadata.hpp + rpc/forward_data.hpp + syscalls/args.hpp + syscalls/decoder.hpp + syscalls/errno.hpp + syscalls/rets.hpp + syscalls/syscall.hpp + syscalls/detail/syscall_info.h ) target_sources( - gkfs_user_lib - PUBLIC gkfs_functions.hpp - env.hpp - hooks.hpp - intercept.hpp - logging.hpp - make_array.hpp - open_file_map.hpp - open_dir.hpp - path.hpp - preload.hpp - preload_context.hpp - preload_util.hpp - rpc/rpc_types.hpp - rpc/forward_management.hpp - rpc/forward_metadata.hpp - rpc/forward_data.hpp + gkfs_user_lib + PUBLIC gkfs_functions.hpp + env.hpp + hooks.hpp + intercept.hpp + logging.hpp + make_array.hpp + open_file_map.hpp + open_dir.hpp + path.hpp + preload.hpp + preload_context.hpp + preload_util.hpp + cache.hpp + rpc/rpc_types.hpp + rpc/forward_management.hpp + rpc/forward_metadata.hpp + rpc/forward_data.hpp rpc/forward_malleability.hpp - syscalls/args.hpp - syscalls/decoder.hpp - syscalls/errno.hpp - syscalls/rets.hpp - syscalls/syscall.hpp - syscalls/detail/syscall_info.h - void_syscall_intercept.hpp - user_functions.hpp + syscalls/args.hpp + syscalls/decoder.hpp + syscalls/errno.hpp + syscalls/rets.hpp + syscalls/syscall.hpp + syscalls/detail/syscall_info.h + void_syscall_intercept.hpp + user_functions.hpp ) diff --git a/include/client/cache.hpp b/include/client/cache.hpp new file mode 100644 index 0000000000000000000000000000000000000000..87a5de813a8481ac5c1fd6542c7d3a307da1dac1 --- /dev/null +++ b/include/client/cache.hpp @@ -0,0 +1,137 @@ +/* + Copyright 2018-2024, Barcelona Supercomputing Center (BSC), Spain + Copyright 2015-2024, Johannes Gutenberg Universitaet Mainz, Germany + + This software was partially supported by the + EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu). + + This software was partially supported by the + ADA-FS project under the SPPEXA project funded by the DFG. + + This file is part of GekkoFS' POSIX interface. + + GekkoFS' POSIX interface is free software: you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GekkoFS' POSIX interface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with GekkoFS' POSIX interface. If not, see + . + + SPDX-License-Identifier: LGPL-3.0-or-later +*/ + +#ifndef GKFS_CLIENT_CACHE +#define GKFS_CLIENT_CACHE + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace gkfs::cache { + +namespace dir { + +/** + * @brief Cache entry metadata. + * The entries are limited to the get_dir_extended RPC. + */ +struct cache_entry { + gkfs::filemap::FileType file_type; + uint64_t size; + time_t ctime; +}; + +/** + * @brief Cache for directory entries to accelerate ls -l type operations + */ +class DentryCache { +private: + // >: Associate a directory id with its entries + // containing the directory name and cache entry metadata + std::unordered_map> + entries_; + // : Associate a directory path with a unique id + std::unordered_map entry_dir_id_; + std::mutex mtx_; // Mutex to protect the cache + std::hash str_hash; // hash to generate ids + + /** + * @brief Generate a unique id for caching a directory + * @param dir_path + * @return id + */ + uint32_t + gen_dir_id(const std::string& dir_path); + + /** + * @brief Get the unique id for a directory to retrieve its entries. Creates + * an id if it does not exist. + * @param dir_path + * @return id + */ + uint32_t + get_dir_id(const std::string& dir_path); + +public: + DentryCache() = default; + + virtual ~DentryCache() = default; + + /** + * @brief Insert a new entry in the cache + * @param parent_dir + * @param name + * @param value + */ + void + insert(const std::string& parent_dir, std::string name, cache_entry value); + + /** + * @brief Get an entry from the cache for a given directory + * @param parent_dir + * @param name + * @return std::optional + */ + std::optional + get(const std::string& parent_dir, const std::string& name); + + /** + * @brief Clear the cache for a given directory. Called when a directory is + * closed + * @param dir_path + */ + void + clear_dir(const std::string& dir_path); + + /** + * @brief Dump the cache to the log for debugging purposes. Not used in + * production. + * @param dir_path + */ + void + dump_cache_to_log(const std::string& dir_path); + + /** + * @brief Clear the entire cache + */ + void + clear(); +}; +} // namespace dir + +} // namespace gkfs::cache + +#endif // GKFS_CLIENT_CACHE diff --git a/include/client/env.hpp b/include/client/env.hpp index 5574df2477650c4499ea84ad6cfde344614640fc..231d9c6adbda15eb6697c37f8e0102cf6cf2fcd8 100644 --- a/include/client/env.hpp +++ b/include/client/env.hpp @@ -60,6 +60,7 @@ static constexpr auto METRICS_IP_PORT = ADD_PREFIX("METRICS_IP_PORT"); static constexpr auto NUM_REPL = ADD_PREFIX("NUM_REPL"); static constexpr auto PROXY_PID_FILE = ADD_PREFIX("PROXY_PID_FILE"); +static constexpr auto DENTRY_CACHE = ADD_PREFIX("DENTRY_CACHE"); } // namespace gkfs::env diff --git a/include/client/preload_context.hpp b/include/client/preload_context.hpp index 95d2f8093fec6d7b817351d06ceefa8307286c02..662b092440fc446c931a6a5bcf5fba925d16e69e 100644 --- a/include/client/preload_context.hpp +++ b/include/client/preload_context.hpp @@ -55,6 +55,12 @@ namespace messagepack { class ClientMetrics; } +namespace cache { +namespace dir { +class DentryCache; +} +} // namespace cache + namespace preload { /* * Client file system config @@ -90,6 +96,8 @@ private: std::shared_ptr ofm_; std::shared_ptr distributor_; std::shared_ptr fs_conf_; + std::shared_ptr dentry_cache_; + bool use_dentry_cache_{false}; std::string cwd_; std::vector mountdir_components_; @@ -229,6 +237,19 @@ public: const std::shared_ptr& fs_conf() const; + std::shared_ptr + dentry_cache() const; + + void + dentry_cache(std::shared_ptr dentry_cache); + + bool + use_dentry_cache() const; + + void + use_dentry_cache(bool use_dentry_cache); + + void enable_interception(); diff --git a/include/common/CMakeLists.txt b/include/common/CMakeLists.txt index 73861334eda2188b7aaca7f650d547443bcef250..8e23d110f0a40f046bc956ca1b0d451553c0bb45 100644 --- a/include/common/CMakeLists.txt +++ b/include/common/CMakeLists.txt @@ -27,8 +27,8 @@ ################################################################################ target_sources( - gkfs_daemon PUBLIC cmake_configure.hpp.in common_defs.hpp rpc/rpc_types.hpp - rpc/rpc_util.hpp + gkfs_daemon PUBLIC cmake_configure.hpp.in common_defs.hpp rpc/rpc_types.hpp + rpc/rpc_util.hpp ) target_sources(gkfs_proxy diff --git a/include/common/common_defs.hpp b/include/common/common_defs.hpp index 58a67f17cd5074d1eb8c0900509a9c4f92ec2d09..bd1647801d247b73358c33975b841c1eac9a7384 100644 --- a/include/common/common_defs.hpp +++ b/include/common/common_defs.hpp @@ -120,6 +120,8 @@ constexpr auto migrate_metadata = "rpc_srv_migrate_metadata"; namespace config::syscall::stat { // Number 512-byte blocks allocated as it is in the linux kernel (struct_stat.h) constexpr auto st_nblocksize = 512; +constexpr auto file_mode_default = 33188; +constexpr auto dir_mode_default = 16895; } // namespace config::syscall::stat } // namespace gkfs #endif // GEKKOFS_COMMON_DEFS_HPP diff --git a/include/config.hpp b/include/config.hpp index e859b20f3d074aa1f9e28b4aceb715f2f4f0ba7f..899beff7b023b96573b52edd4c690df24030c31e 100644 --- a/include/config.hpp +++ b/include/config.hpp @@ -46,6 +46,14 @@ constexpr auto hostfile_path = "./gkfs_hosts.txt"; // We do not default this, ENV variable always required. constexpr auto forwarding_file_path = ""; +namespace cache { +// Optimization for readdir which avoids consecutive stat calls +constexpr bool use_dentry_cache = false; +// When enabled, the dentry cache is cleared when a directory is closed. +// Disabling this may cause semantic issues. +constexpr bool clear_dentry_cache_on_close = true; +} // namespace cache + namespace client_metrics { // Default directory where client metrics are stored. Can be set via // LIBGKFS_METRICS_PATH. Filename consists of starting time, pid, and hostname diff --git a/include/daemon/CMakeLists.txt b/include/daemon/CMakeLists.txt index 977c51cbd407bf48fdd7e70b48770e53bc416e93..2eb53c12af63cf07b5b5190b4423538bfdfeda1a 100644 --- a/include/daemon/CMakeLists.txt +++ b/include/daemon/CMakeLists.txt @@ -27,19 +27,19 @@ ################################################################################ target_sources( - gkfs_daemon - PUBLIC daemon.hpp - util.hpp - ops/data.hpp - ops/metadentry.hpp - classes/fs_data.hpp - classes/rpc_data.hpp - handler/rpc_defs.hpp - handler/rpc_util.hpp + gkfs_daemon + PUBLIC daemon.hpp + util.hpp + ops/data.hpp + ops/metadentry.hpp + classes/fs_data.hpp + classes/rpc_data.hpp + handler/rpc_defs.hpp + handler/rpc_util.hpp malleability/malleable_manager.hpp malleability/rpc/forward_redistribution.hpp ) -if(GKFS_ENABLE_AGIOS) - target_sources(gkfwd_daemon PUBLIC scheduler/agios.hpp) -endif() +if (GKFS_ENABLE_AGIOS) + target_sources(gkfwd_daemon PUBLIC scheduler/agios.hpp) +endif () diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index e2a53a0826e59b91889a981bb51b1e100b4ae6b2..333c66269f671a9aa51999adbb78ab6b4e6bfcd7 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -32,108 +32,110 @@ # based on syscall interception. # ############################################################################## -add_library (gkfs_intercept SHARED) -add_library (gkfs_user_lib SHARED) +add_library(gkfs_intercept SHARED) +add_library(gkfs_user_lib SHARED) target_sources(gkfs_intercept - PRIVATE gkfs_functions.cpp - intercept.cpp - hooks.cpp - logging.cpp - open_file_map.cpp - open_dir.cpp - path.cpp - preload.cpp - preload_context.cpp - preload_util.cpp - rpc/rpc_types.cpp - rpc/forward_data.cpp - rpc/forward_data_proxy.cpp - rpc/forward_management.cpp - rpc/forward_metadata.cpp - rpc/forward_metadata_proxy.cpp - syscalls/detail/syscall_info.c) + PRIVATE gkfs_functions.cpp + intercept.cpp + hooks.cpp + logging.cpp + open_file_map.cpp + open_dir.cpp + path.cpp + preload.cpp + preload_context.cpp + preload_util.cpp + cache.cpp + rpc/rpc_types.cpp + rpc/forward_data.cpp + rpc/forward_data_proxy.cpp + rpc/forward_management.cpp + rpc/forward_metadata.cpp + rpc/forward_metadata_proxy.cpp + syscalls/detail/syscall_info.c) target_sources( - gkfs_user_lib - PRIVATE gkfs_functions.cpp - intercept.cpp - hooks.cpp - logging.cpp - open_file_map.cpp - open_dir.cpp - path.cpp - preload.cpp - preload_context.cpp - preload_util.cpp - malleability.cpp - rpc/rpc_types.cpp - rpc/forward_data.cpp - rpc/forward_data_proxy.cpp - rpc/forward_management.cpp - rpc/forward_metadata.cpp - rpc/forward_metadata_proxy.cpp - rpc/forward_malleability.cpp - syscalls/detail/syscall_info.c syscalls/util.S + gkfs_user_lib + PRIVATE gkfs_functions.cpp + intercept.cpp + hooks.cpp + logging.cpp + open_file_map.cpp + open_dir.cpp + path.cpp + preload.cpp + preload_context.cpp + preload_util.cpp + malleability.cpp + cache.cpp + rpc/rpc_types.cpp + rpc/forward_data.cpp + rpc/forward_data_proxy.cpp + rpc/forward_management.cpp + rpc/forward_metadata.cpp + rpc/forward_metadata_proxy.cpp + rpc/forward_malleability.cpp + syscalls/detail/syscall_info.c syscalls/util.S ) target_compile_definitions(gkfs_user_lib PUBLIC BYPASS_SYSCALL) target_link_options(gkfs_user_lib PRIVATE -z noexecstack) -if(GKFS_ENABLE_AGIOS) - target_compile_definitions(gkfs_intercept PUBLIC GKFS_ENABLE_AGIOS) -endif() +if (GKFS_ENABLE_AGIOS) + target_compile_definitions(gkfs_intercept PUBLIC GKFS_ENABLE_AGIOS) +endif () # Enable MSGPack metrics for intercept only target_link_libraries( - gkfs_intercept - PRIVATE metadata distributor env_util arithmetic path_util rpc_utils - PUBLIC dl - Mercury::Mercury - hermes - fmt::fmt - Threads::Threads - Syscall_intercept::Syscall_intercept + gkfs_intercept + PRIVATE metadata distributor env_util arithmetic path_util rpc_utils + PUBLIC dl + Mercury::Mercury + hermes + fmt::fmt + Threads::Threads + Syscall_intercept::Syscall_intercept ) # Enable MSGPack metrics for intercept only if (GKFS_ENABLE_CLIENT_METRICS) - target_link_libraries( - gkfs_intercept - PUBLIC - msgpack_util - ) - target_compile_definitions(gkfs_intercept PUBLIC GKFS_ENABLE_CLIENT_METRICS) + target_link_libraries( + gkfs_intercept + PUBLIC + msgpack_util + ) + target_compile_definitions(gkfs_intercept PUBLIC GKFS_ENABLE_CLIENT_METRICS) endif () target_link_libraries( - gkfs_user_lib - PRIVATE metadata distributor env_util arithmetic path_util rpc_utils - PUBLIC dl - Mercury::Mercury - hermes - fmt::fmt - Threads::Threads + gkfs_user_lib + PRIVATE metadata distributor env_util arithmetic path_util rpc_utils + PUBLIC dl + Mercury::Mercury + hermes + fmt::fmt + Threads::Threads ) install( - TARGETS gkfs_intercept - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gkfs + TARGETS gkfs_intercept + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gkfs ) -set_target_properties(gkfs_user_lib - PROPERTIES - PUBLIC_HEADER "../../include/client/void_syscall_intercept.hpp" - PUBLIC_HEADER "../../include/client/user_functions.hpp" +set_target_properties(gkfs_user_lib + PROPERTIES + PUBLIC_HEADER "../../include/client/void_syscall_intercept.hpp" + PUBLIC_HEADER "../../include/client/user_functions.hpp" ) install( - TARGETS gkfs_user_lib - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gkfs + TARGETS gkfs_user_lib + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gkfs ) diff --git a/src/client/cache.cpp b/src/client/cache.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad75d4c9a9ac720dff098e8ca78f9f5b4cdb3911 --- /dev/null +++ b/src/client/cache.cpp @@ -0,0 +1,129 @@ +/* + Copyright 2018-2024, Barcelona Supercomputing Center (BSC), Spain + Copyright 2015-2024, Johannes Gutenberg Universitaet Mainz, Germany + + This software was partially supported by the + EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu). + + This software was partially supported by the + ADA-FS project under the SPPEXA project funded by the DFG. + + This file is part of GekkoFS' POSIX interface. + + GekkoFS' POSIX interface is free software: you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GekkoFS' POSIX interface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with GekkoFS' POSIX interface. If not, see + . + + SPDX-License-Identifier: LGPL-3.0-or-later +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace gkfs::cache { + +namespace dir { + +uint32_t +DentryCache::gen_dir_id(const std::string& dir_path) { + // While collisions can theoretically occur, they are extremely unlikely as + // clients are ephemeral and thus the lifetime of a cached directory as + // well. + return str_hash(dir_path); +} + +uint32_t +DentryCache::get_dir_id(const std::string& dir_path) { + // check if id already exists in map and return + if(entry_dir_id_.find(dir_path) != entry_dir_id_.end()) { + return entry_dir_id_[dir_path]; + } + // otherwise generate one + auto dir_id = gen_dir_id(dir_path); + entry_dir_id_.emplace(dir_path, dir_id); + return dir_id; +} + + +void +DentryCache::insert(const std::string& parent_dir, const std::string name, + const cache_entry value) { + std::lock_guard const lock(mtx_); + auto dir_id = get_dir_id(parent_dir); + entries_[dir_id].emplace(name, value); +} + +std::optional +DentryCache::get(const std::string& parent_dir, const std::string& name) { + std::lock_guard const lock(mtx_); + auto dir_id = get_dir_id(parent_dir); + if(entries_[dir_id].find(name) != entries_[dir_id].end()) { + return entries_[dir_id][name]; + } else { + return {}; + } +} + +void +DentryCache::clear_dir(const std::string& dir_path) { + std::lock_guard const lock(mtx_); + + auto id_it = entry_dir_id_.find(dir_path); + if(id_it == entry_dir_id_.end()) { + return; + } + auto entry_it = entries_.find(id_it->second); + if(entry_it != entries_.end()) { + entries_.erase(entry_it); + } + entry_dir_id_.erase(id_it); +} + +void +DentryCache::dump_cache_to_log(const std::string& dir_path) { + std::lock_guard const lock(mtx_); + auto id_it = entry_dir_id_.find(dir_path); + if(id_it == entry_dir_id_.end()) { + LOG(INFO, "{}(): Cache contents for dir path '{}' NONE", __func__, + dir_path); + return; + } + auto dir_id = id_it->second; + for(auto& [name, entry] : entries_[dir_id]) { + // log entry + LOG(INFO, + "{}(): Cache contents for dir path '{}' -> name '{}' is_dir '{}' size '{}' ctime '{}'", + __func__, dir_path, name, + entry.file_type == gkfs::filemap::FileType::directory, entry.size, + entry.ctime); + } +} + +void +DentryCache::clear() { + std::lock_guard const lock(mtx_); + entries_.clear(); + entry_dir_id_.clear(); +} + +} // namespace dir + +} // namespace gkfs::cache diff --git a/src/client/gkfs_functions.cpp b/src/client/gkfs_functions.cpp index ec04145f1fc169239e80e0f961bf78d8ffcd5d01..a5cc35100796cc46b021cd92655c8beb1cd8d924 100644 --- a/src/client/gkfs_functions.cpp +++ b/src/client/gkfs_functions.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #ifdef GKFS_ENABLE_CLIENT_METRICS @@ -1322,12 +1323,60 @@ gkfs_opendir(const std::string& path) { } if(!S_ISDIR(md->mode())) { - LOG(DEBUG, "Path is not a directory"); + LOG(DEBUG, "{}() Path is not a directory", __func__); errno = ENOTDIR; return -1; } - - auto ret = gkfs::rpc::forward_get_dirents(path); + pair> ret{}; + // Use cache: Get all entries from all servers for the basic metadata + // this is used in get_metadata() later to avoid stat RPCs + if(CTX->use_dentry_cache()) { + ret.second = make_shared(path); + std::vector, + bool, size_t, time_t>>>>>> + dcache_futures; + LOG(DEBUG, + "{}() Sending async dirents for path '{}' to '{}' daemons ...", + __func__, path, CTX->hosts().size()); + // Launch RPC calls asynchronously + for(uint64_t i = 0; i < CTX->hosts().size(); i++) { + dcache_futures.push_back(std::async(std::launch::async, [&, i]() { + if(gkfs::config::proxy::fwd_get_dirents_single && + CTX->use_proxy()) { + return gkfs::rpc::forward_get_dirents_single_proxy(path, i); + } else { + return gkfs::rpc::forward_get_dirents_single(path, i); + } + })); + } + int cnt = 0; + // Collect and process results + for(auto& fut : dcache_futures) { + auto res = fut.get(); // Wait for the RPC result + auto& open_dir = *res.second; + for(auto& dentry : open_dir) { + // type returns as a boolean. true if it is a directory + LOG(DEBUG, "name: {} type: {} size: {} ctime: {}", + get<0>(dentry), get<1>(dentry), get<2>(dentry), + get<3>(dentry)); + auto ftype = get<1>(dentry) ? gkfs::filemap::FileType::directory + : gkfs::filemap::FileType::regular; + // filename, is_dir, size, ctime + ret.second->add(get<0>(dentry), ftype); + CTX->dentry_cache()->insert( + path, get<0>(dentry), + gkfs::cache::dir::cache_entry{ftype, get<2>(dentry), + get<3>(dentry)}); + cnt++; + } + ret.first = res.first; + } + LOG(DEBUG, "{}() Unpacked dirents for path '{}' counted '{}' entries", + __func__, path, cnt); + } else { + ret = gkfs::rpc::forward_get_dirents(path); + } auto err = ret.first; if(err) { errno = err; @@ -1389,7 +1438,6 @@ gkfs_rmdir(const std::string& path) { */ int gkfs_getdents(unsigned int fd, struct linux_dirent* dirp, unsigned int count) { - // Get opendir object (content was downloaded with opendir() call) auto open_dir = CTX->file_map()->get_dir(fd); if(open_dir == nullptr) { @@ -1464,7 +1512,6 @@ gkfs_getdents(unsigned int fd, struct linux_dirent* dirp, unsigned int count) { int gkfs_getdents64(unsigned int fd, struct linux_dirent64* dirp, unsigned int count) { - auto open_dir = CTX->file_map()->get_dir(fd); if(open_dir == nullptr) { // Cast did not succeeded: open_file is a regular file @@ -1533,6 +1580,15 @@ gkfs_getdents64(unsigned int fd, struct linux_dirent64* dirp, int gkfs_close(unsigned int fd) { if(CTX->file_map()->exist(fd)) { + if(CTX->use_dentry_cache() && + gkfs::config::cache::clear_dentry_cache_on_close) { + // clear cache for directory + if(CTX->file_map()->get(fd)->type() == + gkfs::filemap::FileType::directory) { + CTX->dentry_cache()->clear_dir( + CTX->file_map()->get(fd)->path()); + } + } // No call to the daemon is required CTX->file_map()->remove(fd); return 0; diff --git a/src/client/preload.cpp b/src/client/preload.cpp index 32a52ad56d0968f6bc7023369102c3aa5e8f35a4..52422c057139f89f2983bb5aacf81ac9868fe19a 100644 --- a/src/client/preload.cpp +++ b/src/client/preload.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -258,6 +259,30 @@ init_environment() { CTX->distributor(distributor); } + auto use_dcache = gkfs::env::get_var(gkfs::env::DENTRY_CACHE, + gkfs::config::cache::use_dentry_cache + ? "ON" + : "OFF") == "ON"; + if(use_dcache) { + try { + LOG(INFO, "Initializing dentry caching..."); + auto dentry_cache = + std::make_shared(); + CTX->dentry_cache(dentry_cache); + LOG(INFO, "dentry caching enabled."); + CTX->use_dentry_cache(true); + } catch(const std::exception& e) { + exit_error_msg(EXIT_FAILURE, + "Failed to initialize dentry cache: "s + e.what()); + } + } else { + if(gkfs::env::var_is_set(gkfs::env::DENTRY_CACHE)) { + LOG(INFO, "Dentry cache is disabled by environment variable."); + } else { + LOG(INFO, "Dentry cache is disabled by configuration."); + } + } + LOG(INFO, "Retrieving file system configuration..."); if(!gkfs::rpc::forward_get_fs_config()) { diff --git a/src/client/preload_context.cpp b/src/client/preload_context.cpp index 7ae774a902dda8561ea705e333ba7b5d8319a905..ccc41a0ea748d1c574d5c230d992c21d2451f8fd 100644 --- a/src/client/preload_context.cpp +++ b/src/client/preload_context.cpp @@ -412,6 +412,27 @@ PreloadContext::fs_conf() const { return fs_conf_; } +std::shared_ptr +PreloadContext::dentry_cache() const { + return dentry_cache_; +} + +void +PreloadContext::dentry_cache( + std::shared_ptr dentry_cache) { + dentry_cache_ = dentry_cache; +} + +bool +PreloadContext::use_dentry_cache() const { + return use_dentry_cache_; +} + +void +PreloadContext::use_dentry_cache(bool use_dentry_cache) { + use_dentry_cache_ = use_dentry_cache; +} + void PreloadContext::enable_interception() { interception_enabled_ = true; diff --git a/src/client/preload_util.cpp b/src/client/preload_util.cpp index 806db66395d988387f7c1277df8786a2f9370585..3737368f8c6721a9ae90f74cf7fbca47c47866d3 100644 --- a/src/client/preload_util.cpp +++ b/src/client/preload_util.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,7 @@ #include #include #include +#include extern "C" { #include @@ -209,6 +211,27 @@ optional get_metadata(const string& path, bool follow_links) { std::string attr; int err{}; + // Use file metadata from dentry cache if available + if(CTX->use_dentry_cache()) { + // get parent and filename path to retrieve the cache entry + std::filesystem::path p(path); + auto parent = p.parent_path().string(); + auto filename = p.filename().string(); + auto cache_entry = CTX->dentry_cache()->get(parent, filename); + if(cache_entry) { + LOG(DEBUG, "{}(): Dentry cache hit for file '{}'", __func__, path); + // if cache_entry exists, generate a Metadata object from it. + mode_t mode = gkfs::config::syscall::stat::file_mode_default; + if(cache_entry->file_type == gkfs::filemap::FileType::directory) { + mode = gkfs::config::syscall::stat::dir_mode_default; + } + gkfs::metadata::Metadata md{}; + md.mode(mode); + md.ctime(cache_entry->ctime); + md.size(cache_entry->size); + return md; + } + } if(gkfs::config::proxy::fwd_stat && CTX->use_proxy()) { err = gkfs::rpc::forward_stat_proxy(path, attr); } else { diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 789dd2d04cf237704c0010155be45ca0b7b881f7..89bc6c57fc7ba8da39f1303b316ac5a2f362925f 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -31,7 +31,7 @@ include(FetchContent) add_library(rpc_utils OBJECT) set_property(TARGET rpc_utils PROPERTY POSITION_INDEPENDENT_CODE ON) target_sources(rpc_utils - PRIVATE + PRIVATE rpc/rpc_util.cpp ) @@ -46,7 +46,7 @@ target_sources(distributor ${INCLUDE_DIR}/common/rpc/distributor.hpp PRIVATE ${CMAKE_CURRENT_LIST_DIR}/rpc/distributor.cpp - ) +) add_library(statistics STATIC) set_property(TARGET statistics PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -55,18 +55,18 @@ target_sources(statistics ${INCLUDE_DIR}/common/statistics/stats.hpp PRIVATE ${CMAKE_CURRENT_LIST_DIR}/statistics/stats.cpp - ) +) -if(GKFS_ENABLE_PROMETHEUS) - target_link_libraries(statistics - PRIVATE - prometheus-cpp::pull - prometheus-cpp::push - prometheus-cpp::core - curl +if (GKFS_ENABLE_PROMETHEUS) + target_link_libraries(statistics + PRIVATE + prometheus-cpp::pull + prometheus-cpp::push + prometheus-cpp::core + curl ) -endif() +endif () add_library(log_util STATIC) set_property(TARGET log_util PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -75,11 +75,11 @@ target_sources(log_util ${INCLUDE_DIR}/common/log_util.hpp PRIVATE ${CMAKE_CURRENT_LIST_DIR}/log_util.cpp - ) +) target_link_libraries(log_util - PUBLIC + PUBLIC spdlog::spdlog - ) +) add_library(env_util STATIC) set_property(TARGET env_util PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -89,7 +89,7 @@ target_sources(env_util PRIVATE ${INCLUDE_DIR}/config.hpp ${CMAKE_CURRENT_LIST_DIR}/env_util.cpp - ) +) add_library(metadata STATIC) set_property(TARGET metadata PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -98,11 +98,11 @@ target_sources(metadata ${INCLUDE_DIR}/common/metadata.hpp PRIVATE ${CMAKE_CURRENT_LIST_DIR}/metadata.cpp - ) +) target_link_libraries(metadata PRIVATE fmt::fmt - ) +) add_library(path_util STATIC) set_property(TARGET path_util PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -111,7 +111,7 @@ target_sources(path_util path_util.cpp PUBLIC ${INCLUDE_DIR}/common/path_util.hpp - ) +) if (GKFS_ENABLE_CLIENT_METRICS) add_library(msgpack_util STATIC) diff --git a/src/common/arithmetic/CMakeLists.txt b/src/common/arithmetic/CMakeLists.txt index d399c33b87e9bfe040836641355ed62bfc1d6b93..2716d0bcf52f4aa011a62bc12bb4369b7fee8f41 100644 --- a/src/common/arithmetic/CMakeLists.txt +++ b/src/common/arithmetic/CMakeLists.txt @@ -30,9 +30,9 @@ add_library(arithmetic INTERFACE) target_sources(arithmetic INTERFACE ${INCLUDE_DIR}/common/arithmetic/arithmetic.hpp - ) +) target_include_directories(arithmetic INTERFACE ${INCLUDE_DIR}/common/arithmetic/ - ) +) diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index d71a36d547874c2b64d8995794d3abfc4754eee5..f6c310bcdb56fd2bc88e654b360a0ade9d6bab6f 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -37,53 +37,53 @@ pkg_check_modules(URING IMPORTED_TARGET liburing) # We need to add here any files that may have different compile definitions target_sources( - gkfs_daemon - PRIVATE daemon.cpp - handler/srv_data.cpp - ../common/rpc/rpc_util.cpp - util.cpp - ops/metadentry.cpp - ops/data.cpp - classes/fs_data.cpp - classes/rpc_data.cpp - handler/srv_metadata.cpp - handler/srv_management.cpp + gkfs_daemon + PRIVATE daemon.cpp + handler/srv_data.cpp + ../common/rpc/rpc_util.cpp + util.cpp + ops/metadentry.cpp + ops/data.cpp + classes/fs_data.cpp + classes/rpc_data.cpp + handler/srv_metadata.cpp + handler/srv_management.cpp handler/srv_malleability.cpp malleability/malleable_manager.cpp malleability/rpc/forward_redistribution.cpp - PUBLIC ${CMAKE_SOURCE_DIR}/include/config.hpp - ${CMAKE_SOURCE_DIR}/include/version.hpp.in + PUBLIC ${CMAKE_SOURCE_DIR}/include/config.hpp + ${CMAKE_SOURCE_DIR}/include/version.hpp.in ) target_link_libraries( - gkfs_daemon - PUBLIC # internal libs - metadata - metadata_backend - storage - distributor - statistics - log_util - env_util - path_util - # external libs - CLI11::CLI11 - fmt::fmt - Mercury::Mercury - Argobots::Argobots - Margo::Margo - # others - Threads::Threads + gkfs_daemon + PUBLIC # internal libs + metadata + metadata_backend + storage + distributor + statistics + log_util + env_util + path_util + # external libs + CLI11::CLI11 + fmt::fmt + Mercury::Mercury + Argobots::Argobots + Margo::Margo + # others + Threads::Threads ) -if(GKFS_ENABLE_AGIOS) - target_sources(gkfs_daemon PRIVATE scheduler/agios.cpp) - target_compile_definitions(gkfs_daemon PUBLIC GKFS_ENABLE_AGIOS) - target_link_libraries(gkfs_daemon PRIVATE AGIOS::AGIOS) -endif() +if (GKFS_ENABLE_AGIOS) + target_sources(gkfs_daemon PRIVATE scheduler/agios.cpp) + target_compile_definitions(gkfs_daemon PUBLIC GKFS_ENABLE_AGIOS) + target_link_libraries(gkfs_daemon PRIVATE AGIOS::AGIOS) +endif () -if(GKFS_ENABLE_CODE_COVERAGE) +if (GKFS_ENABLE_CODE_COVERAGE) target_code_coverage(gkfs_daemon AUTO) -endif() +endif () install(TARGETS gkfs_daemon RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/src/daemon/backend/data/CMakeLists.txt b/src/daemon/backend/data/CMakeLists.txt index 4bb182fb49ae7ff4862156d7b3bce0967e49d02c..f23a9f1d38989e2aeb897dd88979b9f921d4913f 100644 --- a/src/daemon/backend/data/CMakeLists.txt +++ b/src/daemon/backend/data/CMakeLists.txt @@ -28,17 +28,17 @@ add_library(data_module STATIC - ) +) target_sources(data_module PUBLIC ${INCLUDE_DIR}/daemon/backend/data/data_module.hpp PRIVATE ${CMAKE_CURRENT_LIST_DIR}/data_module.cpp - ) +) target_link_libraries(data_module - PRIVATE + PRIVATE log_util ) @@ -51,7 +51,7 @@ target_sources(storage ${INCLUDE_DIR}/common/common_defs.hpp ${INCLUDE_DIR}/daemon/backend/data/file_handle.hpp ${CMAKE_CURRENT_LIST_DIR}/chunk_storage.cpp - ) +) target_link_libraries(storage PRIVATE @@ -61,7 +61,7 @@ target_link_libraries(storage # open issue for std::filesystem https://gitlab.kitware.com/cmake/cmake/-/issues/17834 stdc++fs -ldl - ) +) #target_include_directories(storage # PRIVATE diff --git a/src/daemon/backend/metadata/CMakeLists.txt b/src/daemon/backend/metadata/CMakeLists.txt index 878663ff4688c5dca51111210cbb68d207cc8f16..0468e7cf83d894305f5b82ed28a8b3c69139d832 100644 --- a/src/daemon/backend/metadata/CMakeLists.txt +++ b/src/daemon/backend/metadata/CMakeLists.txt @@ -29,54 +29,54 @@ # Define metadata module library first add_library(metadata_module STATIC) target_sources( - metadata_module - PUBLIC ${CMAKE_SOURCE_DIR}/include/daemon/backend/metadata/metadata_module.hpp - PRIVATE metadata_module.cpp + metadata_module + PUBLIC ${CMAKE_SOURCE_DIR}/include/daemon/backend/metadata/metadata_module.hpp + PRIVATE metadata_module.cpp ) target_link_libraries(metadata_module PRIVATE log_util) # Define metadata_backend and its common dependencies and sources add_library(metadata_backend STATIC) target_sources( - metadata_backend - PUBLIC + metadata_backend + PUBLIC ${CMAKE_SOURCE_DIR}/include/daemon/backend/metadata/db.hpp ${CMAKE_SOURCE_DIR}/include/daemon/backend/exceptions.hpp ${CMAKE_SOURCE_DIR}/include/daemon/backend/metadata/metadata_backend.hpp - PRIVATE ${CMAKE_SOURCE_DIR}/include/daemon/backend/metadata/merge.hpp - merge.cpp db.cpp + PRIVATE ${CMAKE_SOURCE_DIR}/include/daemon/backend/metadata/merge.hpp + merge.cpp db.cpp ) target_link_libraries( - metadata_backend - PRIVATE metadata_module dl log_util path_util + metadata_backend + PRIVATE metadata_module dl log_util path_util ) -if(GKFS_ENABLE_ROCKSDB) - target_sources( - metadata_backend - PUBLIC ${CMAKE_SOURCE_DIR}/include/daemon/backend/metadata/rocksdb_backend.hpp - PRIVATE rocksdb_backend.cpp - ) +if (GKFS_ENABLE_ROCKSDB) + target_sources( + metadata_backend + PUBLIC ${CMAKE_SOURCE_DIR}/include/daemon/backend/metadata/rocksdb_backend.hpp + PRIVATE rocksdb_backend.cpp + ) - # If liburing is available in the system, RocksDB will have been built - # with liburing support. If so, we need to propagate the dependency to - # the daemon. Since liburing exports a pkg-config .pc file, we can use it - # to retrieve its details. - pkg_check_modules(URING IMPORTED_TARGET liburing) + # If liburing is available in the system, RocksDB will have been built + # with liburing support. If so, we need to propagate the dependency to + # the daemon. Since liburing exports a pkg-config .pc file, we can use it + # to retrieve its details. + pkg_check_modules(URING IMPORTED_TARGET liburing) - if(URING_FOUND) - target_link_libraries(metadata_backend PUBLIC PkgConfig::URING) - endif() + if (URING_FOUND) + target_link_libraries(metadata_backend PUBLIC PkgConfig::URING) + endif () - target_link_libraries(metadata_backend PUBLIC RocksDB::rocksdb) -endif() + target_link_libraries(metadata_backend PUBLIC RocksDB::rocksdb) +endif () -if(GKFS_ENABLE_PARALLAX) - target_sources(metadata_backend - PUBLIC ${CMAKE_SOURCE_DIR}/include/daemon/backend/metadata/parallax_backend.hpp - PRIVATE parallax_backend.cpp +if (GKFS_ENABLE_PARALLAX) + target_sources(metadata_backend + PUBLIC ${CMAKE_SOURCE_DIR}/include/daemon/backend/metadata/parallax_backend.hpp + PRIVATE parallax_backend.cpp ) - target_link_libraries(metadata_backend PUBLIC Parallax::parallax - Parallax::log) -endif() + target_link_libraries(metadata_backend PUBLIC Parallax::parallax + Parallax::log) +endif ()