From b71a49cfbeacdf44fa442663e44f367938b4b319 Mon Sep 17 00:00:00 2001 From: Pcornat Date: Sun, 21 Feb 2021 19:02:32 +0100 Subject: [PATCH] Caching of files is done : not tested yet. --- include/cache_files.hpp | 27 +++++++++++++++++++++++++- src/cache_files.cpp | 43 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/include/cache_files.hpp b/include/cache_files.hpp index 9aa1a0d..8034ef7 100644 --- a/include/cache_files.hpp +++ b/include/cache_files.hpp @@ -1,13 +1,38 @@ #ifndef GEMINISERVER_CACHE_FILES_HPP #define GEMINISERVER_CACHE_FILES_HPP +#include +#include +#include +#include namespace gemini { + struct Information; + /** * \brief This class is used to store the files in cache. */ - class CacheFiles { + class CacheFiles final { + private: + std::unordered_set files; + std::unordered_map content; + public: + const Information &information; + + CacheFiles() = delete; + + CacheFiles(const std::filesystem::path &folder, const Information &infos); + + ~CacheFiles() noexcept = default; + + [[nodiscard, gnu::always_inline]] inline const std::unordered_set &get_files() const { + return files; + } + + [[nodiscard, gnu::always_inline]] inline const std::unordered_map &get_content() const { + return content; + } }; } diff --git a/src/cache_files.cpp b/src/cache_files.cpp index 9366e7e..06700ae 100644 --- a/src/cache_files.cpp +++ b/src/cache_files.cpp @@ -1 +1,44 @@ #include "../include/cache_files.hpp" +#include +#include "../include/information.hpp" +#include + +namespace fs = std::filesystem; + +gemini::CacheFiles::CacheFiles(const std::filesystem::path &folder, const Information &infos) : information(infos) { + if (!fs::is_directory(folder)) { + spdlog::error("Path {} is not a folder", folder.string()); + throw std::runtime_error("Stopped in cache files constructor, see log."); + } + std::size_t global_cache = 0; + for (const auto &iterator : fs::directory_iterator(folder, fs::directory_options::follow_directory_symlink)) { + // Each time it finds a file, it is going to load it in memory and check if infos.cache_size is reached in terms of size. + if (!iterator.is_regular_file()) + continue; + const std::size_t file_size = [&]() -> std::size_t { + std::ifstream in(iterator.path()); + const std::size_t begin = in.tellg(); + in.seekg(0, std::ios::end); + return static_cast(in.tellg()) - begin; + }(); + global_cache += file_size; + + if (global_cache > infos.cache_size) + break; + + // I want to have the filename and not the whole path to be stored (less characters, less memory used). + const std::string filename = [&]() -> std::string { + const std::string_view path = iterator.path().string(); + const std::size_t pos = path.rfind('/'); + return iterator.path().string().substr(pos != std::string::npos ? pos + 1 : pos); + }(); + + if (files.insert(filename.empty() ? iterator.path().string() : filename).second) + spdlog::warn("File {} could not be registered", iterator.path().string()); + + std::ifstream file{ iterator.path() }; + if (!content.emplace(filename.empty() ? iterator.path().string() : filename, + std::string{ std::istreambuf_iterator(file), std::istreambuf_iterator() }).second) + spdlog::warn("File {} could not be loaded in cache", iterator.path().string()); + } +}