diff options
Diffstat (limited to 'project2/xmlCache.cpp')
-rw-r--r-- | project2/xmlCache.cpp | 143 |
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); + |