diff options
author | randomdan <randomdan@localhost> | 2012-02-12 14:39:28 +0000 |
---|---|---|
committer | randomdan <randomdan@localhost> | 2012-02-12 14:39:28 +0000 |
commit | 226d35215412aed267c7d5939f1c7fae5158cae9 (patch) | |
tree | debeb5af1f05909003f8a8ace816f4578e5af587 | |
parent | Add some more aggregates (diff) | |
download | project2-226d35215412aed267c7d5939f1c7fae5158cae9.tar.bz2 project2-226d35215412aed267c7d5939f1c7fae5158cae9.tar.xz project2-226d35215412aed267c7d5939f1c7fae5158cae9.zip |
Adds support for presenter level caching modules and implements a file based one (requires xattr support)
-rw-r--r-- | project2/cgi/cgiAppEngine.cpp | 51 | ||||
-rw-r--r-- | project2/cgi/cgiAppEngine.h | 16 | ||||
-rw-r--r-- | project2/cgi/cgiEnvironment.cpp | 6 | ||||
-rw-r--r-- | project2/cgi/cgiEnvironment.h | 1 | ||||
-rw-r--r-- | project2/cgi/cgiStageCacheHit.cpp | 27 | ||||
-rw-r--r-- | project2/cgi/cgiStagePresent.cpp | 12 | ||||
-rw-r--r-- | project2/common/environment.h | 1 | ||||
-rw-r--r-- | project2/common/exceptions.cpp | 23 | ||||
-rw-r--r-- | project2/common/exceptions.h | 14 | ||||
-rw-r--r-- | project2/common/presenterCache.cpp | 25 | ||||
-rw-r--r-- | project2/common/presenterCache.h | 21 | ||||
-rw-r--r-- | project2/common/transform.cpp | 19 | ||||
-rw-r--r-- | project2/common/transform.h | 7 | ||||
-rw-r--r-- | project2/console/consoleEnvironment.cpp | 6 | ||||
-rw-r--r-- | project2/console/consoleEnvironment.h | 1 | ||||
-rw-r--r-- | project2/files/Jamfile.jam | 2 | ||||
-rw-r--r-- | project2/files/presenterCache.cpp | 187 | ||||
-rw-r--r-- | project2/json/transformStream.cpp | 25 | ||||
-rw-r--r-- | project2/xml/transformXml.cpp | 14 |
19 files changed, 402 insertions, 56 deletions
diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp index b92095c..9e91800 100644 --- a/project2/cgi/cgiAppEngine.cpp +++ b/project2/cgi/cgiAppEngine.cpp @@ -27,7 +27,8 @@ getSessionID(const std::vector<cgicc::HTTPCookie> & cookies) { CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e, std::ostream & io) : _env(e), sessionsContainer(LoaderBase::getLoader<SessionContainerLoader, NotSupported>(e->sessionModule)->open()), - IO(io) + IO(io), + outputCachingActive(false) { cursession = sessionsContainer->GetSession(getSessionID(e->getCookieList())); currentStage = NextStage(new InitialStage(e)); @@ -55,7 +56,7 @@ class CgiResult : public TransformChainLink { const std::string encoding; }; -class WriteToCgiResult : public TransformImpl<WritableContent, CgiResult> { +class WritableToCgiResult : public TransformImpl<WritableContent, CgiResult> { public: void transform(const WritableContent * wc, CgiResult * cr) const { cr->header->addHeader("Content-Type", Glib::ustring::compose("%1; charset=%2", wc->getContentType(), cr->encoding)); @@ -63,23 +64,32 @@ class WriteToCgiResult : public TransformImpl<WritableContent, CgiResult> { wc->writeTo(cr->stream, cr->encoding); } }; -DECLARE_TRANSFORM(WriteToCgiResult); +DECLARE_TRANSFORM(WritableToCgiResult); -bool -addFinalTransformTarget(TransformSourcePtr ts, TransformChainLink * tcl) +class StaticToCgiResult : public TransformImpl<StaticContent, CgiResult> { + public: + void transform(const StaticContent * sc, CgiResult * cr) const { + cr->header->addHeader("Content-Type", Glib::ustring::compose("%1; charset=%2", sc->getContentType(), sc->getEncoding())); + cr->header->render(cr->stream); + sc->writeTo(cr->stream); + } +}; +DECLARE_TRANSFORM(StaticToCgiResult); + +TransformSourcePtr +finalTransformSource(TransformSourcePtr ts) { if (ts->getTargets().empty()) { - ts->addTarget(tcl, NULL); - return true; + return ts; } BOOST_FOREACH(const Targets::value_type & t, ts->getTargets()) { if (TransformSource * tr = dynamic_cast<TransformSource *>(t.first.get())) { - if (addFinalTransformTarget(tr, tcl)) { - return true; + if (TransformSourcePtr f = finalTransformSource(tr)) { + return f; } } } - return false; + return NULL; } void @@ -117,6 +127,7 @@ CgiApplicationEngine::process() const } while (currentStage.get<0>()); endTime = boost::date_time::microsec_clock<boost::posix_time::ptime>::universal_time(); ResponseStagePtr rs = currentStage.get<1>(); + outputCachingActive = !rs->caches.empty(); if (const MultiRowSetPresenter * p = currentStage.get<3>().get()) { addAppData(p, rs->outputOptions); addEnvData(p, rs->outputOptions); @@ -128,8 +139,12 @@ CgiApplicationEngine::process() const _env->getServerName().substr(_env->getServerName().find(".")), env()->sessionTimeOut, "/", false)); } if (TransformSourcePtr ts = currentStage.get<2>()) { - addFinalTransformTarget(ts, new CgiResult(header, IO, - rs && rs->root ? rs->root->value("encoding", _env->outputEncoding) : VariableType(_env->outputEncoding))); + TransformSourcePtr final = finalTransformSource(ts); + final->addTarget(new CgiResult(header, IO, + rs && rs->root ? rs->root->value("encoding", _env->outputEncoding) : VariableType(_env->outputEncoding)), NULL); + BOOST_FOREACH(const PresenterCachePtr & p, rs->caches) { + final->addTarget(p, NULL); + } std::fstream * ddd = NULL; if (!_env->dumpdatadoc.empty()) { ddd = new std::fstream(_env->dumpdatadoc.c_str(), std::fstream::trunc | std::fstream::out); @@ -169,8 +184,10 @@ CgiApplicationEngine::addEnvData(const MultiRowSetPresenter * p, OutputOptionsPt addEnvToPresenter(p, "serverport", &cgicc::CgiEnvironment::getServerPort); addEnvToPresenter(p, "serverhttps", &cgicc::CgiEnvironment::usingHTTPS); // Request stuff - addEnvToPresenter(p, "referrer", &cgicc::CgiEnvironment::getReferrer); - addEnvToPresenter(p, "querystring", &cgicc::CgiEnvironment::getQueryString); + if (!outputCachingActive) { + addEnvToPresenter(p, "referrer", &cgicc::CgiEnvironment::getReferrer); + addEnvToPresenter(p, "querystring", &cgicc::CgiEnvironment::getQueryString); + } p->finishRowSet(); } @@ -186,7 +203,7 @@ CgiApplicationEngine::addEnvData(const MultiRowSetPresenter * p, OutputOptionsPt p->finishRowSet(); } - if (!o || o->Parameters()) { + if (!outputCachingActive && (!o || o->Parameters())) { // Parameters p->addNewRowSet("params", env()->scriptNamespacePrefix); BOOST_FOREACH(cgicc::FormEntry fe, _env->cgi->getElements()) { @@ -214,7 +231,7 @@ CgiApplicationEngine::addAppData(const MultiRowSetPresenter * p, OutputOptionsPt if (!o || o->Core()) { addCoreAppData(p); } - if (!o || o->Session()) { + if (!outputCachingActive && (!o || o->Session())) { // Sessions variables p->addNewRowSet("session", env()->scriptNamespacePrefix); p->addAttribute("id", cursession->ID.str()); @@ -222,7 +239,7 @@ CgiApplicationEngine::addAppData(const MultiRowSetPresenter * p, OutputOptionsPt p->finishRowSet(); } - if (!o || o->Timing()) { + if (!outputCachingActive && (!o || o->Timing())) { // Timing info p->addNewRowSet("timing", env()->scriptNamespacePrefix); p->addAttribute("start", startTime); diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h index 64f081d..b362ece 100644 --- a/project2/cgi/cgiAppEngine.h +++ b/project2/cgi/cgiAppEngine.h @@ -9,6 +9,7 @@ #include "viewHost.h" #include "transform.h" #include "xmlPresenter.h" +#include "presenterCache.h" #include "sessionContainer.h" #include <boost/intrusive_ptr.hpp> #include <boost/tuple/tuple.hpp> @@ -67,11 +68,14 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink /// Base class for a stage that can be a response to the client class ResponseStage : public Stage { public: + typedef ANONORDEREDSTORAGEOF(PresenterCache) PresenterCaches; + ResponseStage(const CgiEnvironment * e, ScriptNodePtr root); virtual HttpHeaderPtr getHeader() const = 0; OutputOptionsPtr outputOptions; ScriptNodePtr root; + PresenterCaches caches; }; /// Stage implementation used to bootstrap the iteration process based on the CGI environment @@ -104,6 +108,17 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink mutable MultiRowSetPresenterPtr presenter; }; + /// Stage to return previous cached output + class CacheHitStage : public virtual ResponseStage { + public: + CacheHitStage(const CgiEnvironment * e, ScriptNodePtr, PresenterCachePtr); + + virtual NextStage run(); + virtual HttpHeaderPtr getHeader() const; + protected: + PresenterCachePtr pc; + }; + /// The built-in fail-safe not found stage class DefaultNotFoundStage : public virtual ResponseStage { public: @@ -150,6 +165,7 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink mutable NextStage currentStage; SessionPtr cursession; mutable std::ostream & IO; + mutable bool outputCachingActive; }; #endif diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp index b1565ad..001d4bd 100644 --- a/project2/cgi/cgiEnvironment.cpp +++ b/project2/cgi/cgiEnvironment.cpp @@ -85,6 +85,12 @@ CgiEnvironment::getParamUri(unsigned int p) const return elems[p]; } +unsigned int +CgiEnvironment::getParamUriCount() const +{ + return elems.size(); +} + Glib::ustring CgiEnvironment::getParamQuery(const std::string & p) const { diff --git a/project2/cgi/cgiEnvironment.h b/project2/cgi/cgiEnvironment.h index 25ea90f..78f8730 100644 --- a/project2/cgi/cgiEnvironment.h +++ b/project2/cgi/cgiEnvironment.h @@ -28,6 +28,7 @@ class CgiEnvironment : public Environment, public cgicc::CgiEnvironment { virtual ~CgiEnvironment(); Glib::ustring getParamUri(unsigned int idx) const; + unsigned int getParamUriCount() const; Glib::ustring getParamQuery(const std::string & idx) const; std::string getServerName() const { return cgicc::CgiEnvironment::getServerName(); } std::string getScriptName() const { return cgicc::CgiEnvironment::getScriptName(); } diff --git a/project2/cgi/cgiStageCacheHit.cpp b/project2/cgi/cgiStageCacheHit.cpp new file mode 100644 index 0000000..728cc56 --- /dev/null +++ b/project2/cgi/cgiStageCacheHit.cpp @@ -0,0 +1,27 @@ +#include <pch.hpp> +#include "cgiAppEngine.h" +#include "cgiEnvironment.h" +#include "cgiHttpHeader.h" +#include <boost/foreach.hpp> +#include <boost/bind.hpp> + +CgiApplicationEngine::CacheHitStage::CacheHitStage(const CgiEnvironment * e, ScriptNodePtr s, PresenterCachePtr pcp) : + CgiApplicationEngine::ResponseStage(e, s), + pc(pcp) +{ +} + +CgiApplicationEngine::NextStage +CgiApplicationEngine::CacheHitStage::run() +{ + return NextStage(NULL, this, pc, NULL); +} + +CgiApplicationEngine::HttpHeaderPtr +CgiApplicationEngine::CacheHitStage::getHeader() const +{ + Project2HttpHeader * header = new Project2HttpHeader("200 OK"); + header->addHeader("Cache-control", "no-cache"); + return HttpHeaderPtr(header); +} + diff --git a/project2/cgi/cgiStagePresent.cpp b/project2/cgi/cgiStagePresent.cpp index 152b906..b5e73b5 100644 --- a/project2/cgi/cgiStagePresent.cpp +++ b/project2/cgi/cgiStagePresent.cpp @@ -13,12 +13,24 @@ CgiApplicationEngine::PresentStage::PresentStage(const CgiEnvironment * e, Scrip { s->loader.addLoadTarget(s->root(), Storer::into<OutputOptionsLoader>(&outputOptions)); s->loader.addLoadTarget(s->root(), Storer::into<PresenterLoader>(&presenter)); + s->loader.addLoadTarget(s->root(), Storer::into<ElementLoader>(&caches)); } CgiApplicationEngine::NextStage CgiApplicationEngine::PresentStage::run() { runChecks(); + PresenterCaches backFill; + BOOST_FOREACH(const PresenterCachePtr & pc, caches) { + if (pc->check()) { + CacheHitStage * chs = new CacheHitStage(e, root, pc); + chs->caches = backFill; + return NextStage(NULL, chs, pc, NULL); + } + else { + backFill.push_back(pc); + } + } try { executeViews(); return NextStage(NULL, this, boost::dynamic_pointer_cast<TransformSource>(presenter), presenter); diff --git a/project2/common/environment.h b/project2/common/environment.h index 8c6ae61..0c33283 100644 --- a/project2/common/environment.h +++ b/project2/common/environment.h @@ -21,6 +21,7 @@ class Environment { static const Environment * getCurrent(); virtual Glib::ustring getParamUri(unsigned int idx) const = 0; + virtual unsigned int getParamUriCount() const = 0; virtual Glib::ustring getParamQuery(const std::string & idx) const = 0; virtual std::string getServerName() const = 0; diff --git a/project2/common/exceptions.cpp b/project2/common/exceptions.cpp index 2fa5509..4f061ab 100644 --- a/project2/common/exceptions.cpp +++ b/project2/common/exceptions.cpp @@ -48,3 +48,26 @@ two_part_error::what() const throw() return buf; } + +syscall_error::syscall_error(int e) : + err(e), + buf(NULL) +{ +} + +syscall_error::~syscall_error() throw() +{ + free(buf); +} + +const char * +syscall_error::what() const throw() +{ + if (!buf) { + if (asprintf(&buf, "%s (%d)", strerror(err), err) < 1) { + throw std::bad_alloc(); + } + } + return buf; +} + diff --git a/project2/common/exceptions.h b/project2/common/exceptions.h index a45e53d..6d3410d 100644 --- a/project2/common/exceptions.h +++ b/project2/common/exceptions.h @@ -12,6 +12,15 @@ class numeric_error : public std::exception { int err; mutable char * buf; }; +class syscall_error : public std::exception { + public: + syscall_error(int); + ~syscall_error() throw(); + const char * what() const throw(); + private: + int err; + mutable char * buf; +}; class two_part_error : public std::exception { public: two_part_error(const std::string & what1, const std::string & what2); @@ -47,6 +56,11 @@ class Name : public numeric_error { \ public: \ Name(int e) : numeric_error(e) { } \ } +#define SimpleSysCallException(Name) \ +class Name : public syscall_error { \ + public: \ + Name(int e) : syscall_error(e) { } \ +} SimpleNumericException(UriElementOutOfRange); SimpleMessageException(ParamNotFound); diff --git a/project2/common/presenterCache.cpp b/project2/common/presenterCache.cpp new file mode 100644 index 0000000..4771eed --- /dev/null +++ b/project2/common/presenterCache.cpp @@ -0,0 +1,25 @@ +#include "presenterCache.h" +#include <boost/foreach.hpp> + +PresenterCache::PresenterCache(ScriptNodePtr s) : + SourceObject(s), + IHaveParameters(s), + encoding(s->value("encoding", "utf-8").as<std::string>()) +{ +} + +void +PresenterCache::applyKeys(const boost::function2<void, const std::string &, const VariableType &> & f) const +{ + BOOST_FOREACH(const IHaveParameters::Parameters::value_type & p, allParameters()) { + f(p.first, p.second); + } +} + +class WriteToCache : public TransformImpl<WritableContent, PresenterCache> { + public: + void transform(const WritableContent * wc, PresenterCache * pc) const { + wc->writeTo(pc->writeCache(wc->getContentType(), pc->encoding), pc->encoding); + } +}; +DECLARE_TRANSFORM(WriteToCache); diff --git a/project2/common/presenterCache.h b/project2/common/presenterCache.h new file mode 100644 index 0000000..92de2d2 --- /dev/null +++ b/project2/common/presenterCache.h @@ -0,0 +1,21 @@ +#ifndef PRESENTER_CACHE_H +#define PRESENTER_CACHE_H + +#include "transform.h" +#include "scripts.h" +#include "iHaveParameters.h" + +class PresenterCache : public SourceObject, public virtual TransformSource, public IHaveParameters { + public: + PresenterCache(ScriptNodePtr); + virtual bool check() const = 0; + + virtual std::ostream & writeCache(const std::string & ct, const std::string & encoding) = 0; + const std::string encoding; + + protected: + void applyKeys(const boost::function2<void, const std::string &, const VariableType &> & f) const; +}; +typedef boost::intrusive_ptr<PresenterCache> PresenterCachePtr; + +#endif diff --git a/project2/common/transform.cpp b/project2/common/transform.cpp index 202da6a..5a40ce3 100644 --- a/project2/common/transform.cpp +++ b/project2/common/transform.cpp @@ -1,6 +1,7 @@ #include <pch.hpp> #include "transform.h" #include "logger.h" +#include "ostreamWrapper.h" #include <boost/foreach.hpp> class TransformTargetStorer : public Storer { @@ -72,3 +73,21 @@ TransformSource::getTargets() const return targets; } +class TransformWritableContentToStdStream : public TransformImpl<WritableContent, ostreamWrapper> { + public: + void transform(const WritableContent * wc, ostreamWrapper * o) const + { + wc->writeTo(o->strm, "UTF-8"); + } +}; +DECLARE_TRANSFORM(TransformWritableContentToStdStream); + +class TransformStaticContentToStdStream : public TransformImpl<StaticContent, ostreamWrapper> { + public: + void transform(const StaticContent * wc, ostreamWrapper * o) const + { + wc->writeTo(o->strm); + } +}; +DECLARE_TRANSFORM(TransformStaticContentToStdStream); + diff --git a/project2/common/transform.h b/project2/common/transform.h index a9dde49..e3bdf4f 100644 --- a/project2/common/transform.h +++ b/project2/common/transform.h @@ -98,5 +98,12 @@ class WritableContent { virtual void writeTo(std::ostream &, const std::string & encoding) const = 0; }; +class StaticContent { + public: + virtual Glib::ustring getContentType() const = 0; + virtual Glib::ustring getEncoding() const = 0; + virtual void writeTo(std::ostream &) const = 0; +}; + #endif diff --git a/project2/console/consoleEnvironment.cpp b/project2/console/consoleEnvironment.cpp index 25c2f40..8f4465c 100644 --- a/project2/console/consoleEnvironment.cpp +++ b/project2/console/consoleEnvironment.cpp @@ -71,6 +71,12 @@ ConsoleEnvironment::getParamUri(unsigned int idx) const throw UriElementOutOfRange(idx); } +unsigned int +ConsoleEnvironment::getParamUriCount() const +{ + return uriParams.size(); +} + Glib::ustring ConsoleEnvironment::getParamQuery(const std::string & p) const { diff --git a/project2/console/consoleEnvironment.h b/project2/console/consoleEnvironment.h index a5530a9..6d57d3c 100644 --- a/project2/console/consoleEnvironment.h +++ b/project2/console/consoleEnvironment.h @@ -18,6 +18,7 @@ class ConsoleEnvironment : public Environment { Glib::ustring getParamUri(unsigned int idx) const; + unsigned int getParamUriCount() const; Glib::ustring getParamQuery(const std::string & idx) const; std::string getServerName() const; std::string getScriptName() const; diff --git a/project2/files/Jamfile.jam b/project2/files/Jamfile.jam index 54df687..bdb851f 100644 --- a/project2/files/Jamfile.jam +++ b/project2/files/Jamfile.jam @@ -4,6 +4,7 @@ alias glibmm : : : : ; lib boost_system : : <name>boost_system ; lib boost_filesystem : : <name>boost_filesystem ; +lib boost_iostreams : : <name>boost_iostreams ; cpp-pch pch : pch.hpp : <library>../common//p2common @@ -16,6 +17,7 @@ lib p2files : <library>glibmm <library>boost_filesystem <library>boost_system + <library>boost_iostreams <library>../common//p2common : : <include>. diff --git a/project2/files/presenterCache.cpp b/project2/files/presenterCache.cpp new file mode 100644 index 0000000..76a4e86 --- /dev/null +++ b/project2/files/presenterCache.cpp @@ -0,0 +1,187 @@ +#include "../common/presenterCache.h" +#include "../common/exceptions.h" +#include "../common/options.h" +#include "../common/environment.h" +#include <fcntl.h> +#include <attr/xattr.h> +#include <sys/stat.h> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/filesystem/path.hpp> +#include <boost/filesystem/operations.hpp> +#include <boost/bind.hpp> +#include <glibmm/convert.h> +#include <sys/file.h> + +SimpleSysCallException(OpenCacheFile); +SimpleSysCallException(StatCacheFile); +SimpleSysCallException(LockCacheFile); +SimpleSysCallException(CacheFileXAttr); + +template <class E> +int safesys(int n, int r) { + if (r == n) { + throw E(errno); + } + return r; +} + +class FilePresenterCache : public PresenterCache, public StaticContent, public SourceOf<StaticContent> { + public: + FilePresenterCache(ScriptNodePtr s) : + PresenterCache(s), + readcachefd(0), + writecache(NULL) { + } + ~FilePresenterCache() + { + if (readcachefd) { + close(readcachefd); + } + delete writecache; + } + bool check() const + { + try { + readcachefd = safesys<OpenCacheFile>(-1, open(getCacheFile().string().c_str(), O_RDONLY)); + struct stat st; + safesys<CacheFileXAttr>(-1, fstat(readcachefd, &st)); + if (st.st_mtime < time(NULL) - FilePresenterCache::CacheLife) { + unlink(getCacheFile().string().c_str()); + close(readcachefd); + readcachefd = 0; + return false; + } + safesys<LockCacheFile>(-1, ::flock(readcachefd, LOCK_SH)); + return true; + } + catch (...) { + close(readcachefd); + readcachefd = 0; + return false; + } + } + + Glib::ustring getEncoding() const + { + char buf[BUFSIZ]; + buf[safesys<CacheFileXAttr>(-1, fgetxattr(readcachefd, "user.encoding", buf, sizeof(buf)))] = 0; + return buf; + } + Glib::ustring getContentType() const + { + char buf[BUFSIZ]; + buf[safesys<CacheFileXAttr>(-1, fgetxattr(readcachefd, "user.content-type", buf, sizeof(buf)))] = 0; + return buf; + } + void writeTo(std::ostream & o) const + { + boost::iostreams::stream<boost::iostreams::file_descriptor_source> cache(readcachefd, boost::iostreams::never_close_handle); + cache.seekg(0); + o << cache.rdbuf(); + } + operator const StaticContent * () const { + return this; + } + mutable int readcachefd; + + std::ostream & writeCache(const std::string & ct, const std::string & enc) + { + int fd = safesys<OpenCacheFile>(-1, open(getCacheFile().string().c_str(), + O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)); + safesys<LockCacheFile>(-1, ::flock(fd, LOCK_EX)); + safesys<CacheFileXAttr>(-1, fsetxattr(fd, "user.content-type", ct.c_str(), ct.length(), 0)); + safesys<CacheFileXAttr>(-1, fsetxattr(fd, "user.encoding", enc.c_str(), enc.length(), 0)); + writecache = new boost::iostreams::stream<boost::iostreams::file_descriptor_sink>(fd, boost::iostreams::close_handle); + return *writecache; + } + std::ostream * writecache; + + private: + 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; + } + return cache; + } + + 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 boost::filesystem::path Store; + static std::string FileName; + static time_t CacheLife; + friend class FilePresenterCacheLoader; +}; +boost::filesystem::path FilePresenterCache::Store; +std::string FilePresenterCache::FileName; +time_t FilePresenterCache::CacheLife; + +class FilePresenterCacheLoader : public ElementLoaderImpl<FilePresenterCache> { + public: + FilePresenterCacheLoader() : + opts("XML Cache options") + { + opts + ("pcache.file.store", Options::value(&FilePresenterCache::Store, "/tmp/project2.pcache"), + "The root folder of the cache storage area") + ("pcache.file.filename", Options::value(&FilePresenterCache::FileName, "cache"), + "The filename to store the data in") + ("pcache.file.life", Options::value(&FilePresenterCache::CacheLife, 3600), + "The age of cache entries after which they are removed (seconds)") + ; + } + + const Options * options() const + { + return &opts; + } + + void onIdle() + { + emptyDir(FilePresenterCache::Store); + } + + bool emptyDir(const boost::filesystem::path & dir) + { + bool files = false; + boost::filesystem::directory_iterator end; + for (boost::filesystem::directory_iterator itr(dir); itr != end; ++itr) { + struct stat st; + stat(itr->path().string().c_str(), &st); + if (S_ISDIR(st.st_mode)) { + if (emptyDir(*itr)) { + files = true; + } + else { + boost::filesystem::remove(*itr); + } + } + else { + if (st.st_mtime > time(NULL) - FilePresenterCache::CacheLife) { + files = true; + } + else { + boost::filesystem::remove(*itr); + } + } + } + return files; + } + + private: + Options opts; +}; +DECLARE_CUSTOM_LOADER("filecache", FilePresenterCacheLoader); diff --git a/project2/json/transformStream.cpp b/project2/json/transformStream.cpp deleted file mode 100644 index fae71b0..0000000 --- a/project2/json/transformStream.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include <pch.hpp> -#include "transform.h" -#include "logger.h" -#include "json.h" -#include "ostreamWrapper.h" - -class TransformJsonToStream : public TransformImpl<json::Object, ostreamWrapper> { - public: - TransformJsonToStream() : - encoding("utf-8") { - } - void transform(const json::Object * obj, ostreamWrapper * o) const - { - json::serializeObject(*obj, o->strm, encoding); - } - void configure(ScriptNodePtr s) - { - s->applyValue("encoding", encoding); - } - private: - VariableType encoding; -}; -DECLARE_TRANSFORM(TransformJsonToStream); - - diff --git a/project2/xml/transformXml.cpp b/project2/xml/transformXml.cpp deleted file mode 100644 index fb115f1..0000000 --- a/project2/xml/transformXml.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include <pch.hpp> -#include "transform.h" -#include <libxml++/document.h> -#include "ostreamWrapper.h" - -class TransformXmlToStdStream : public TransformImpl<xmlpp::Document, ostreamWrapper> { - public: - void transform(const xmlpp::Document * doc, ostreamWrapper * o) const - { - const_cast<xmlpp::Document *>(doc)->write_to_stream_formatted(o->strm, "UTF-8"); - } -}; -DECLARE_TRANSFORM(TransformXmlToStdStream); - |