diff options
author | randomdan <randomdan@localhost> | 2010-08-31 19:51:02 +0000 |
---|---|---|
committer | randomdan <randomdan@localhost> | 2010-08-31 19:51:02 +0000 |
commit | ac4136de947054a1673a9bc004e47824ada549ce (patch) | |
tree | e4fcd16d531847ad17961f97d0d588e4cf659400 | |
parent | Add alarm to be called when p2web has been idle for 60seconds (diff) | |
download | project2-ac4136de947054a1673a9bc004e47824ada549ce.tar.bz2 project2-ac4136de947054a1673a9bc004e47824ada549ce.tar.xz project2-ac4136de947054a1673a9bc004e47824ada549ce.zip |
Drop the pain in the ass SHM session container in favour of an XML one
Fix setting the environment up in p2console
-rw-r--r-- | project2/cgi/cgiAppEngine.cpp | 6 | ||||
-rw-r--r-- | project2/console/consoleAppEngine.cpp | 3 | ||||
-rw-r--r-- | project2/console/consoleEnvironment.cpp | 1 | ||||
-rw-r--r-- | project2/sessionShm.cpp | 143 | ||||
-rw-r--r-- | project2/sessionShm.h | 38 | ||||
-rw-r--r-- | project2/sessionXml.cpp | 171 | ||||
-rw-r--r-- | project2/sessionXml.h | 18 |
7 files changed, 195 insertions, 185 deletions
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 <boost/bind.hpp> #include <boost/lexical_cast.hpp> #include <boost/uuid/uuid_io.hpp> -#include "../sessionShm.h" +#include "../sessionXml.h" #include <boost/uuid/uuid_generators.hpp> 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<Glib::ustring>(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 <libxml/xinclude.h> 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 <sys/utsname.h> #include <syslog.h> #include <errno.h> +#include <stdio.h> #include <string.h> 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 <syslog.h> -#include <set> -#include <boost/uuid/uuid.hpp> -#include <boost/foreach.hpp> -#include <boost/uuid/uuid_generators.hpp> -#include <boost/lexical_cast.hpp> -#include <boost/uuid/uuid_io.hpp> - -using namespace boost::interprocess; -using namespace boost::uuids; -class SessionShmData { - public: - typedef boost::interprocess::string SKey; - typedef boost::interprocess::string SValue; - - typedef std::pair<const SKey, SValue> SValueType; - typedef boost::interprocess::allocator<SValueType, boost::interprocess::managed_mapped_file::segment_manager> AllocatorValueType; - typedef boost::interprocess::map<SKey, SValue, std::less<SKey>, AllocatorValueType> SessionValues; - - SessionShmData(); - ~SessionShmData(); - - SessionValues svs; - time_t expiryTime; - - static boost::interprocess::managed_mapped_file & shm(); - static boost::shared_ptr<boost::interprocess::managed_mapped_file> _shm; - friend class SessionContainerShm; -}; - -const char * shmFile = "/tmp/project2.sessions"; - -boost::shared_ptr<boost::interprocess::managed_mapped_file> SessionShmData::_shm; - -SessionContainerShm::SessionContainerShm() -{ -} - -SessionContainerShm::~SessionContainerShm() -{ -} - -void -SessionContainerShm::CleanUp() -{ - std::set<std::string> toDelete; - for (managed_mapped_file::const_named_iterator i = SessionShmData::shm().named_begin(); - i != SessionShmData::shm().named_end(); i++) { - const SessionShmData * s = static_cast<const SessionShmData *>(i->value()); - if (s) { - if (s->expiryTime < time(NULL)) { - toDelete.insert(i->name()); - } - } - } - for(std::set<std::string>::const_iterator s = toDelete.begin(); s != toDelete.end(); s++) { - SessionShmData::shm().destroy<const SessionShmData>(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<SessionShmData>(boost::lexical_cast<std::string>(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<SKey>(), AllocatorValueType(shm().get_segment_manager())) -{ -} - -SessionShmData::~SessionShmData() -{ -} - -boost::interprocess::managed_mapped_file & -SessionShmData::shm() -{ - if (!_shm) { - _shm = boost::shared_ptr<boost::interprocess::managed_mapped_file>( - 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<SessionShmData::SKey, SessionShmData::SValue>(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 <boost/interprocess/containers/string.hpp> -#include <boost/interprocess/managed_mapped_file.hpp> -#include <boost/interprocess/allocators/allocator.hpp> -#include <boost/interprocess/containers/map.hpp> - -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 <libxml++/nodes/element.h> +#include <libxml++/parsers/domparser.h> +#include <libxml++/nodes/textnode.h> +#include <set> +#include <boost/uuid/uuid.hpp> +#include <boost/foreach.hpp> +#include <boost/uuid/uuid_generators.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/uuid/uuid_io.hpp> + +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<SessionXml> 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<std::string>(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<Glib::ustring>(currentSession->sessionID)); + sess->set_attribute("expires", boost::lexical_cast<Glib::ustring>(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<std::string>(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<const xmlpp::Element *>(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<uuid>(p->get_attribute_value("id"))), + expires(boost::lexical_cast<time_t>(p->get_attribute_value("expires"))) +{ + xmlpp::NodeSet xvars = p->find("var"); + BOOST_FOREACH(const xmlpp::Node * n, xvars) { + const xmlpp::Element * e = dynamic_cast<const xmlpp::Element *>(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 <map> + +class SessionContainerXml : public SessionContainer { + public: + SessionContainerXml(); + ~SessionContainerXml(); + + void CleanUp(); + + protected: + SessionPtr getSession(boost::uuids::uuid & sid); +}; + +#endif |