From e398a4e1f5e90196304f1355e7b48b63ef811eea Mon Sep 17 00:00:00 2001 From: randomdan Date: Fri, 4 May 2012 20:39:51 +0000 Subject: Process parameters each time to avoid serving up the same content everytime Close cache handles on idle and config load Bugs 21 and 21 --- project2/files/presenterCache.cpp | 115 ++++++++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 35 deletions(-) diff --git a/project2/files/presenterCache.cpp b/project2/files/presenterCache.cpp index 9505496..b90e29d 100644 --- a/project2/files/presenterCache.cpp +++ b/project2/files/presenterCache.cpp @@ -1,6 +1,7 @@ #include "../common/presenterCache.h" #include "../common/exceptions.h" #include "../common/options.h" +#include "../common/safeMapFind.h" #include "../common/environment.h" #include #include @@ -10,6 +11,7 @@ #include #include #include +#include #include #include @@ -29,78 +31,91 @@ int safesys(int n, int r) { class FilePresenterCache : public PresenterCache, public StaticContent, public SourceOf { public: + typedef std::vector Path; + typedef std::map Parameters; + typedef boost::tuple Key; + class CacheFile : public IntrusivePtrBase { + public: + CacheFile(int f) : fd(f) { + } + ~CacheFile() { + close(fd); + } + operator int() const { return fd; } + const int fd; + }; + typedef boost::intrusive_ptr CacheFilePtr; + typedef std::map OpenCaches; + FilePresenterCache(ScriptNodePtr s) : PresenterCache(s), - readcachefd(0), writecache(NULL) { } ~FilePresenterCache() { - if (readcachefd) { - close(readcachefd); - } delete writecache; } bool check(time_t scriptMtime) const { + Key key = getCacheKey(); try { - if (readcachefd == 0) { - readcachefd = safesys(-1, open(getCacheFile().string().c_str(), O_RDONLY)); + CacheFilePtr f = defaultMapFind(openCaches, key); + if (!f) { + f = openCacheFile(key); } struct stat st; - safesys(-1, fstat(readcachefd, &st)); + safesys(-1, fstat(*f, &st)); if (st.st_nlink == 0) { - close(readcachefd); - readcachefd = 0; - readcachefd = safesys(-1, open(getCacheFile().string().c_str(), O_RDONLY)); + f = openCacheFile(key); + safesys(-1, fstat(*f, &st)); } if ((st.st_mtime < (time(NULL) - FilePresenterCache::CacheLife)) || (st.st_mtime < scriptMtime)) { unlink(getCacheFile().string().c_str()); - close(readcachefd); - readcachefd = 0; + openCaches.erase(key); + f.reset(); return false; } + myCache = f; return true; } catch (...) { - if (readcachefd) { - close(readcachefd); - readcachefd = 0; - } + openCaches.erase(key); + myCache.reset(); return false; } } Glib::ustring getEncoding() const { - char buf[BUFSIZ]; - buf[safesys(-1, fgetxattr(readcachefd, "user.encoding", buf, sizeof(buf)))] = 0; - return buf; + return getXAttr("user.encoding"); } Glib::ustring getContentType() const + { + return getXAttr("user.content-type"); + } + Glib::ustring getXAttr(const char * attr) const { char buf[BUFSIZ]; - buf[safesys(-1, fgetxattr(readcachefd, "user.content-type", buf, sizeof(buf)))] = 0; + buf[safesys(-1, fgetxattr(*myCache, attr, buf, sizeof(buf)))] = 0; return buf; } size_t getSizeInBytes() const { struct stat st; - safesys(-1, fstat(readcachefd, &st)); + safesys(-1, fstat(*myCache, &st)); return st.st_size; } void writeTo(std::ostream & o) const { - safesys(-1, ::flock(readcachefd, LOCK_SH)); - boost::iostreams::stream cache(readcachefd, boost::iostreams::never_close_handle); + safesys(-1, ::flock(*myCache, LOCK_SH)); + boost::iostreams::stream cache(*myCache, boost::iostreams::never_close_handle); cache.seekg(0); o << cache.rdbuf(); - safesys(-1, ::flock(readcachefd, LOCK_UN)); + safesys(-1, ::flock(*myCache, LOCK_UN)); } operator const StaticContent * () const { return this; } - mutable int readcachefd; std::ostream & writeCache(const std::string & ct, const std::string & enc) { @@ -121,33 +136,58 @@ class FilePresenterCache : public PresenterCache, public StaticContent, public S std::ostream * writecache; private: + Key getCacheKey() const + { + Key key; + unsigned int puc = Environment::getCurrent()->getParamUriCount(); + key.get<0>().reserve(puc); + for (unsigned int i = 0; i < puc; i += 1) { + key.get<0>()[i] = Environment::getCurrent()->getParamUri(i).raw(); + } + applyKeys(boost::bind(&appendParams, &key.get<1>(), _1, _2)); + return key; + } + CacheFilePtr openCacheFile(const Key & key) const + { + CacheFilePtr c = new CacheFile(safesys(-1, open(getCacheFile().string().c_str(), O_RDONLY))); + openCaches[key] = c; + return c; + } boost::filesystem::path getCacheFile() const { - if (cache.empty()) { - cache = Store; - unsigned int puc = Environment::getCurrent()->getParamUriCount(); - for (unsigned int i = 0; i < puc; i += 1) { - cache /= Environment::getCurrent()->getParamUri(i).raw(); - } - applyKeys(boost::bind(&appendPath, &cache, _1, _2)); - boost::filesystem::create_directories(cache); - cache /= FileName; + boost::filesystem::path cache; + cache = Store; + unsigned int puc = Environment::getCurrent()->getParamUriCount(); + for (unsigned int i = 0; i < puc; i += 1) { + cache /= Environment::getCurrent()->getParamUri(i).raw(); } + applyKeys(boost::bind(&appendPath, &cache, _1, _2)); + boost::filesystem::create_directories(cache); + cache /= FileName; return cache; } + static void appendParams(Parameters * cache, const std::string & n, const VariableType & v) + { + cache->insert(Parameters::value_type(n, v)); + } + static void appendPath(boost::filesystem::path * cache, const std::string & n, const VariableType & v) { *cache /= n; *cache /= v.operator const std::string &(); } - mutable boost::filesystem::path cache; + static OpenCaches openCaches; + mutable CacheFilePtr myCache; + + // Config static boost::filesystem::path Store; static std::string FileName; static time_t CacheLife; friend class FilePresenterCacheLoader; }; +FilePresenterCache::OpenCaches FilePresenterCache::openCaches; boost::filesystem::path FilePresenterCache::Store; std::string FilePresenterCache::FileName; time_t FilePresenterCache::CacheLife; @@ -175,6 +215,11 @@ class FilePresenterCacheLoader : public ElementLoader::For { void onIdle() { emptyDir(FilePresenterCache::Store); + FilePresenterCache::openCaches.clear(); + } + void onConfigLoad() + { + FilePresenterCache::openCaches.clear(); } bool emptyDir(const boost::filesystem::path & dir) -- cgit v1.2.3