summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2012-02-13 22:49:51 +0000
committerrandomdan <randomdan@localhost>2012-02-13 22:49:51 +0000
commite661ebd7b36ded384d91c7af1bb890e6c9aef3cc (patch)
tree840fbfbed7d3083cbd730ffcbb740535f15fa333
parentLazy session ID creation (diff)
downloadproject2-e661ebd7b36ded384d91c7af1bb890e6c9aef3cc.tar.bz2
project2-e661ebd7b36ded384d91c7af1bb890e6c9aef3cc.tar.xz
project2-e661ebd7b36ded384d91c7af1bb890e6c9aef3cc.zip
Persist the CGI Environment over many iterations of the app engine, reloading the configuration only when needed
-rw-r--r--project2/cgi/cgiAppEngine.cpp16
-rw-r--r--project2/cgi/cgiAppEngine.h10
-rw-r--r--project2/cgi/cgiCommon.cpp9
-rw-r--r--project2/cgi/cgiCommon.h3
-rw-r--r--project2/cgi/cgiEnvironment.cpp48
-rw-r--r--project2/cgi/cgiEnvironment.h22
-rw-r--r--project2/cgi/p2webCgi.cpp3
-rw-r--r--project2/cgi/p2webFCgi.cpp3
-rw-r--r--project2/cgi/testCgi.cpp3
-rw-r--r--project2/common/environment.cpp47
-rw-r--r--project2/common/environment.h8
-rw-r--r--project2/common/optionsSource.h1
-rw-r--r--project2/console/claOptions.cpp10
-rw-r--r--project2/files/optionsSource.cpp20
-rw-r--r--project2/files/optionsSource.h3
15 files changed, 144 insertions, 62 deletions
diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp
index c08eb3e..07aa737 100644
--- a/project2/cgi/cgiAppEngine.cpp
+++ b/project2/cgi/cgiAppEngine.cpp
@@ -15,22 +15,18 @@ typedef std::string SValue;
SimpleMessageException(UnknownDomain);
-static UUID
-getSessionID(const std::vector<cgicc::HTTPCookie> & cookies) {
- BOOST_FOREACH(const cgicc::HTTPCookie & c, cookies) {
- if (c.getName() == SESSIONID) {
- return c.getValue();
- }
- }
- return UUID();
-}
CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e, std::ostream & io) :
_env(e),
sessionsContainer(LoaderBase::getLoader<SessionContainerLoader, NotSupported>(e->sessionModule)->open()),
IO(io),
outputCachingActive(false)
{
- cursession = sessionsContainer->GetSession(getSessionID(e->getCookieList()));
+ try {
+ cursession = sessionsContainer->GetSession(e->getCookieValue(SESSIONID));
+ }
+ catch (const NoSuchCookie &) {
+ cursession = sessionsContainer->GetSession(UUID());
+ }
currentStage = NextStage(new InitialStage(e));
}
diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h
index b362ece..154ca09 100644
--- a/project2/cgi/cgiAppEngine.h
+++ b/project2/cgi/cgiAppEngine.h
@@ -15,8 +15,9 @@
#include <boost/tuple/tuple.hpp>
#include "cgiOutputOptions.h"
#include "cgiHttpHeader.h"
+#include "cgiEnvironment.h"
+#include <cgicc/Cgicc.h>
-class CgiEnvironment;
class Session;
namespace cgicc {
class HTTPHeader;
@@ -43,10 +44,9 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
SessionContainerPtr sessionsContainer;
// Helpers
void addVarToPresenter(const MultiRowSetPresenter * p, const Glib::ustring & name, const VariableType &) const;
- typedef std::string (cgicc::CgiEnvironment::*StrEnvGetter)() const;
- template <class X>
- void addEnvToPresenter(const MultiRowSetPresenter * p, const char * name, X (cgicc::CgiEnvironment::*getter)() const) const {
- addVarToPresenter(p, name, (_env->*getter)());
+ template <class X, class Y>
+ void addEnvToPresenter(const MultiRowSetPresenter * p, const char * name, X (Y::*getter)() const) const {
+ addVarToPresenter(p, name, (_env->cgi->getEnvironment().*getter)());
}
public:
diff --git a/project2/cgi/cgiCommon.cpp b/project2/cgi/cgiCommon.cpp
index 7559ea7..ac3e6d4 100644
--- a/project2/cgi/cgiCommon.cpp
+++ b/project2/cgi/cgiCommon.cpp
@@ -5,7 +5,6 @@
#include <cgicc/CgiEnvironment.h>
#include <cgicc/HTTPContentHeader.h>
#include <cgicc/HTTPStatusHeader.h>
-#include "cgiEnvironment.h"
#include "cgiAppEngine.h"
#include <boost/bind.hpp>
#include <cxxabi.h>
@@ -38,13 +37,13 @@ doExceptionReporting(const E & e, std::ostream & IO)
}
void
-cgiServe(cgicc::CgiInput * i, std::ostream & IO)
+cgiServe(cgicc::CgiInput * i, CgiEnvironment * env, std::ostream & IO)
{
cgicc::Cgicc cgi(i);
- CgiEnvironment env(&cgi);
- env.init();
+ env->setCGICC(&cgi);
+ env->init();
try {
- CgiApplicationEngine app(&env, IO);
+ CgiApplicationEngine app(env, IO);
LoaderBase::onAllComponents(boost::bind(&ComponentLoader::onBefore, _1));
Logger()->messagef(LOG_DEBUG, "%s: Processing request", __FUNCTION__);
diff --git a/project2/cgi/cgiCommon.h b/project2/cgi/cgiCommon.h
index 489e3fb..ce6108e 100644
--- a/project2/cgi/cgiCommon.h
+++ b/project2/cgi/cgiCommon.h
@@ -1,5 +1,6 @@
#include <ostream>
#include <cgicc/Cgicc.h>
+#include "cgiEnvironment.h"
-void cgiServe(cgicc::CgiInput * i, std::ostream & o);
+void cgiServe(cgicc::CgiInput * i, CgiEnvironment *, std::ostream & o);
diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp
index 001d4bd..2e977b2 100644
--- a/project2/cgi/cgiEnvironment.cpp
+++ b/project2/cgi/cgiEnvironment.cpp
@@ -23,10 +23,7 @@ makeVector(const boost::filesystem::path & y)
return r;
}
-CgiEnvironment::CgiEnvironment(cgicc::Cgicc * c) :
- cgicc::CgiEnvironment(c->getEnvironment()),
- elems(makeVector(boost::filesystem::path(getRedirectURL()))),
- cgi(c),
+CgiEnvironment::CgiEnvironment() :
cgiOptions("Project2 CGI options"),
hpi(new HostnamePlatformIdentifier())
{
@@ -69,6 +66,48 @@ CgiEnvironment::~CgiEnvironment()
{
}
+void
+CgiEnvironment::setCGICC(const cgicc::Cgicc * c)
+{
+ cgi = c;
+ elems = makeVector(boost::filesystem::path(getRedirectURL()));
+}
+
+std::string
+CgiEnvironment::getCookieValue(const std::string & name) const
+{
+ BOOST_FOREACH(const cgicc::HTTPCookie & c, cgi->getEnvironment().getCookieList()) {
+ if (c.getName() == name) {
+ return c.getValue();
+ }
+ }
+ throw NoSuchCookie(name);
+}
+
+std::string
+CgiEnvironment::getRequestMethod() const
+{
+ return cgi->getEnvironment().getRequestMethod();
+}
+
+std::string
+CgiEnvironment::getRedirectURL() const
+{
+ return cgi->getEnvironment().getRedirectURL();
+}
+
+std::string
+CgiEnvironment::getScriptName() const
+{
+ return cgi->getEnvironment().getScriptName();
+}
+
+std::string
+CgiEnvironment::getServerName() const
+{
+ return cgi->getEnvironment().getServerName();
+}
+
const Glib::ustring &
CgiEnvironment::platform() const
{
@@ -125,6 +164,7 @@ HostnamePlatformIdentifier::reset() const
{
if (platform) {
delete platform;
+ platform = NULL;
}
}
diff --git a/project2/cgi/cgiEnvironment.h b/project2/cgi/cgiEnvironment.h
index 78f8730..27b1694 100644
--- a/project2/cgi/cgiEnvironment.h
+++ b/project2/cgi/cgiEnvironment.h
@@ -6,6 +6,8 @@
#include "environment.h"
#include <cgicc/CgiEnvironment.h>
+SimpleMessageException(NoSuchCookie);
+
namespace cgicc {
class Cgicc;
}
@@ -22,19 +24,23 @@ class HostnamePlatformIdentifier : public Options::Target {
mutable Glib::ustring * platform;
};
-class CgiEnvironment : public Environment, public cgicc::CgiEnvironment {
+class CgiEnvironment : public Environment {
public:
- CgiEnvironment(cgicc::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(); }
+ std::string getServerName() const;
+ std::string getScriptName() const;
+ std::string getRedirectURL() const;
+ std::string getRequestMethod() const;
+ std::string getCookieValue(const std::string & name) const;
+ void setCGICC(const cgicc::Cgicc *);
+ const cgicc::Cgicc * cgi;
std::vector<std::string> elems;
- const cgicc::Cgicc * const cgi;
private:
const Options & engineOptions() const;
@@ -52,9 +58,9 @@ class CgiEnvironment : public Environment, public cgicc::CgiEnvironment {
std::string errorPresentRoot;
std::string notFoundPresent;
std::string onErrorPresent;
- std::string defaultPresenter;
- std::string sessionModule;
- std::string outputEncoding;
+ std::string defaultPresenter;
+ std::string sessionModule;
+ std::string outputEncoding;
};
#endif
diff --git a/project2/cgi/p2webCgi.cpp b/project2/cgi/p2webCgi.cpp
index 0248df6..646d08b 100644
--- a/project2/cgi/p2webCgi.cpp
+++ b/project2/cgi/p2webCgi.cpp
@@ -6,7 +6,8 @@ int
main(void)
{
LoaderBase::onAllComponents(boost::bind(&ComponentLoader::onBegin, _1));
- cgiServe(NULL, std::cout);
+ CgiEnvironment env;
+ cgiServe(NULL, &env, std::cout);
LoaderBase::onAllComponents(boost::bind(&ComponentLoader::onIteration, _1));
LoaderBase::onAllComponents(boost::bind(&ComponentLoader::onPeriodic, _1));
LoaderBase::onAllComponents(boost::bind(&ComponentLoader::onIdle, _1));
diff --git a/project2/cgi/p2webFCgi.cpp b/project2/cgi/p2webFCgi.cpp
index 3b833ed..a1786d2 100644
--- a/project2/cgi/p2webFCgi.cpp
+++ b/project2/cgi/p2webFCgi.cpp
@@ -40,11 +40,12 @@ main(void)
fprintf(stderr, "Failed to set signal handler\n");
}
alarm(60);
+ CgiEnvironment env;
LoaderBase::onAllComponents(boost::bind(&ComponentLoader::onBegin, _1));
while (FCGX_Accept_r(&request) == 0) {
alarm(0);
cgicc::FCgiIO IO(request);
- cgiServe(&IO, IO);
+ cgiServe(&IO, &env, IO);
alarm(60);
LoaderBase::onAllComponents(boost::bind(&ComponentLoader::onIteration, _1));
if (time(NULL) > lastPeriodic + periodicDelay) {
diff --git a/project2/cgi/testCgi.cpp b/project2/cgi/testCgi.cpp
index 6250cb0..1d3f72c 100644
--- a/project2/cgi/testCgi.cpp
+++ b/project2/cgi/testCgi.cpp
@@ -75,11 +75,12 @@ class TestInput : public cgicc::CgiInput {
void run()
{
for (int run = 0; run < runCount; run += 1) {
- cgiServe(this, std::cout);
+ cgiServe(this, &env, std::cout);
}
}
private:
+ CgiEnvironment env;
Options opts;
int runCount;
};
diff --git a/project2/common/environment.cpp b/project2/common/environment.cpp
index 2047813..c0f84a2 100644
--- a/project2/common/environment.cpp
+++ b/project2/common/environment.cpp
@@ -10,11 +10,11 @@
#include <boost/bind.hpp>
const Environment * Environment::currentEnv(NULL);
-int Environment::clLevel(-1);
-int Environment::slLevel(-1);
Environment::Environment() :
- commonOptions("Project2 Common options")
+ commonOptions("Project2 Common options"),
+ clLevel(-1),
+ slLevel(-1)
{
currentEnv = this;
commonOptions
@@ -31,6 +31,10 @@ Environment::Environment() :
("common.sessionTimeOut", Options::value(&sessionTimeOut, 3600),
"The time after which idle sessions are forgotten")
;
+ typedef std::map<std::string, boost::shared_ptr<OptionsSourceLoader> > ConfigParsersMap;
+ BOOST_FOREACH(const ConfigParsersMap::value_type & cp, *LoaderBase::objLoaders<OptionsSourceLoader>()) {
+ configs.push_back(cp.second->create());
+ }
}
typedef std::vector<const Options *> AllOptions;
@@ -66,26 +70,27 @@ class DefaultConfigConsumer : public ConfigConsumer {
void
Environment::init()
{
- DefaultConfigConsumer dcc;
- dcc.allOptions.push_back(&commonOptions);
- dcc.allOptions.push_back(&engineOptions());
- LoaderBase::onAllComponents(boost::bind(optionsHelper, &dcc.allOptions, boost::bind(&ComponentLoader::options, _1)));
+ if (std::find_if(configs.begin(), configs.end(), boost::bind(&OptionsSource::needReload, _1)) != configs.end()) {
+ DefaultConfigConsumer dcc;
+ dcc.allOptions.push_back(&commonOptions);
+ dcc.allOptions.push_back(&engineOptions());
+ LoaderBase::onAllComponents(boost::bind(optionsHelper, &dcc.allOptions, boost::bind(&ComponentLoader::options, _1)));
- BOOST_FOREACH(const AllOptions::value_type & v, dcc.allOptions) {
- v->reset();
- }
-
- typedef std::map<std::string, boost::shared_ptr<OptionsSourceLoader> > ConfigParsersMap;
- BOOST_FOREACH(const ConfigParsersMap::value_type & cp, *LoaderBase::objLoaders<OptionsSourceLoader>()) {
- cp.second->create()->loadInto(dcc);
- }
+ BOOST_FOREACH(const AllOptions::value_type & v, dcc.allOptions) {
+ v->reset();
+ }
- Logger()->clear();
- if (clLevel >= 0) {
- Logger()->addLogger(new ConsoleLogDriver(stderr, clLevel, false));
- }
- if (slLevel >= 0) {
- Logger()->addLogger(new SyslogLogDriver(getScriptName().c_str(), slLevel));
+ BOOST_FOREACH(const ConfigsMap::value_type & c, configs) {
+ c->loadInto(dcc);
+ }
+ Logger()->clear();
+ if (clLevel >= 0) {
+ Logger()->addLogger(new ConsoleLogDriver(stderr, clLevel, false));
+ }
+ if (slLevel >= 0) {
+ Logger()->addLogger(new SyslogLogDriver(getScriptName().c_str(), slLevel));
+ }
+ Logger()->message(LOG_DEBUG, "Loaded configuration");
}
}
diff --git a/project2/common/environment.h b/project2/common/environment.h
index 0c33283..894b2f8 100644
--- a/project2/common/environment.h
+++ b/project2/common/environment.h
@@ -5,7 +5,7 @@
#include <glibmm/ustring.h>
#include <boost/function.hpp>
#include <boost/filesystem/path.hpp>
-#include "options.h"
+#include "optionsSource.h"
#include "exceptions.h"
#include "scripts.h"
@@ -36,8 +36,10 @@ class Environment {
static const Environment * currentEnv;
- static int clLevel;
- static int slLevel;
+ int clLevel;
+ int slLevel;
+ typedef std::vector<OptionsSourcePtr> ConfigsMap;
+ ConfigsMap configs;
public:
std::string datasourceRoot;
diff --git a/project2/common/optionsSource.h b/project2/common/optionsSource.h
index c73a500..f238a66 100644
--- a/project2/common/optionsSource.h
+++ b/project2/common/optionsSource.h
@@ -17,6 +17,7 @@ class ConfigConsumer {
class OptionsSource : public IntrusivePtrBase {
public:
virtual void loadInto(const ConfigConsumer &) const = 0;
+ virtual bool needReload() const = 0;
};
typedef boost::intrusive_ptr<OptionsSource> OptionsSourcePtr;
diff --git a/project2/console/claOptions.cpp b/project2/console/claOptions.cpp
index b931392..4660134 100644
--- a/project2/console/claOptions.cpp
+++ b/project2/console/claOptions.cpp
@@ -11,6 +11,9 @@ SimpleMessageException(UnknownOption);
class CommandLineArguments : public OptionsSource {
public:
+ CommandLineArguments() :
+ loadedAt(0) {
+ }
void loadInto(const ConfigConsumer & consume) const {
int argc = ConsoleEnvironment::argc;
char ** argv = ConsoleEnvironment::argv;
@@ -74,7 +77,14 @@ class CommandLineArguments : public OptionsSource {
}
}
}
+ time(&loadedAt);
+ }
+ bool needReload() const
+ {
+ return !loadedAt;
}
+ private:
+ mutable time_t loadedAt;
};
// A... process first :)
diff --git a/project2/files/optionsSource.cpp b/project2/files/optionsSource.cpp
index 84c06dc..50e924d 100644
--- a/project2/files/optionsSource.cpp
+++ b/project2/files/optionsSource.cpp
@@ -5,12 +5,14 @@
#include <boost/algorithm/string/trim.hpp>
FileOptions::FileOptions() :
- file(".p2config")
+ file(".p2config"),
+ loadedAt(0)
{
}
FileOptions::FileOptions(const Glib::ustring & f) :
- file(f)
+ file(f),
+ loadedAt(0)
{
}
@@ -53,11 +55,25 @@ FileOptions::loadInto(const ConfigConsumer & consume) const {
break;
}
}
+ struct stat st;
+ if (stat(file.c_str(), &st) == 0) {
+ loadedAt = st.st_mtime;
+ }
}
catch (const Glib::FileError &) {
}
}
+bool
+FileOptions::needReload() const
+{
+ struct stat st;
+ if (stat(file.c_str(), &st) != 0) {
+ return true;
+ }
+ return (loadedAt != st.st_mtime);
+}
+
// Z... process last :)
DECLARE_COMPONENT_LOADER("Z_configfile", FileOptions, OptionsSourceLoader)
diff --git a/project2/files/optionsSource.h b/project2/files/optionsSource.h
index 722d7b9..5cd5250 100644
--- a/project2/files/optionsSource.h
+++ b/project2/files/optionsSource.h
@@ -9,8 +9,11 @@ class FileOptions : public OptionsSource {
FileOptions(const Glib::ustring & file);
void loadInto(const ConfigConsumer & consume) const;
+ bool needReload() const;
+
private:
const Glib::ustring file;
+ mutable time_t loadedAt;
};
#endif