summaryrefslogtreecommitdiff
path: root/project2/xmlCache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'project2/xmlCache.cpp')
-rw-r--r--project2/xmlCache.cpp143
1 files changed, 143 insertions, 0 deletions
diff --git a/project2/xmlCache.cpp b/project2/xmlCache.cpp
new file mode 100644
index 0000000..0a166e8
--- /dev/null
+++ b/project2/xmlCache.cpp
@@ -0,0 +1,143 @@
+#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 <boost/filesystem/path.hpp>
+#include <boost/filesystem/convenience.hpp>
+#include <libxml++/nodes/textnode.h>
+#include <libxml++/document.h>
+
+class XmlCache : public Cache {
+ public:
+ XmlCache(const xmlpp::Element * p) :
+ Cache(p)
+ {
+ }
+
+ void loadComplete(const CommonObjects*)
+ {
+ }
+
+ RowSetCPtr getCachedRowSet(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const
+ {
+ boost::filesystem::path cache = getCacheFile(n, f, ps);
+ struct stat st;
+ if (stat(cache.string().c_str(), &st) == 0) {
+ if (st.st_mtime < time(NULL) - CacheLife) {
+ boost::filesystem::remove(cache);
+ return NULL;
+ }
+ return new XmlRawRows(cache.string());
+ }
+ return NULL;
+ }
+
+ PresenterPtr openFor(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps)
+ {
+ target = getCacheFile(n, f, ps);
+ writeTo = new XmlPresenter(n, Glib::ustring(), Glib::ustring());
+ return writeTo;
+ }
+
+ void close()
+ {
+ try {
+ boost::filesystem::create_directories(target.parent_path());
+ const xmlpp::Document * d = *writeTo;
+ const_cast<xmlpp::Document *>(d)->write_to_file(target.string());
+ writeTo.reset();
+ }
+ catch (...) {
+ Logger()->messagef(LOG_WARNING, "Failed to save cache (%s)", target.string().c_str());
+ }
+ }
+
+ private:
+ boost::filesystem::path getCacheFile(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const
+ {
+ boost::filesystem::path cache = Store / n.raw() / f.raw();
+ BOOST_FOREACH(const IHaveParameters::Parameters::value_type & p, ps->allParameters()) {
+ std::string v = p.second->value();
+ cache /= p.first.raw();
+ cache /= v;
+ }
+ cache /= FileName;
+ return cache;
+ }
+
+ XmlPresenterPtr writeTo;
+ boost::filesystem::path target;
+
+ friend class CustomXmlCacheLoader;
+ static boost::filesystem::path Store;
+ static std::string FileName;
+ static time_t CacheLife;
+};
+
+boost::filesystem::path XmlCache::Store;
+std::string XmlCache::FileName;
+time_t XmlCache::CacheLife;
+
+namespace po = boost::program_options;
+class CustomXmlCacheLoader : public ElementLoaderImpl<XmlCache> {
+ public:
+ CustomXmlCacheLoader() :
+ opts("XML Cache options")
+ {
+ opts.add_options()
+ ("cache.xml.store", po::value(&XmlCache::Store)->default_value("/tmp/project2.cache"),
+ "The root folder of the cache storage area")
+ ("cache.xml.filename", po::value(&XmlCache::FileName)->default_value("cache.xml"),
+ "The filename to store the data in")
+ ("cache.xml.life", po::value(&XmlCache::CacheLife)->default_value(3600),
+ "The age of cache entries after which they are removed (seconds)")
+ ;
+ }
+
+ po::options_description * options()
+ {
+ return &opts;
+ }
+
+ void onIdle()
+ {
+ emptyDir(XmlCache::Store);
+ }
+
+ bool emptyDir(const boost::filesystem::path & dir)
+ {
+ bool files = false;
+ boost::filesystem::directory_iterator end;
+ for (boost::filesystem::directory_iterator itr(dir); itr != end; ++itr) {
+ struct stat st;
+ stat(itr->path().string().c_str(), &st);
+ if (S_ISDIR(st.st_mode)) {
+ if (emptyDir(*itr)) {
+ files = true;
+ }
+ else {
+ boost::filesystem::remove(*itr);
+ }
+ }
+ else {
+ if (st.st_mtime > time(NULL) - XmlCache::CacheLife) {
+ files = true;
+ }
+ else {
+ boost::filesystem::remove(*itr);
+ }
+ }
+ }
+ return files;
+ }
+
+ private:
+ po::options_description opts;
+};
+DECLARE_CUSTOM_LOADER("xmlcache", CustomXmlCacheLoader);
+