summaryrefslogtreecommitdiff
path: root/src/ModuleCache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/ModuleCache.cc')
-rw-r--r--src/ModuleCache.cc105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/ModuleCache.cc b/src/ModuleCache.cc
new file mode 100644
index 0000000..e974a03
--- /dev/null
+++ b/src/ModuleCache.cc
@@ -0,0 +1,105 @@
+#include "ModuleCache.h"
+#include "module.h"
+#include "printutils.h"
+#include "openscad.h"
+
+#include "boosty.h"
+#include <boost/format.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/foreach.hpp>
+
+#include <stdio.h>
+#include <fstream>
+#include <sstream>
+#include <time.h>
+#include <sys/stat.h>
+
+/*!
+ FIXME: Implement an LRU scheme to avoid having an ever-growing module cache
+*/
+
+ModuleCache *ModuleCache::inst = NULL;
+
+static bool is_modified(const std::string &filename, const time_t &mtime)
+{
+ struct stat st;
+ memset(&st, 0, sizeof(struct stat));
+ stat(filename.c_str(), &st);
+ return (st.st_mtime > mtime);
+}
+
+Module *ModuleCache::evaluate(const std::string &filename)
+{
+ Module *lib_mod = NULL;
+
+ // Create cache ID
+ struct stat st;
+ memset(&st, 0, sizeof(struct stat));
+ stat(filename.c_str(), &st);
+
+ std::string cache_id = str(boost::format("%x.%x") % st.st_mtime % st.st_size);
+
+ // Lookup in cache
+ if (this->entries.find(filename) != this->entries.end() &&
+ this->entries[filename].cache_id == cache_id) {
+#ifdef DEBUG
+ PRINTB("Using cached library: %s (%s)", filename % cache_id);
+#endif
+ lib_mod = &(*this->entries[filename].module);
+
+ BOOST_FOREACH(const Module::IncludeContainer::value_type &item, lib_mod->includes) {
+ if (is_modified(item.first, item.second)) {
+ lib_mod = NULL;
+ break;
+ }
+ }
+ }
+
+ // If cache lookup failed (non-existing or old timestamp), compile module
+ if (!lib_mod) {
+#ifdef DEBUG
+ if (this->entries.find(filename) != this->entries.end()) {
+ PRINTB("Recompiling cached library: %s (%s)", filename % cache_id);
+ }
+ else {
+ PRINTB("Compiling library '%s'.", filename);
+ }
+#endif
+
+ std::ifstream ifs(filename.c_str());
+ if (!ifs.is_open()) {
+ PRINTB("WARNING: Can't open library file '%s'\n", filename);
+ return NULL;
+ }
+ std::string text((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
+
+ print_messages_push();
+
+ cache_entry e = { NULL, cache_id };
+ if (this->entries.find(filename) != this->entries.end()) {
+ delete this->entries[filename].module;
+ }
+ this->entries[filename] = e;
+
+ std::string pathname = boosty::stringy(fs::path(filename).parent_path());
+ lib_mod = dynamic_cast<Module*>(parse(text.c_str(), pathname.c_str(), 0));
+
+ if (lib_mod) {
+ this->entries[filename].module = lib_mod;
+ } else {
+ this->entries.erase(filename);
+ }
+
+ print_messages_pop();
+ }
+
+ if (lib_mod) lib_mod->handleDependencies();
+
+ return lib_mod;
+}
+
+void ModuleCache::clear()
+{
+ this->entries.clear();
+}
+
contact: Jan Huwald // Impressum