From ac4136de947054a1673a9bc004e47824ada549ce Mon Sep 17 00:00:00 2001 From: randomdan Date: Tue, 31 Aug 2010 19:51:02 +0000 Subject: Drop the pain in the ass SHM session container in favour of an XML one Fix setting the environment up in p2console --- project2/cgi/cgiAppEngine.cpp | 6 +- project2/console/consoleAppEngine.cpp | 3 +- project2/console/consoleEnvironment.cpp | 1 + project2/sessionShm.cpp | 143 -------------------------- project2/sessionShm.h | 38 ------- project2/sessionXml.cpp | 171 ++++++++++++++++++++++++++++++++ project2/sessionXml.h | 18 ++++ 7 files changed, 195 insertions(+), 185 deletions(-) delete mode 100644 project2/sessionShm.cpp delete mode 100644 project2/sessionShm.h create mode 100644 project2/sessionXml.cpp create mode 100644 project2/sessionXml.h diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp index f37172e..e419ddf 100644 --- a/project2/cgi/cgiAppEngine.cpp +++ b/project2/cgi/cgiAppEngine.cpp @@ -9,14 +9,14 @@ #include #include #include -#include "../sessionShm.h" +#include "../sessionXml.h" #include const std::string SESSIONID = "sessionID"; typedef boost::uuids::uuid SIDKey; typedef std::string SValue; -SessionContainer * sessionsContainer = new SessionContainerShm(); +SessionContainer * sessionsContainer = new SessionContainerXml(); CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e) : ApplicationEngine(), @@ -118,7 +118,7 @@ CgiApplicationEngine::PresentStage::getDataDocument() const xmlpp::Element * sessionXml = responseRoot->add_child("session", "project2"); sessionXml->set_attribute("id", boost::lexical_cast(appEngine->sessionID)); Session::Values session(sessionsContainer->GetSession(appEngine->sessionID)->GetValuesCopy()); - BOOST_FOREACH(SessionShm::Values::value_type sv, session) { + BOOST_FOREACH(Session::Values::value_type sv, session) { xmlpp::Element * param = sessionXml->add_child("var", "project2"); param->add_child_text(sv.second); param->set_attribute("name", sv.first); diff --git a/project2/console/consoleAppEngine.cpp b/project2/console/consoleAppEngine.cpp index 035f60a..e58bf5d 100644 --- a/project2/console/consoleAppEngine.cpp +++ b/project2/console/consoleAppEngine.cpp @@ -5,7 +5,8 @@ #include ConsoleApplicationEngine::ConsoleApplicationEngine(const ConsoleEnvironment * env, const boost::filesystem::path & f) : - ApplicationEngine() + ApplicationEngine(), + _env(env) { xmlpp::DomParser request(f.string()); while (xmlXIncludeProcessFlags(request.get_document()->cobj(), XML_PARSE_NOXINCNODE) > 0); diff --git a/project2/console/consoleEnvironment.cpp b/project2/console/consoleEnvironment.cpp index 314f465..0d2f026 100644 --- a/project2/console/consoleEnvironment.cpp +++ b/project2/console/consoleEnvironment.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include ConsoleEnvironment::ConsoleEnvironment(int argc, char ** argv) : diff --git a/project2/sessionShm.cpp b/project2/sessionShm.cpp deleted file mode 100644 index 8064142..0000000 --- a/project2/sessionShm.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "sessionShm.h" -#include -#include -#include -#include -#include -#include -#include - -using namespace boost::interprocess; -using namespace boost::uuids; -class SessionShmData { - public: - typedef boost::interprocess::string SKey; - typedef boost::interprocess::string SValue; - - typedef std::pair SValueType; - typedef boost::interprocess::allocator AllocatorValueType; - typedef boost::interprocess::map, AllocatorValueType> SessionValues; - - SessionShmData(); - ~SessionShmData(); - - SessionValues svs; - time_t expiryTime; - - static boost::interprocess::managed_mapped_file & shm(); - static boost::shared_ptr _shm; - friend class SessionContainerShm; -}; - -const char * shmFile = "/tmp/project2.sessions"; - -boost::shared_ptr SessionShmData::_shm; - -SessionContainerShm::SessionContainerShm() -{ -} - -SessionContainerShm::~SessionContainerShm() -{ -} - -void -SessionContainerShm::CleanUp() -{ - std::set toDelete; - for (managed_mapped_file::const_named_iterator i = SessionShmData::shm().named_begin(); - i != SessionShmData::shm().named_end(); i++) { - const SessionShmData * s = static_cast(i->value()); - if (s) { - if (s->expiryTime < time(NULL)) { - toDelete.insert(i->name()); - } - } - } - for(std::set::const_iterator s = toDelete.begin(); s != toDelete.end(); s++) { - SessionShmData::shm().destroy(s->c_str()); - } -} - -SessionPtr -SessionContainerShm::getSession(boost::uuids::uuid & sid) -{ - if (sid.is_nil()) { - sid = boost::uuids::random_generator()(); - } - return SessionPtr(new SessionShm( - SessionShmData::shm().find_or_construct(boost::lexical_cast(sid).c_str())())); -} - -SessionShm::SessionShm(SessionShmData * d) : data(d) -{ -} - -SessionShm::~SessionShm() -{ -} - -void -SessionShm::ExpiryTime(time_t t) -{ - data->expiryTime = t; -} - -time_t -SessionShm::ExpiryTime() const -{ - return data->expiryTime; -} - -SessionShmData::SessionShmData() : - svs(std::less(), AllocatorValueType(shm().get_segment_manager())) -{ -} - -SessionShmData::~SessionShmData() -{ -} - -boost::interprocess::managed_mapped_file & -SessionShmData::shm() -{ - if (!_shm) { - _shm = boost::shared_ptr( - new boost::interprocess::managed_mapped_file(open_or_create, shmFile, 1024 * 1024)); - } - return *_shm; -} - -Glib::ustring -SessionShm::GetValue(const Glib::ustring & name) const -{ - SessionShmData::SessionValues::const_iterator i = data->svs.find(name.c_str()); - if (i == data->svs.end()) { - throw Session::VariableNotFound(); - } - return i->second.c_str(); -} - -void -SessionShm::SetValue(const Glib::ustring & name, const Glib::ustring & value) -{ - data->svs.erase(name.c_str()); - data->svs.insert(std::pair(name.c_str(), value.c_str())); -} - -void -SessionShm::ClearValue(const Glib::ustring & name) -{ - data->svs.erase(name.c_str()); -} - -Session::Values -SessionShm::GetValuesCopy() const -{ - Values v; - BOOST_FOREACH(SessionShmData::SessionValues::value_type kvp, data->svs) { - v[kvp.first.c_str()] = kvp.second.c_str(); - } - return v; -} - diff --git a/project2/sessionShm.h b/project2/sessionShm.h deleted file mode 100644 index 2794303..0000000 --- a/project2/sessionShm.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef SESSIONSHM_H -#define SESSIONSHM_H - -#include "session.h" -#include -#include -#include -#include - -class SessionShmData; -class SessionShm : public Session { - public: - SessionShm(SessionShmData *); - virtual ~SessionShm(); - - Glib::ustring GetValue(const Glib::ustring & name) const; - Values GetValuesCopy() const; - void SetValue(const Glib::ustring & name, const Glib::ustring & value); - void ClearValue(const Glib::ustring & name); - time_t ExpiryTime() const; - void ExpiryTime(time_t); - - private: - SessionShmData * data; -}; - -class SessionContainerShm : public SessionContainer { - public: - SessionContainerShm(); - ~SessionContainerShm(); - - void CleanUp(); - - protected: - SessionPtr getSession(boost::uuids::uuid & sid); -}; - -#endif diff --git a/project2/sessionXml.cpp b/project2/sessionXml.cpp new file mode 100644 index 0000000..68e19ea --- /dev/null +++ b/project2/sessionXml.cpp @@ -0,0 +1,171 @@ +#include "sessionXml.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::uuids; +class SessionXml : public Session { + public: + SessionXml(boost::uuids::uuid & sid); + SessionXml(const xmlpp::Element *); + virtual ~SessionXml(); + + Glib::ustring GetValue(const Glib::ustring & name) const; + Values GetValuesCopy() const; + void SetValue(const Glib::ustring & name, const Glib::ustring & value); + void ClearValue(const Glib::ustring & name); + time_t ExpiryTime() const; + void ExpiryTime(time_t); + + const uuid sessionID; + + private: + Values vars; + time_t expires; + + friend class SessionContainerXml; +}; +typedef boost::intrusive_ptr SessionXmlPtr; + + +const char * xmlFile = "/tmp/project2sessions.xml"; +SessionXmlPtr currentSession; + +SessionContainerXml::SessionContainerXml() +{ +} + +SessionContainerXml::~SessionContainerXml() +{ + CleanUp(); +} + +void +SessionContainerXml::CleanUp() +{ + if (currentSession) { + xmlpp::DomParser parser; + xmlpp::Document * doc; + try { + parser.parse_file(xmlFile); + doc = parser.get_document(); + char xpath[200]; + snprintf(xpath, 200, "/sessions/session[@id='%s' or @expires < %lu]", + boost::lexical_cast(currentSession->sessionID).c_str(), time(NULL)); + xmlpp::NodeSet sess = doc->get_root_node()->find(xpath); + BOOST_FOREACH(xmlpp::Node * n, sess) { + n->get_parent()->remove_child(n); + } + } + catch (...) { + doc = new xmlpp::Document(); + doc->create_root_node("sessions"); + } + xmlpp::Element * sess = doc->get_root_node()->add_child("session"); + sess->set_attribute("id", boost::lexical_cast(currentSession->sessionID)); + sess->set_attribute("expires", boost::lexical_cast(currentSession->expires)); + BOOST_FOREACH(const SessionXml::Values::value_type & nvp, currentSession->vars) { + xmlpp::Element * v = sess->add_child("var"); + v->add_child_text(nvp.second); + v->set_attribute("name", nvp.first); + } + doc->write_to_file(xmlFile); + if (!parser) { + delete doc; + } + currentSession = NULL; + } +} + +SessionPtr +SessionContainerXml::getSession(boost::uuids::uuid & sid) +{ + if (!currentSession || currentSession->sessionID != sid) { + try { + xmlpp::DomParser sessions(xmlFile); + char xpath[200]; + snprintf(xpath, 200, "/sessions/session[@id='%s' and @expires > %lu]", + boost::lexical_cast(sid).c_str(), time(NULL)); + xmlpp::NodeSet sess = sessions.get_document()->get_root_node()->find(xpath); + if (sess.size() == 1) { + currentSession = new SessionXml(dynamic_cast(sess[0])); + } + else { + currentSession = new SessionXml(sid); + } + } + catch (...) { + currentSession = new SessionXml(sid); + } + } + return currentSession; +} + +SessionXml::SessionXml(boost::uuids::uuid & sid) : + sessionID(sid.is_nil() ? sid = boost::uuids::random_generator()() : sid) +{ +} + +SessionXml::SessionXml(const xmlpp::Element * p) : + sessionID(boost::lexical_cast(p->get_attribute_value("id"))), + expires(boost::lexical_cast(p->get_attribute_value("expires"))) +{ + xmlpp::NodeSet xvars = p->find("var"); + BOOST_FOREACH(const xmlpp::Node * n, xvars) { + const xmlpp::Element * e = dynamic_cast(n); + if (e) { + vars[e->get_attribute_value("name")] = e->get_child_text()->get_content(); + } + } +} + +SessionXml::~SessionXml() +{ +} + +void +SessionXml::ExpiryTime(time_t t) +{ + expires = t; +} + +time_t +SessionXml::ExpiryTime() const +{ + return expires; +} + +Glib::ustring +SessionXml::GetValue(const Glib::ustring & name) const +{ + Values::const_iterator i = vars.find(name); + if (i == vars.end()) { + throw Session::VariableNotFound(); + } + return i->second; +} + +void +SessionXml::SetValue(const Glib::ustring & name, const Glib::ustring & value) +{ + vars[name] = value; +} + +void +SessionXml::ClearValue(const Glib::ustring & name) +{ + vars.erase(name); +} + +Session::Values +SessionXml::GetValuesCopy() const +{ + return vars; +} + diff --git a/project2/sessionXml.h b/project2/sessionXml.h new file mode 100644 index 0000000..6995826 --- /dev/null +++ b/project2/sessionXml.h @@ -0,0 +1,18 @@ +#ifndef SESSIONXML_H +#define SESSIONXML_H + +#include "session.h" +#include + +class SessionContainerXml : public SessionContainer { + public: + SessionContainerXml(); + ~SessionContainerXml(); + + void CleanUp(); + + protected: + SessionPtr getSession(boost::uuids::uuid & sid); +}; + +#endif -- cgit v1.2.3