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);
|