summaryrefslogtreecommitdiff
path: root/project2/xmlMemCache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'project2/xmlMemCache.cpp')
-rw-r--r--project2/xmlMemCache.cpp120
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);
+