Implemented body caching and cleanups to FileCache.

This commit is contained in:
Relintai 2020-11-25 14:53:53 +01:00
parent dc3967c5f4
commit 4e98d05bd5
5 changed files with 110 additions and 27 deletions

View File

@ -38,7 +38,7 @@ void Application::handle_request(Request *request) {
std::string path = request->http_parser->getPath(); 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); send_file(path, request);
return; return;
@ -92,7 +92,7 @@ void Application::send_error(int error_code, Request *request) {
} }
void Application::send_file(const std::string &path, 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"); FILE *f = fopen(fp.c_str(), "rb");

View File

@ -4,25 +4,25 @@
#include <iostream> #include <iostream>
void FileCache::register_file(const std::string &file_path) { void FileCache::wwwroot_register_file(const std::string &file_path) {
registered_files.insert(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); 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(); return registered_files.find(file_path) != registered_files.end();
} }
void FileCache::refresh() { void FileCache::wwwroot_refresh_cache() {
registered_files.clear(); 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; tinydir_dir dir;
if (tinydir_open(&dir, path) == -1) { if (tinydir_open(&dir, path) == -1) {
printf("Error opening wwwroot!\n"); printf("Error opening wwwroot!\n");
@ -47,7 +47,7 @@ void FileCache::evaluate_dir(const char *path) {
continue; continue;
} }
evaluate_dir(file.path); wwwroot_evaluate_dir(file.path);
} }
tinydir_next(&dir); tinydir_next(&dir);
@ -56,17 +56,68 @@ void FileCache::evaluate_dir(const char *path) {
tinydir_close(&dir); tinydir_close(&dir);
} }
FileCache::FileCache() { bool FileCache::get_cached_body(const std::string &path, std::string *body) {
_instance = this; //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::seconds>(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::seconds>(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() { FileCache::~FileCache() {
registered_files.clear(); registered_files.clear();
_instance = nullptr; if (_instance == this)
_instance = nullptr;
} }
FileCache *FileCache::get_instance() { FileCache *FileCache::get_singleton() {
return _instance; return _instance;
} }

View File

@ -3,28 +3,48 @@
#include <string> #include <string>
#include <set> #include <set>
#include <map>
#include <chrono>
#include <mutex>
class FileCache { class FileCache {
public: public:
std::string wwwroot; std::string wwwroot;
int cache_invalidation_time;
//Note: file path should be the url you want to access the file with, inculding lead slash //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 //e.g. http://127.0.0.1/a/b/d.jpg -> /a/b/d.jpg
void register_file(const std::string &file_path); void wwwroot_register_file(const std::string &file_path);
void deregister_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(); FileCache(bool singleton = false);
void evaluate_dir(const char *path);
FileCache();
virtual ~FileCache(); virtual ~FileCache();
static FileCache *get_instance(); static FileCache *get_singleton();
std::set<std::string> registered_files; std::set<std::string> registered_files;
protected:
struct CacheEntry {
int64_t timestamp;
std::string body;
CacheEntry() {
timestamp = 0;
}
};
std::mutex cache_mutex;
std::map<std::string, CacheEntry *> cache_map;
private: private:
static FileCache *_instance; static FileCache *_instance;
}; };

View File

@ -10,9 +10,9 @@
#define MAIN_CLASS RDNApplication #define MAIN_CLASS RDNApplication
int main(int argc, char **argv) { int main(int argc, char **argv) {
FileCache *file_cache = new FileCache(); FileCache *file_cache = new FileCache(true);
file_cache->wwwroot = "./www"; file_cache->wwwroot = "./www";
file_cache->refresh(); file_cache->wwwroot_refresh_cache();
Application *app = new MAIN_CLASS(); Application *app = new MAIN_CLASS();

View File

@ -4,16 +4,28 @@
#include <iostream> #include <iostream>
void RDNApplication::index(Request *request) { #include "core/file_cache.h"
//std::string body = "<html>hello world aaaaa </html>";
std::string body = "<html><script>var blocked = false; document.addEventListener(\"visibilitychange\", function() { if (!blocked && document.hidden) {blocked = true;alert('Blocked once');}});</script></html>"; void RDNApplication::index(Request *request) {
std::string body;
if (FileCache::get_singleton()->get_cached_body("index", &body)) {
std::string body = "<html>hello world aaaaa </html>";
request->response->setBody(body);
return;
}
body = "<html>hello world aaaaa </html>";
FileCache::get_singleton()->set_cached_body("index", body);
request->response->setBody(body); request->response->setBody(body);
} }
void RDNApplication::session_middleware_func(Request *request) { void RDNApplication::session_middleware_func(Request *request) {
std::cout << "dddd" << std::endl; std::cout << "dddd" << std::endl;
} }
void RDNApplication::setup_routes() { void RDNApplication::setup_routes() {