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();
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");

View File

@ -4,25 +4,25 @@
#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);
}
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::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() {
registered_files.clear();
_instance = nullptr;
if (_instance == this)
_instance = nullptr;
}
FileCache *FileCache::get_instance() {
FileCache *FileCache::get_singleton() {
return _instance;
}

View File

@ -3,28 +3,48 @@
#include <string>
#include <set>
#include <map>
#include <chrono>
#include <mutex>
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<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:
static FileCache *_instance;
};

View File

@ -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();

View File

@ -4,16 +4,28 @@
#include <iostream>
void RDNApplication::index(Request *request) {
//std::string body = "<html>hello world aaaaa </html>";
#include "core/file_cache.h"
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);
}
void RDNApplication::session_middleware_func(Request *request) {
std::cout << "dddd" << std::endl;
std::cout << "dddd" << std::endl;
}
void RDNApplication::setup_routes() {