summaryrefslogtreecommitdiff
path: root/project2/xml/xmlMemCache.cpp
blob: 9fe0a6f4248103e0d37c2a4f2149b646dbdb2715 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <pch.hpp>
#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);