From 4e98d05bd57ec9f34455226a0bff29ba893b68c8 Mon Sep 17 00:00:00 2001 From: Relintai Date: Wed, 25 Nov 2020 14:53:53 +0100 Subject: [PATCH] Implemented body caching and cleanups to FileCache. --- core/application.cpp | 4 +-- core/file_cache.cpp | 73 +++++++++++++++++++++++++++++++++++++------- core/file_cache.h | 36 +++++++++++++++++----- main.cpp | 4 +-- rdn_application.cpp | 20 +++++++++--- 5 files changed, 110 insertions(+), 27 deletions(-) diff --git a/core/application.cpp b/core/application.cpp index db9fa2f..0c8fa81 100644 --- a/core/application.cpp +++ b/core/application.cpp @@ -38,7 +38,7 @@ void Application::handle_request(Request *request) { std::string path = request->http_parser->getPath(); - if (FileCache::get_instance()->has_file(path)) { + if (FileCache::get_singleton()->wwwroot_has_file(path)) { send_file(path, request); return; @@ -92,7 +92,7 @@ void Application::send_error(int error_code, Request *request) { } void Application::send_file(const std::string &path, Request *request) { - std::string fp = FileCache::get_instance()->wwwroot + path; + std::string fp = FileCache::get_singleton()->wwwroot + path; FILE *f = fopen(fp.c_str(), "rb"); diff --git a/core/file_cache.cpp b/core/file_cache.cpp index 3c908e4..15cea3e 100644 --- a/core/file_cache.cpp +++ b/core/file_cache.cpp @@ -4,25 +4,25 @@ #include -void FileCache::register_file(const std::string &file_path) { +void FileCache::wwwroot_register_file(const std::string &file_path) { registered_files.insert(file_path); } -void FileCache::deregister_file(const std::string &file_path) { +void FileCache::wwwroot_deregister_file(const std::string &file_path) { registered_files.erase(file_path); } -bool FileCache::has_file(const std::string &file_path) { +bool FileCache::wwwroot_has_file(const std::string &file_path) { return registered_files.find(file_path) != registered_files.end(); } -void FileCache::refresh() { +void FileCache::wwwroot_refresh_cache() { registered_files.clear(); - evaluate_dir(wwwroot.c_str()); + wwwroot_evaluate_dir(wwwroot.c_str()); } -void FileCache::evaluate_dir(const char *path) { +void FileCache::wwwroot_evaluate_dir(const char *path) { tinydir_dir dir; if (tinydir_open(&dir, path) == -1) { printf("Error opening wwwroot!\n"); @@ -47,7 +47,7 @@ void FileCache::evaluate_dir(const char *path) { continue; } - evaluate_dir(file.path); + wwwroot_evaluate_dir(file.path); } tinydir_next(&dir); @@ -56,17 +56,68 @@ void FileCache::evaluate_dir(const char *path) { tinydir_close(&dir); } -FileCache::FileCache() { - _instance = this; +bool FileCache::get_cached_body(const std::string &path, std::string *body) { + //TODO ERROR MACRO body == null + + //this shouldn't need mutexes + + CacheEntry *e = cache_map[path]; + + if (!e) { + return false; + } + + int64_t current_timestamp = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + + int64_t diff = current_timestamp - e->timestamp; + + if (diff > cache_invalidation_time) { + return false; + } + + body->append(e->body); + + return true; +} + +void FileCache::set_cached_body(const std::string &path, const std::string &body) { + cache_mutex.lock(); + + CacheEntry *e = cache_map[path]; + + if (!e) { + e = new CacheEntry(); + cache_map[path] = e; + } + + int64_t current_timestamp = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + + e->timestamp = current_timestamp; + e->body = body; + + cache_mutex.unlock(); +} + +FileCache::FileCache(bool singleton) { + if (singleton) { + if (_instance) { + printf("FileCache: Filecache instance is set as singleton, but an another FileCache instance is already set up as singleton! Ignoring setting!\n"); + } else { + _instance = this; + } + } + + cache_invalidation_time = 1; } FileCache::~FileCache() { registered_files.clear(); - _instance = nullptr; + if (_instance == this) + _instance = nullptr; } -FileCache *FileCache::get_instance() { +FileCache *FileCache::get_singleton() { return _instance; } diff --git a/core/file_cache.h b/core/file_cache.h index c225f2e..2678eec 100644 --- a/core/file_cache.h +++ b/core/file_cache.h @@ -3,28 +3,48 @@ #include #include +#include +#include +#include class FileCache { public: std::string wwwroot; + int cache_invalidation_time; //Note: file path should be the url you want to access the file with, inculding lead slash //e.g. http://127.0.0.1/a/b/d.jpg -> /a/b/d.jpg - void register_file(const std::string &file_path); - void deregister_file(const std::string &file_path); + void wwwroot_register_file(const std::string &file_path); + void wwwroot_deregister_file(const std::string &file_path); + bool wwwroot_has_file(const std::string &file_path); + void wwwroot_refresh_cache(); + void wwwroot_evaluate_dir(const char *path); - bool has_file(const std::string &file_path); + bool get_cached_body(const std::string &path, std::string *body); + void set_cached_body(const std::string &path, const std::string &body); - void refresh(); - void evaluate_dir(const char *path); - - FileCache(); + FileCache(bool singleton = false); virtual ~FileCache(); - static FileCache *get_instance(); + static FileCache *get_singleton(); std::set registered_files; +protected: + + struct CacheEntry { + int64_t timestamp; + std::string body; + + CacheEntry() { + timestamp = 0; + } + }; + + std::mutex cache_mutex; + + std::map cache_map; + private: static FileCache *_instance; }; diff --git a/main.cpp b/main.cpp index d763cac..2d47b66 100644 --- a/main.cpp +++ b/main.cpp @@ -10,9 +10,9 @@ #define MAIN_CLASS RDNApplication int main(int argc, char **argv) { - FileCache *file_cache = new FileCache(); + FileCache *file_cache = new FileCache(true); file_cache->wwwroot = "./www"; - file_cache->refresh(); + file_cache->wwwroot_refresh_cache(); Application *app = new MAIN_CLASS(); diff --git a/rdn_application.cpp b/rdn_application.cpp index ffb98cd..282d9a1 100644 --- a/rdn_application.cpp +++ b/rdn_application.cpp @@ -4,16 +4,28 @@ #include -void RDNApplication::index(Request *request) { - //std::string body = "hello world aaaaa "; +#include "core/file_cache.h" - std::string body = ""; +void RDNApplication::index(Request *request) { + std::string body; + + if (FileCache::get_singleton()->get_cached_body("index", &body)) { + std::string body = "hello world aaaaa "; + + request->response->setBody(body); + + return; + } + + body = "hello world aaaaa "; + + FileCache::get_singleton()->set_cached_body("index", body); request->response->setBody(body); } void RDNApplication::session_middleware_func(Request *request) { - std::cout << "dddd" << std::endl; + std::cout << "dddd" << std::endl; } void RDNApplication::setup_routes() {