From c5460032331b9886e4a660169e2d8d8bf7a1edf4 Mon Sep 17 00:00:00 2001 From: randomdan Date: Sun, 27 Nov 2011 16:17:36 +0000 Subject: New memoryCache implementation New mapFind helper function --- project2/common/Jamfile.jam | 2 +- project2/common/commonObjects.cpp | 2 +- project2/common/config.cpp | 4 +- project2/common/iHaveParameters.cpp | 2 +- project2/common/memoryCache.cpp | 175 ++++++++++++++++++++++++++++++++ project2/common/safeMapFind.h | 11 ++ project2/common/session.cpp | 2 +- project2/common/variables-modlookup.cpp | 2 +- project2/console/consoleAppEngine.cpp | 2 +- project2/json/couchSession.cpp | 8 +- project2/xml/xmlDocumentCache.cpp | 2 +- project2/xml/xpathRows.cpp | 2 +- 12 files changed, 200 insertions(+), 14 deletions(-) create mode 100644 project2/common/memoryCache.cpp diff --git a/project2/common/Jamfile.jam b/project2/common/Jamfile.jam index 9f8f012..5bb0507 100644 --- a/project2/common/Jamfile.jam +++ b/project2/common/Jamfile.jam @@ -18,7 +18,7 @@ lib p2common : sourceObject.cpp task.cpp variables.cpp variableConvert.cpp view.cpp xmlObjectLoader.cpp exceptions.cpp cache.cpp sessionContainer.cpp sessionClearTask.cpp session.cpp sessionSetTask.cpp commonObjects.cpp taskHost.cpp checkHost.cpp rowView.cpp rowSet.cpp rowProcessor.cpp config.cpp fileStrmVarWriter.cpp noOutputExecute.cpp columns.cpp scopeObject.cpp - transform.cpp definedColumns.cpp structExceptHandling.cpp validDateCheck.cpp + transform.cpp definedColumns.cpp structExceptHandling.cpp validDateCheck.cpp memoryCache.cpp variables-modconfig.cpp variables-modlocalparam.cpp variables-modlookup.cpp diff --git a/project2/common/commonObjects.cpp b/project2/common/commonObjects.cpp index 2ffa353..8ad1a97 100644 --- a/project2/common/commonObjects.cpp +++ b/project2/common/commonObjects.cpp @@ -12,7 +12,7 @@ CommonObjects::~CommonObjects() RowSetPtr CommonObjects::getSource(const std::string & name) const { - return safeMapFind(rowSets, name)->second; + return safeMapLookup(rowSets, name); } CommonObjects::DataSources::const_iterator diff --git a/project2/common/config.cpp b/project2/common/config.cpp index 6f5b243..cb316e5 100644 --- a/project2/common/config.cpp +++ b/project2/common/config.cpp @@ -51,13 +51,13 @@ Configuration::getCurrentConfig() const { load(); Glib::ustring platformName(resolveCurrentConfig()); - return safeMapFind(platforms, platformName)->second; + return safeMapLookup(platforms, platformName); } const Glib::ustring & Configuration::Platform::getValue(const Glib::ustring & key) const { - return safeMapFind(values, key)->second; + return safeMapLookup(values, key); } Configuration::Platform::Platform(const xmlpp::Element * e) diff --git a/project2/common/iHaveParameters.cpp b/project2/common/iHaveParameters.cpp index 18996e5..cded7e1 100644 --- a/project2/common/iHaveParameters.cpp +++ b/project2/common/iHaveParameters.cpp @@ -23,7 +23,7 @@ IHaveParameters::~IHaveParameters() VariableType IHaveParameters::getParameter(const Glib::ustring & name) const { - return safeMapFind(parameters, name)->second; + return safeMapLookup(parameters, name); } void diff --git a/project2/common/memoryCache.cpp b/project2/common/memoryCache.cpp new file mode 100644 index 0000000..34d2cf9 --- /dev/null +++ b/project2/common/memoryCache.cpp @@ -0,0 +1,175 @@ +#include +#include "logger.h" +#include "cache.h" +#include +#include +#include "rowSet.h" +#include "presenter.h" +#include "safeMapFind.h" +#include +#include +#include + +class MemoryCache : public Cache { + public: + typedef std::vector Key; + class CachedRowSet : public RowSet, public RowSetPresenter { + public: + class MemoryCacheRow : public RowState { + public: + typedef std::map AttrMap; + MemoryCacheRow(const Columns * c) : + columns(c) { + } + const Columns & getColumns() const { + return *columns; + } + RowAttribute resolveAttr(const Glib::ustring & attrName) const { + return boost::bind(&safeMapLookup, attrs, attrName); + } + private: + friend class CachedRowSet; + const Columns * columns; + AttrMap attrs; + }; + typedef boost::shared_ptr MemoryCacheRowPtr; + typedef std::list DataCache; + + CachedRowSet(const std::vector & k) : + RowSet(NULL), + key(k), + createdAt(time(NULL)) + { + } + + void execute(const Glib::ustring&, const RowProcessor * rp) const { + BOOST_FOREACH(const DataCache::value_type & mcr, dataCache) { + mcr->process(rp, false); + } + } + + void addAttribute(const Glib::ustring & name, const VariableType & value) const { + cur->attrs.insert(MemoryCacheRow::AttrMap::value_type(name, value)); + } + + void addNamedValue(const Glib::ustring & name, const VariableType & value) const { + if (cur->fields.size() <= col) { + cur->fields.resize(col + 1); + columns.insert(new Column(col, name)); + } + cur->fields[col++] = value; + } + + void addNewRow(const Glib::ustring&) const { + col = 0; + cur = MemoryCacheRowPtr(new MemoryCacheRow(&columns)); + } + + void finishRow() const { + dataCache.push_back(cur); + cur.reset(); + } + + const Key key; + const time_t createdAt; + + private: + mutable unsigned int col; + mutable Columns columns; + mutable DataCache dataCache; + mutable MemoryCacheRowPtr cur; + + }; + typedef boost::intrusive_ptr CachedRowSetPtr; + typedef boost::intrusive_ptr CachedRowSetCPtr; + + struct IndexByKey { }; + struct IndexByTime { }; + typedef boost::multi_index::multi_index_container< + CachedRowSetCPtr, + boost::multi_index::indexed_by< + boost::multi_index::ordered_unique< + boost::multi_index::tag, BOOST_MULTI_INDEX_MEMBER(CachedRowSet, const Key, key)>, + boost::multi_index::ordered_non_unique< + boost::multi_index::tag, BOOST_MULTI_INDEX_MEMBER(CachedRowSet, const time_t, createdAt)> + > > CacheStore; + + MemoryCache(const xmlpp::Element * p) : + Cache(p) + { + } + + RowSetCPtr getCachedRowSet(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const { + Key key(makeKey(n, f, ps)); + CacheStore::index::type::const_iterator i = Store.get().find(key); + if (i == Store.get().end()) { + return NULL; + } + if ((*i)->createdAt < (time(NULL) - CacheLife)) { + Store.erase(i); + return NULL; + } + return *i; + } + + RowSetPresenterPtr openFor(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) { + return (cur = new CachedRowSet(makeKey(n, f, ps))); + } + + void save(const Glib::ustring & , const Glib::ustring & , const IHaveParameters * ) { + if (cur) { + Store.insert(cur); + cur.reset(); + } + } + + void discard(const Glib::ustring & , const Glib::ustring & , const IHaveParameters * ) { + cur.reset(); + } + + private: + Key makeKey(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const { + Key key; + key.push_back(n); + key.push_back(f); + applyKeys(boost::bind(&Key::push_back, &key, _2), ps); + return key; + } + + CachedRowSetPtr cur; + + friend class CustomMemoryCacheLoader; + static time_t CacheLife; + static CacheStore Store; +}; +time_t MemoryCache::CacheLife; +MemoryCache::CacheStore MemoryCache::Store; + +namespace po = boost::program_options; +class CustomMemoryCacheLoader : public ElementLoaderImpl { + public: + CustomMemoryCacheLoader() : + opts("Memory Cache options") + { + opts.add_options() + ("cache.memory.life", po::value(&MemoryCache::CacheLife)->default_value(3600), + "The age of cache entries after which they are removed (seconds)") + ; + } + + po::options_description * options() { + return &opts; + } + + void onPeriodic() { + typedef MemoryCache::CacheStore::index::type::iterator iter; + iter x = MemoryCache::Store.get().begin(); + iter y = MemoryCache::Store.get().upper_bound(time(NULL) - MemoryCache::CacheLife); + MemoryCache::Store.get().erase(x, y); + } + + private: + po::options_description opts; +}; +DECLARE_CUSTOM_LOADER("memorycache", CustomMemoryCacheLoader); + diff --git a/project2/common/safeMapFind.h b/project2/common/safeMapFind.h index b27caf3..b461074 100644 --- a/project2/common/safeMapFind.h +++ b/project2/common/safeMapFind.h @@ -23,5 +23,16 @@ defaultMapFind(const Map & map, const typename Map::key_type & key, const typena return i->second; } +template +const typename Map::mapped_type & +safeMapLookup(const Map & map, const typename Map::key_type & key) +{ + typename Map::const_iterator i = map.find(key); + if (i == map.end()) { + throw Ex(key); + } + return i->second; +} + #endif diff --git a/project2/common/session.cpp b/project2/common/session.cpp index 9736c4d..fd8f569 100644 --- a/project2/common/session.cpp +++ b/project2/common/session.cpp @@ -32,7 +32,7 @@ Session::Empty() const VariableType Session::GetValue(const Glib::ustring & name) const { - return safeMapFind(vars, name)->second; + return safeMapLookup(vars, name); } void diff --git a/project2/common/variables-modlookup.cpp b/project2/common/variables-modlookup.cpp index 836bfea..408c98b 100644 --- a/project2/common/variables-modlookup.cpp +++ b/project2/common/variables-modlookup.cpp @@ -49,7 +49,7 @@ class VariableLookup : public VariableImplDyn, public RowProcessor { BOOST_FOREACH(const Parameters::value_type & p, parameters) { k.push_back(p.second); } - return safeMapFind(map, k)->second; + return safeMapLookup(map, k); } private: void fillCache() const diff --git a/project2/console/consoleAppEngine.cpp b/project2/console/consoleAppEngine.cpp index cf0548d..a34e078 100644 --- a/project2/console/consoleAppEngine.cpp +++ b/project2/console/consoleAppEngine.cpp @@ -80,7 +80,7 @@ ConsoleApplicationEngine::addAppData(const Presenter *) const Glib::ustring ConsoleApplicationEngine::resolveCurrentConfig() const { - return safeMapFind(conplat, _env->getPlatform())->second; + return safeMapLookup(conplat, _env->getPlatform()); } void diff --git a/project2/json/couchSession.cpp b/project2/json/couchSession.cpp index 35650f2..fbe38f8 100644 --- a/project2/json/couchSession.cpp +++ b/project2/json/couchSession.cpp @@ -22,7 +22,7 @@ class CouchSessionContainer : public SessionContainer { virtual SessionPtr getSession(const UUID & uuid) const { try { json::Object obj = getSessionFromServer(uuid); - if (boost::get(*safeMapFind(obj, ExpiryKey)->second) > time(NULL)) { + if (boost::get(*safeMapLookup(obj, ExpiryKey)) > time(NULL)) { SessionPtr s = new Session(uuid); BOOST_FOREACH(const json::Object::value_type & v, obj) { s->SetValue(v.first, boost::apply_visitor(JsonToProject2(), *v.second)); @@ -162,10 +162,10 @@ class CustomCouchSessionLoader : public SessionContainerLoaderImplsetopt(CURLOPT_URL, (b + "_temp_view").c_str()); c->performRead(boost::bind(CouchSessionContainer::append, &msg, _1, _2)); json::Object o = json::parseObject(msg); - BOOST_FOREACH(const json::Array::value_type & v, boost::get(*safeMapFind(o, "rows")->second)) { + BOOST_FOREACH(const json::Array::value_type & v, boost::get(*safeMapLookup(o, "rows"))) { json::Object rec = boost::get(*v); - UUID u = boost::get(*safeMapFind(rec, "id")->second).raw(); - Glib::ustring & rev = boost::get(*safeMapFind(rec, "value")->second); + UUID u = boost::get(*safeMapLookup(rec, "id")).raw(); + Glib::ustring & rev = boost::get(*safeMapLookup(rec, "value")); deleteSession(u, rev); } return; diff --git a/project2/xml/xmlDocumentCache.cpp b/project2/xml/xmlDocumentCache.cpp index 9941336..696b2e5 100644 --- a/project2/xml/xmlDocumentCache.cpp +++ b/project2/xml/xmlDocumentCache.cpp @@ -83,7 +83,7 @@ XmlDocumentCache::getDocument(const Glib::ustring & url, const char * encoding) cbf.perform(); queued.clear(); } - return safeMapFind(documents, url)->second().get(); + return safeMapLookup(documents, url)().get(); } void diff --git a/project2/xml/xpathRows.cpp b/project2/xml/xpathRows.cpp index 7dc9c2b..e65104d 100644 --- a/project2/xml/xpathRows.cpp +++ b/project2/xml/xpathRows.cpp @@ -64,7 +64,7 @@ XPathRows::newCurl() const void XPathRows::execute(const Glib::ustring & filter, const RowProcessor * rp) const { - FilterViewPtr fv = safeMapFind(fvs, filter)->second; + FilterViewPtr fv = safeMapLookup(fvs, filter); typedef boost::shared_ptr xmlXPathObjectSPtr; typedef boost::shared_ptr xmlXPathContextSPtr; -- cgit v1.2.3