diff options
Diffstat (limited to 'project2/xmlMemCache.cpp')
-rw-r--r-- | project2/xmlMemCache.cpp | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/project2/xmlMemCache.cpp b/project2/xmlMemCache.cpp new file mode 100644 index 0000000..af54eb5 --- /dev/null +++ b/project2/xmlMemCache.cpp @@ -0,0 +1,120 @@ +#include "cache.h" +#include "logger.h" +#include "xmlObjectLoader.h" +#include "iHaveParameters.h" +#include "xmlRawRows.h" +#include "xmlPresenter.h" +#include <sys/stat.h> +#include <boost/foreach.hpp> +#include <boost/program_options.hpp> +#include <libxml++/document.h> +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/member.hpp> +#include <boost/multi_index/ordered_index.hpp> + +class XmlMemCache : public Cache { + public: + class CacheEntry : public IntrusivePtrBase { + public: + std::vector<std::string> key; + time_t createdAt; + boost::shared_ptr<const xmlpp::Document> doc; + }; + typedef boost::intrusive_ptr<CacheEntry> CacheEntryPtr; + typedef boost::intrusive_ptr<const CacheEntry> CacheEntryCPtr; + + struct IndexByKey { }; + struct IndexByTime { }; + typedef boost::multi_index::multi_index_container< + boost::intrusive_ptr<const CacheEntry>, + boost::multi_index::indexed_by< + boost::multi_index::ordered_unique< + boost::multi_index::tag<IndexByKey>, BOOST_MULTI_INDEX_MEMBER(CacheEntry, const std::vector<std::string>, key)>, + boost::multi_index::ordered_non_unique< + boost::multi_index::tag<IndexByTime>, BOOST_MULTI_INDEX_MEMBER(CacheEntry, const time_t, createdAt)> + > > CacheStore; + + XmlMemCache(const xmlpp::Element * p) : + Cache(p) + { + } + + void loadComplete(const CommonObjects*) + { + } + + RowSetCPtr getCachedRowSet(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const + { + std::vector<std::string> key; + key.push_back(n); + key.push_back(f); + applyKeys(boost::bind(&std::vector<std::string>::push_back, &key, _2), ps); + CacheStore::index<IndexByKey>::type::const_iterator i = Store.get<IndexByKey>().find(key); + if (i == Store.get<IndexByKey>().end()) { + return NULL; + } + if ((*i)->createdAt < (time(NULL) - CacheLife)) { + Store.erase(i); + return NULL; + } + return new XmlMemRawRows((*i)->doc); + } + + PresenterPtr openFor(const Glib::ustring & n, const Glib::ustring &, const IHaveParameters *) + { + writeTo = new XmlPresenter(n, Glib::ustring(), Glib::ustring()); + return writeTo; + } + + void close(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) + { + CacheEntryPtr ce = new CacheEntry(); + ce->key.push_back(n); + ce->key.push_back(f); + applyKeys(boost::bind(&std::vector<std::string>::push_back, &ce->key, _2), ps); + time(&ce->createdAt); + ce->doc = *(const boost::shared_ptr<xmlpp::Document>*)(*writeTo); + Store.insert(ce); + } + + private: + XmlPresenterPtr writeTo; + + friend class CustomXmlMemCacheLoader; + static time_t CacheLife; + static CacheStore Store; +}; + +time_t XmlMemCache::CacheLife; +XmlMemCache::CacheStore XmlMemCache::Store; + +namespace po = boost::program_options; +class CustomXmlMemCacheLoader : public ElementLoaderImpl<XmlMemCache> { + public: + CustomXmlMemCacheLoader() : + opts("XML Memory Cache options") + { + opts.add_options() + ("cache.xmlmem.life", po::value(&XmlMemCache::CacheLife)->default_value(3600), + "The age of cache entries after which they are removed (seconds)") + ; + } + + po::options_description * options() + { + return &opts; + } + + void onIdle() + { + typedef XmlMemCache::CacheStore::index<XmlMemCache::IndexByTime>::type::iterator iter; + iter x = XmlMemCache::Store.get<XmlMemCache::IndexByTime>().begin(); + iter y = XmlMemCache::Store.get<XmlMemCache::IndexByTime>().upper_bound(time(NULL) - XmlMemCache::CacheLife); + XmlMemCache::Store.get<XmlMemCache::IndexByTime>().erase(x, y); + } + + private: + po::options_description opts; +}; +DECLARE_CUSTOM_LOADER("xmlmemcache", CustomXmlMemCacheLoader); + |