Skip to content

Commit

Permalink
[Cache] Add caching mecanism
Browse files Browse the repository at this point in the history
  • Loading branch information
unkn0wn107 committed Jun 24, 2024
1 parent 7e76030 commit ea84bd1
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 13 deletions.
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# By: agaley <[email protected]> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2023/12/15 15:51:13 by agaley #+# #+# #
# Updated: 2024/06/24 22:57:11 by agaley ### ########lyon.fr #
# Updated: 2024/06/25 00:40:40 by agaley ### ########lyon.fr #
# #
# **************************************************************************** #

Expand All @@ -32,7 +32,7 @@ export NGINX_PORT_2 ?= 8001
SRC = $(SRC_DIR)/Server.cpp \
$(SRC_DIR)/Config.cpp $(SRC_DIR)/ConfigManager.cpp $(SRC_DIR)/ConfigParser.cpp \
$(SRC_DIR)/FileManager.cpp \
$(SRC_DIR)/ConnectionHandler.cpp \
$(SRC_DIR)/ConnectionHandler.cpp $(SRC_DIR)/CacheHandler.cpp \
$(SRC_DIR)/Worker.cpp \
$(SRC_DIR)/HTTPRequest.cpp $(SRC_DIR)/HTTPResponse.cpp $(SRC_DIR)/URI.cpp \
$(SRC_DIR)/CGIHandler.cpp $(SRC_DIR)/FileHandler.cpp \
Expand Down Expand Up @@ -67,6 +67,9 @@ $(DEBUG_OBJ_DIR)/%.o: %.cpp

run: daemon
$(MAKE) wait-for-healthy
docker compose exec -it webserv make
docker compose exec -it webserv bash -c "kill 1"
sleep 1
@make logs

daemon:
Expand Down
1 change: 1 addition & 0 deletions default.conf
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ server {
}

location /cgi/ {
autoindex on;
cgi on;
limit_except GET POST { deny all; }
}
Expand Down
87 changes: 87 additions & 0 deletions src/CacheHandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* CacheHandler.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: agaley <[email protected]> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/24 23:54:38 by agaley #+# #+# */
/* Updated: 2024/06/25 01:48:57 by agaley ### ########lyon.fr */
/* */
/* ************************************************************************** */

#include "CacheHandler.hpp"

CacheHandler* CacheHandler::_instance = NULL;

CacheHandler& CacheHandler::getInstance() {
if (_instance == NULL) {
_instance = new CacheHandler();
}
return *_instance;
}

void CacheHandler::deleteInstance() {
if (_instance != NULL) {
delete _instance;
_instance = NULL;
}
}

CacheHandler::CacheHandler() {
pthread_mutex_init(&_mutex, NULL);
}

CacheHandler::~CacheHandler() {
for (std::map<std::string, HTTPResponse*>::iterator it = _cache.begin();
it != _cache.end(); ++it) {
delete it->second;
}
_cache.clear();
pthread_mutex_destroy(&_mutex);
}

HTTPResponse* CacheHandler::getResponse(const HTTPRequest& request) {
std::string key = _generateKey(request);

pthread_mutex_lock(&_mutex);
std::map<std::string, HTTPResponse*>::const_iterator it = _cache.find(key);
if (it != _cache.end()) {
HTTPResponse* response = new HTTPResponse(*(it->second));
pthread_mutex_unlock(&_mutex);
return response;
} else {
pthread_mutex_unlock(&_mutex);
return NULL;
}
}

void CacheHandler::storeResponse(const HTTPRequest& request,
const HTTPResponse& response) {
std::string key = _generateKey(request);
pthread_mutex_lock(&_mutex);
if (_cache.find(key) == _cache.end())
_cache[key] = new HTTPResponse(response);
pthread_mutex_unlock(&_mutex);
}

std::string CacheHandler::_generateKey(const HTTPRequest& request) const {
std::ostringstream oss;
oss << _hash(request.getRawRequest());
return oss.str();
}

unsigned long CacheHandler::_hash(const std::string& str) const {
// FNV-1a Hash Algorithm
const unsigned long FNV_prime = 16777619;
const unsigned long offset_basis = 2166136261U;
unsigned long hash = offset_basis;
const char* cstr = str.c_str();

while (*cstr) {
hash ^= static_cast<unsigned long>(*cstr++);
hash *= FNV_prime;
}

return hash;
}
40 changes: 40 additions & 0 deletions src/CacheHandler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* CacheHandler.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: agaley <[email protected]> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/24 23:54:58 by agaley #+# #+# */
/* Updated: 2024/06/25 01:48:34 by agaley ### ########lyon.fr */
/* */
/* ************************************************************************** */

#ifndef CACHEHANDLER_HPP
#define CACHEHANDLER_HPP

#include <map>
#include "HTTPRequest.hpp"
#include "HTTPResponse.hpp"

class CacheHandler {
public:
static CacheHandler& getInstance();
static void deleteInstance();

void storeResponse(const HTTPRequest& request, const HTTPResponse& response);
HTTPResponse* getResponse(const HTTPRequest& request);

private:
CacheHandler();
~CacheHandler();

static CacheHandler* _instance;
std::map<std::string, HTTPResponse*> _cache;

std::string _generateKey(const HTTPRequest& request) const;
unsigned long _hash(const std::string& str) const;
mutable pthread_mutex_t _mutex;
};

#endif
26 changes: 22 additions & 4 deletions src/ConnectionHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@
/* By: agaley <[email protected]> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/30 16:11:21 by agaley #+# #+# */
/* Updated: 2024/06/24 21:59:35 by agaley ### ########lyon.fr */
/* Updated: 2024/06/25 01:51:28 by agaley ### ########lyon.fr */
/* */
/* ************************************************************************** */

#include "ConnectionHandler.hpp"
#include <sys/epoll.h>
#include <algorithm>
#include <sstream>
#include <string>

#include "CacheHandler.hpp"
#include "Common.hpp"
#include "ConnectionHandler.hpp"
#include "Utils.hpp"

ConnectionHandler::ConnectionHandler(
Expand All @@ -28,7 +30,8 @@ ConnectionHandler::ConnectionHandler(
_epollSocket(epollSocket),
_buffer(new char[BUFFER_SIZE]),
_readn(0),
_vservPool(virtualServers) {
_vservPool(virtualServers),
_cacheHandler(CacheHandler::getInstance()) {
memset(_buffer, 0, BUFFER_SIZE);
}

Expand Down Expand Up @@ -179,6 +182,16 @@ void ConnectionHandler::_processRequest() {
_request->setSessionId(sessionId);
}

if (_request->getHeader("Cache-Control") != "no-cache") {
HTTPResponse* cachedResponse = _cacheHandler.getResponse(*_request);
if (cachedResponse) {
_log.info("CONNECTION_HANDLER: Cache hit");
_response = cachedResponse;
_connectionStatus = SENDING;
return;
}
}

VirtualServer* vserv = _selectVirtualServer(_request->getHost());
if (vserv == NULL) {
_log.error("CONNECTION_HANDLER: No virtual server selected");
Expand All @@ -195,7 +208,12 @@ void ConnectionHandler::_processRequest() {
}

_response = vserv->handleRequest(*_request);
_response->setCookie("sessionid", sessionId);
_cacheHandler.storeResponse(*_request, *_response);

if (_request->getHeader("Set-Cookie").empty()) {
_response->setCookie("sessionid", sessionId);
}

_connectionStatus = SENDING;
}

Expand Down
9 changes: 6 additions & 3 deletions src/ConnectionHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,27 @@
/* ::: :::::::: */
/* ConnectionHandler.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mchenava <mchenava@student.42.fr> +#+ +:+ +#+ */
/* By: agaley <agaley@student.42lyon.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/30 16:11:25 by agaley #+# #+# */
/* Updated: 2024/06/24 10:37:08 by mchenava ### ########.fr */
/* Updated: 2024/06/25 01:51:47 by agaley ### ########lyon.fr */
/* */
/* ************************************************************************** */

#ifndef CONNECTION_HANDLER_H
#define CONNECTION_HANDLER_H

#include <pthread.h>
#include <string.h>
#include <sys/socket.h>
#include <vector>

#include "CacheHandler.hpp"
#include "Config.hpp"
#include "HTTPRequest.hpp"
#include "HTTPResponse.hpp"
#include "Logger.hpp"
#include "VirtualServer.hpp"
#include <pthread.h>

#define BUFFER_SIZE 16384

Expand Down Expand Up @@ -71,6 +73,7 @@ class ConnectionHandler {
std::vector<VirtualServer*> _vservPool;
HTTPRequest* _request;
HTTPResponse* _response;
CacheHandler& _cacheHandler;
// pthread_mutex_t _mutex;

void _receiveRequest();
Expand Down
4 changes: 2 additions & 2 deletions src/HTTPMethods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ std::string HTTPMethods::_generateDirectoryListing(const std::string& path) {
}

HTTPResponse* HTTPMethods::_autoindex(const std::string& path,
LocationConfig& location) {
std::string indexPath = path + "/" + location.index;
LocationConfig& location) {
std::string indexPath = path + location.index;
if (FileManager::doesFileExists(indexPath)) {
HTTPResponse* response = new HTTPResponse(HTTPResponse::OK);
response->addHeader("Content-Type", "text/html");
Expand Down
2 changes: 2 additions & 0 deletions src/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Server::~Server() {
_workers.clear();
pthread_mutex_destroy(&_mutex);
pthread_mutex_destroy(&_eventsMutex);
CacheHandler::deleteInstance();
ConfigManager::deleteInstance();
Server::_instance = NULL;
}

Expand Down
3 changes: 1 addition & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* By: agaley <[email protected]> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/28 15:02:12 by agaley #+# #+# */
/* Updated: 2024/06/24 23:05:06 by agaley ### ########lyon.fr */
/* Updated: 2024/06/25 01:13:41 by agaley ### ########lyon.fr */
/* */
/* ************************************************************************** */

Expand Down Expand Up @@ -47,7 +47,6 @@ int main(int argc, char* argv[]) {
server.start();
Logger::getInstance().info("Shutdown WebServ");
usleep(SHUTDOWN_DELAY); // Wait for Logger to finish output logs
ConfigManager::deleteInstance();
Logger::deleteInstance();
return EXIT_SUCCESS;
}

0 comments on commit ea84bd1

Please sign in to comment.