diff options
-rw-r--r-- | project2/json/couchSession.cpp | 188 |
1 files changed, 0 insertions, 188 deletions
diff --git a/project2/json/couchSession.cpp b/project2/json/couchSession.cpp deleted file mode 100644 index 51d466c..0000000 --- a/project2/json/couchSession.cpp +++ /dev/null @@ -1,188 +0,0 @@ -#include <pch.hpp> -#include "curlHelper.h" -#include "safeMapFind.h" -#include "exceptions.h" -#include "logger.h" -#include "buffer.h" -#include "curlsup.h" -#include <scriptLoader.h> -#include <sessionContainer.h> -#include <boost/bind.hpp> -#include <boost/lexical_cast.hpp> -#include <boost/uuid/uuid_io.hpp> -#include <boost/uuid/uuid_generators.hpp> -#include "jsonpp.h" -#include "safeMapFind.h" -#include "conversion.h" -#include "options.h" - -class CouchDBFailure : public std::exception { }; - -class CouchSessionContainer : public SessionContainer { - public: - CouchSessionContainer() { - } - virtual SessionPtr getSession(const boost::uuids::uuid & uuid) const { - try { - json::Object obj = getSessionFromServer(uuid); - if (boost::get<json::Number>(*safeMapLookup<Session::VariableNotFound>(obj, ExpiryKey)) > time(NULL)) { - SessionPtr s = new Session(uuid); - for (const json::Object::value_type & v : obj) { - s->SetValue(v.first, boost::apply_visitor(JsonToProject2(), *v.second)); - } - return s; - } - } - catch (...) { - } - return NULL; - } - - virtual void SaveSession(SessionPtr s) const { - CurlPtr c = new Curl(); - c->setopt(CURLOPT_UPLOAD, 1L); - c->setopt(CURLOPT_FAILONERROR, 1); - json::Object obj; - s->ForeachValue(boost::bind(&CouchSessionContainer::addToObject, &obj, _1, _2)); - obj[ExpiryKey] = json::ValuePtr(new json::Value((json::Number)s->ExpiryTime())); - Glib::ustring out = json::serializeObject(obj, "utf-8"); - c->setopt(CURLOPT_INFILESIZE_LARGE, (curl_off_t)out.size()); - unsigned int off = 0; - for (const std::string & b : baseUrls) { - c->setopt(CURLOPT_URL, (b + boost::lexical_cast<std::string>(s->ID())).c_str()); - try { - c->performSend(boost::bind(send, &out, &off, _1, _2)); - return; - } - catch (...) { - } - } - throw CouchDBFailure(); - } - - json::Object getSessionFromServer(const boost::uuids::uuid & uuid) const { - CurlPtr c = new Curl(); - c->setopt(CURLOPT_FAILONERROR, 1); - Glib::ustring msg; - for (const std::string & b : baseUrls) { - try { - c->setopt(CURLOPT_URL, (b + boost::lexical_cast<std::string>(uuid)).c_str()); - c->performRead(boost::bind(append, &msg, _1, _2)); - json::Object o = json::parseObject(msg); - return o; - } - catch (...) { - } - } - throw CouchDBFailure(); - } - - private: - static void addToObject(json::Object * obj, const Glib::ustring & name, const VariableType & value) { - (*obj)[name] = json::ValuePtr(new json::Value(boost::apply_visitor(Project2ToJson(), value))); - } - - static size_t send(Glib::ustring * buf, unsigned int * off, char * str, size_t l) { - size_t len = std::min(buf->size() - *off, l); - memcpy(str, buf->c_str() + *off, len); - return len; - } - - static size_t append(Glib::ustring * buf, const char * str, size_t l) { - buf->append(str, l); - return l; - } - - void setopt_s(CurlHandle::Ptr c, CURLoption o, const char * v) { - c->setopt(o, v); - } - - void setopt_l(CurlHandle::Ptr c, CURLoption o, int64_t v) { - c->setopt(o, (long)v); - } - - static std::vector<std::string> baseUrls; - static const Glib::ustring ExpiryKey; - friend class CustomCouchSessionLoader; -}; -std::vector<std::string> CouchSessionContainer::baseUrls; -const Glib::ustring CouchSessionContainer::ExpiryKey("project2:expires"); - -class CustomCouchSessionLoader : public SessionContainerLoader::For<CouchSessionContainer> { - public: - void onPeriodic() override { - try { - deleteSessions(); - compactDB(); - } - catch (...) { - Logger()->messagebf(LOG_WARNING, "Failed to purge expired sessions and compact DB"); - } - } - - INITOPTIONS; - private: - static size_t discard(size_t l) { - return l; - } - - void compactDB() { - CurlPtr c = new Curl(); - c->setopt(CURLOPT_POST, 1); - c->appendHeader("Content-Type: application/json"); - for (const std::string & b : CouchSessionContainer::baseUrls) { - c->setopt(CURLOPT_URL, (b + "_compact").c_str()); - c->performRead(boost::bind(discard, _2)); - } - } - void deleteSessions() { - // Create the server side search map - json::Object map; - Buffer mapBuf; - mapBuf.appendf("function(doc) { var exp = doc['%s']; if (exp < %u) { emit(exp, doc._rev); } }", - CouchSessionContainer::ExpiryKey.c_str(), (unsigned int)time(NULL)); - map["map"] = json::ValuePtr(new json::Value(mapBuf.str())); - Glib::ustring mapStr(json::serializeObject(map, "utf-8")); - // Create the CURL handle - CurlPtr c = new Curl(); - c->setopt(CURLOPT_FAILONERROR, 1); - c->appendHeader("Content-Type: application/json"); - c->setopt(CURLOPT_POST, 1); - c->setopt(CURLOPT_POSTFIELDS, mapStr.c_str()); - c->setopt(CURLOPT_POSTFIELDSIZE, mapStr.bytes()); - for (const std::string & b : CouchSessionContainer::baseUrls) { - Glib::ustring msg; - try { - c->setopt(CURLOPT_URL, (b + "_temp_view").c_str()); - c->performRead(boost::bind(CouchSessionContainer::append, &msg, _1, _2)); - json::Object o = json::parseObject(msg); - for (const json::Array::value_type & v : boost::get<json::Array>(*safeMapLookup<ParamNotFound>(o, "rows"))) { - json::Object rec = boost::get<json::Object>(*v); - boost::uuids::uuid u = boost::uuids::string_generator()(boost::get<json::String>(*safeMapLookup<ParamNotFound>(rec, "id")).raw()); - Glib::ustring & rev = boost::get<json::String>(*safeMapLookup<ParamNotFound>(rec, "value")); - deleteSession(u, rev); - } - return; - } - catch (...) { - } - } - } - - void deleteSession(const boost::uuids::uuid & sid, const Glib::ustring & rev) const { - CurlPtr c = new Curl(); - c->setopt(CURLOPT_CUSTOMREQUEST, "DELETE"); - for (const std::string & b : CouchSessionContainer::baseUrls) { - c->setopt(CURLOPT_URL, (b + boost::lexical_cast<std::string>(sid) + "?rev=" + rev).c_str()); - c->performRead(boost::bind(discard, _2)); - return; - } - } -}; -DECLARE_CUSTOM_COMPONENT_LOADER("couchsession", CouchSessionContainer, CustomCouchSessionLoader, SessionContainerLoader); - -DECLARE_OPTIONS(CustomCouchSessionLoader, "Session CouchDB options") -("session.couchdb.baseUrl", Options::functions([](const VariableType & v) { CouchSessionContainer::baseUrls.push_back(v); }, boost::bind(&std::vector<std::string>::clear, &CouchSessionContainer::baseUrls)), - "Base URL to store sessions in") -END_OPTIONS(CustomCouchSessionLoader); - |