summaryrefslogtreecommitdiff
path: root/icespider/fileSessions/fileSessions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'icespider/fileSessions/fileSessions.cpp')
-rw-r--r--icespider/fileSessions/fileSessions.cpp132
1 files changed, 132 insertions, 0 deletions
diff --git a/icespider/fileSessions/fileSessions.cpp b/icespider/fileSessions/fileSessions.cpp
new file mode 100644
index 0000000..d2d5823
--- /dev/null
+++ b/icespider/fileSessions/fileSessions.cpp
@@ -0,0 +1,132 @@
+#include <core.h>
+#include <session.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <factory.impl.h>
+#include <boost/filesystem/operations.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <Ice/Stream.h>
+#include "Ice/Initialize.h"
+
+namespace IceSpider {
+ class FileSessions : public Plugin, public SessionManager {
+ public:
+ FileSessions(Ice::CommunicatorPtr c, Ice::PropertiesPtr p) :
+ ic(c),
+ root(p->getProperty("IceSpider.FileSessions.Path")),
+ duration(p->getPropertyAsIntWithDefault("IceSpider.FileSessions.Duration", 3600))
+ {
+ if (!root.empty())
+ if (!boost::filesystem::exists(root))
+ boost::filesystem::create_directories(root);
+ }
+
+ ~FileSessions()
+ {
+ removeExpired();
+ }
+
+ SessionPtr createSession(const ::Ice::Current &) override
+ {
+ SessionPtr s = new Session();
+ s->id = boost::lexical_cast<std::string>(boost::uuids::random_generator()());
+ s->duration = duration;
+ save(s);
+ return s;
+ }
+
+ SessionPtr getSession(const ::std::string & id, const ::Ice::Current & current) override
+ {
+ auto s = load(id);
+ if (s && isExpired(s)) {
+ destroySession(id, current);
+ return NULL;
+ }
+ return s;
+ }
+
+ void updateSession(const SessionPtr & s, const ::Ice::Current &) override
+ {
+ save(s);
+ }
+
+ void destroySession(const ::std::string & id, const ::Ice::Current &) override
+ {
+ try {
+ boost::filesystem::remove(root / id);
+ }
+ catch (const std::exception & e) {
+ throw SessionError(e.what());
+ }
+ }
+
+ private:
+ void save(SessionPtr s)
+ {
+ time(&s->lastUsed);
+ auto buf = Ice::createOutputStream(ic);
+ buf->write(s);
+ auto range = buf->finished();
+ auto fd = sysassert(open((root / s->id).c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR), -1);
+ sysassert(flock(fd, LOCK_EX), -1);
+ sysassert(pwrite(fd, range.first, range.second - range.first, 0), -1);
+ sysassert(ftruncate(fd, range.second - range.first), -1);
+ sysassert(flock(fd, LOCK_UN), -1);
+ sysassert(close(fd), -1);
+ }
+
+ SessionPtr load(const std::string & id)
+ {
+ int fd = open((root / id).c_str(), O_RDONLY);
+ if (fd == -1 && errno == ENOENT) return NULL;
+ sysassert(fd, -1);
+ sysassert(flock(fd, LOCK_SH), -1);
+ struct stat st;
+ sysassert(fstat(fd, &st), -1);
+ auto fbuf = sysassert((Ice::Byte *)mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0), (Ice::Byte *)NULL);
+ auto buf = Ice::createInputStream(ic, std::make_pair(fbuf, fbuf + st.st_size));
+ SessionPtr s;
+ buf->read(s);
+ sysassert(flock(fd, LOCK_UN), -1);
+ sysassert(close(fd), -1);
+ return s;
+ }
+
+ void removeExpired()
+ {
+ if (root.empty() || !boost::filesystem::exists(root)) return;
+ boost::filesystem::directory_iterator di(root);
+ while (di != boost::filesystem::directory_iterator()) {
+ auto s = load(di->path().leaf().string());
+ if (s && isExpired(s)) {
+ destroySession(s->id, Ice::Current());
+ }
+ di++;
+ }
+ }
+
+ bool isExpired(SessionPtr s)
+ {
+ return (s->lastUsed + s->duration < time(NULL));
+ }
+
+ template<typename R, typename ER>
+ R sysassert(R rtn, ER ertn)
+ {
+ if (rtn == ertn) {
+ fprintf(stderr, "%s\n", strerror(errno));
+ throw SessionError(strerror(errno));
+ }
+ return rtn;
+ }
+
+ Ice::CommunicatorPtr ic;
+ const boost::filesystem::path root;
+ const Ice::Int duration;
+ };
+}
+NAMEDFACTORY("IceSpider-FileSessions", IceSpider::FileSessions, IceSpider::PluginFactory);
+