summaryrefslogtreecommitdiff
path: root/project2/cgi
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2012-02-12 14:39:28 +0000
committerrandomdan <randomdan@localhost>2012-02-12 14:39:28 +0000
commit722901e3922cda2e53707c84700a309a99ff9d55 (patch)
treedebeb5af1f05909003f8a8ace816f4578e5af587 /project2/cgi
parentAdd some more aggregates (diff)
downloadproject2-722901e3922cda2e53707c84700a309a99ff9d55.tar.bz2
project2-722901e3922cda2e53707c84700a309a99ff9d55.tar.xz
project2-722901e3922cda2e53707c84700a309a99ff9d55.zip
Adds support for presenter level caching modules and implements a file based one (requires xattr support)
Diffstat (limited to 'project2/cgi')
-rw-r--r--project2/cgi/cgiAppEngine.cpp51
-rw-r--r--project2/cgi/cgiAppEngine.h16
-rw-r--r--project2/cgi/cgiEnvironment.cpp6
-rw-r--r--project2/cgi/cgiEnvironment.h1
-rw-r--r--project2/cgi/cgiStageCacheHit.cpp27
-rw-r--r--project2/cgi/cgiStagePresent.cpp12
6 files changed, 96 insertions, 17 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);