diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index df17033c1..e2ead7bce 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -58,8 +58,6 @@ extern "C" { #include #include -#include -#include #include #include @@ -80,6 +78,7 @@ extern "C" { #define MAX_SEARCH_LEN 140 #define KIWIX_MIN_CONTENT_SIZE_TO_DEFLATE 100 +#define DEFAULT_CACHE_SIZE 2 namespace kiwix { @@ -96,6 +95,18 @@ inline std::string normalizeRootUrl(std::string rootUrl) return rootUrl.empty() ? rootUrl : "/" + rootUrl; } +// Returns the value of env var `name` if found, otherwise returns defaultVal +unsigned int getCacheLength(const char* name, unsigned int defaultVal) { + try { + const char* envString = std::getenv(name); + if (envString == nullptr) { + throw std::runtime_error("Environment variable not set"); + } + return extractFromString(envString); + } catch (...) {} + + return defaultVal; +} } // unnamed namespace static IdNameMapper defaultNameMapper; @@ -134,7 +145,9 @@ InternalServer::InternalServer(Library* library, m_ipConnectionLimit(ipConnectionLimit), mp_daemon(nullptr), mp_library(library), - mp_nameMapper(nameMapper ? nameMapper : &defaultNameMapper) + mp_nameMapper(nameMapper ? nameMapper : &defaultNameMapper), + searcherCache(getCacheLength("SEARCHER_CACHE_SIZE", std::max((unsigned int) (mp_library->getBookCount(true, true)*0.1), 1U))), + searchCache(getCacheLength("SEARCH_CACHE_SIZE", DEFAULT_CACHE_SIZE)) {} bool InternalServer::start() { @@ -488,11 +501,11 @@ std::unique_ptr InternalServer::handle_search(const RequestContext& re } catch(const std::out_of_range&) {} catch(const std::invalid_argument&) {} - std::string bookName; + std::string bookName, bookId; std::shared_ptr archive; try { bookName = request.get_argument("content"); - const std::string bookId = mp_nameMapper->getIdForName(bookName); + bookId = mp_nameMapper->getIdForName(bookName); archive = mp_library->getArchiveById(bookId); } catch (const std::out_of_range&) {} @@ -509,7 +522,7 @@ std::unique_ptr InternalServer::handle_search(const RequestContext& re std::shared_ptr searcher; if (archive) { - searcher = std::make_shared(*archive); + searcher = searcherCache.getOrPut(bookId, [=](){ return std::make_shared(*archive);}); } else { for (auto& bookId: mp_library->filter(kiwix::Filter().local(true).valid(true))) { auto currentArchive = mp_library->getArchiveById(bookId); @@ -540,6 +553,7 @@ std::unique_ptr InternalServer::handle_search(const RequestContext& re } /* Get the results */ + std::string queryString; try { zim::Query query; if (patternString.empty()) { @@ -549,6 +563,7 @@ std::unique_ptr InternalServer::handle_search(const RequestContext& re } query.setQuery(""); + queryString = "GEO:" + to_string(latitude) + to_string(longitude) + to_string(distance); query.setGeorange(latitude, longitude, distance); } else { // Execute Ft search @@ -556,13 +571,16 @@ std::unique_ptr InternalServer::handle_search(const RequestContext& re cout << "Performing query `" << patternString << "'" << endl; } - std::string queryString = removeAccents(patternString); + queryString = "FT:" + removeAccents(patternString); query.setQuery(queryString); } + queryString = bookId + queryString; - zim::Search search = searcher->search(query); - SearchRenderer renderer(search.getResults(start, pageLength), mp_nameMapper, mp_library, start, - search.getEstimatedMatches()); + std::shared_ptr search; + search = searchCache.getOrPut(queryString, [=](){ return make_shared(searcher->search(query));}); + + SearchRenderer renderer(search->getResults(start, pageLength), mp_nameMapper, mp_library, start, + search->getEstimatedMatches()); renderer.setSearchPattern(patternString); renderer.setSearchContent(bookName); renderer.setProtocolPrefix(m_root + "/"); diff --git a/src/server/internalServer.h b/src/server/internalServer.h index f4ae08eea..e808f8ee9 100644 --- a/src/server/internalServer.h +++ b/src/server/internalServer.h @@ -28,6 +28,9 @@ extern "C" { #include "library.h" #include "name_mapper.h" +#include +#include + #include #include @@ -36,9 +39,13 @@ extern "C" { #include "server/request_context.h" #include "server/response.h" +#include "tools/concurrent_cache.h" + namespace kiwix { typedef kainjow::mustache::data MustacheData; +typedef ConcurrentCache> SearcherCache; +typedef ConcurrentCache> SearchCache; class Entry; class OPDSDumper; @@ -115,6 +122,9 @@ class InternalServer { Library* mp_library; NameMapper* mp_nameMapper; + SearcherCache searcherCache; + SearchCache searchCache; + std::string m_server_id; std::string m_library_id;