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
|
#include <pch.hpp>
#include <scriptLoader.h>
#include "xmlDocumentCache.h"
#include <string.h>
#include <logger.h>
#include <libxml/HTMLparser.h>
#include <boost/bind.hpp>
#include <net.h>
#include "exceptions.h"
#include "curlHelper.h"
#include "safeMapFind.h"
XmlDocumentCache::Documents XmlDocumentCache::documents;
XmlDocumentCache::Queued XmlDocumentCache::queued;
AdHoc::Net::CurlMultiHandle XmlDocumentCache::cbf;
SimpleMessageException(XmlParseError);
SimpleMessageException(DownloadFailed);
template <class Exception>
static XmlDocumentCache::DocumentPtr helperThrow(const std::string & msg) {
throw Exception(msg);
}
static XmlDocumentCache::DocumentPtr helperReturnDocument(XmlDocumentCache::DomParserPtr dp) {
return dp->get_document();
}
XmlDocumentCache::DocumentPtr
XmlDocumentCache::getDocument(const Glib::ustring & url, const char * encoding, ExecContext * ec) const
{
Documents::const_iterator i = documents.find(url);
if (i == documents.end()) {
queue(url, encoding, ec);
cbf.performAll();
queued.clear();
}
return AdHoc::safeMapLookup<DownloadFailed>(documents, url)();
}
void
XmlDocumentCache::queue(const Glib::ustring & url, const char *, ExecContext *) const
{
if (queued.find(url) == queued.end()) {
cbf.addCurl(url, [url](std::istream & strm) {
try {
DomParserPtr doc = DomParserPtr(new xmlpp::DomParser());
doc->parse_stream(strm);
XmlDocumentCache::documents.insert(XmlDocumentCache::Documents::value_type(url,
boost::bind(helperReturnDocument, doc)));
}
catch (const AdHoc::Net::CurlException & error) {
Logger()->messagebf(LOG_DEBUG, "Download of '%s' failed with error '%s'", url, error.message);
XmlDocumentCache::documents.insert(XmlDocumentCache::Documents::value_type(url,
boost::bind(helperThrow<DownloadFailed>, error.message)));
}
})->setopt(CURLOPT_ENCODING, "deflate, gzip");
queued.insert(url);
}
}
class XmlDocumentCacheClearer : public LifeCycle {
public:
typedef bool KeyType;
void onIteration() override
{
Logger()->messagef(LOG_DEBUG, "%s: Clearing XML document cache", __PRETTY_FUNCTION__);
XmlDocumentCache::documents.clear();
Logger()->messagef(LOG_DEBUG, "%s: Cleared XML document cache", __PRETTY_FUNCTION__);
}
};
NAMEDPLUGIN("XmlDocumentCacheClearer", XmlDocumentCacheClearer, LifeCycle);
|