]> git.tdb.fi Git - builder.git/commitdiff
Replace DependencyCache with a more generic cache
authorMikko Rasa <tdb@tdb.fi>
Wed, 18 Jul 2012 17:49:21 +0000 (20:49 +0300)
committerMikko Rasa <tdb@tdb.fi>
Wed, 18 Jul 2012 17:49:21 +0000 (20:49 +0300)
source/cache.cpp [new file with mode: 0644]
source/cache.h [new file with mode: 0644]
source/csourcefile.cpp
source/dependencycache.cpp [deleted file]
source/dependencycache.h [deleted file]
source/sourcepackage.cpp
source/sourcepackage.h

diff --git a/source/cache.cpp b/source/cache.cpp
new file mode 100644 (file)
index 0000000..70f4120
--- /dev/null
@@ -0,0 +1,144 @@
+#include <msp/core/maputils.h>
+#include <msp/fs/stat.h>
+#include <msp/io/file.h>
+#include <msp/io/print.h>
+#include <msp/strings/utils.h>
+#include "builder.h"
+#include "cache.h"
+#include "sourcepackage.h"
+#include "target.h"
+
+using namespace std;
+using namespace Msp;
+
+namespace {
+
+unsigned read_count(IO::Base &in)
+{
+       unsigned char head = in.get();
+       if((head&0xC0)==0xC0)
+       {
+               unsigned char tail = in.get();
+               return (head&0x3F)<<8 | tail;
+       }
+       else
+               return head;
+}
+
+string read_string(IO::Base &in)
+{
+       unsigned len = read_count(in);
+       char buf[0x4000];
+       len = in.read(buf, len);
+       return string(buf, len);
+}
+
+void write_count(IO::Base &out, unsigned count)
+{
+       if(count<0xC0)
+               out.put(count);
+       else if(count<0x4000)
+       {
+               out.put(0xC0 | (count>>8));
+               out.put(count&0xFF);
+       }
+       else
+               throw invalid_argument("write_count");
+}
+
+void write_string(IO::Base &out, const string &str)
+{
+       write_count(out, str.size());
+       out.write(str);
+}
+
+}
+
+
+Cache::Cache(SourcePackage &p):
+       package(p),
+       filename(package.get_temp_dir()/"../cache"),
+       changed(false)
+{ }
+
+void Cache::set_value(const Target *tgt, const string &k, const string &v)
+{
+       ValueList vl;
+       vl.push_back(v);
+       set_values(tgt, k, vl);
+}
+
+void Cache::append_value(const Target *tgt, const string &k, const string &v)
+{
+       Key key(tgt->get_name(), k);
+       DataMap::iterator i = data.find(key);
+       if(i==data.end())
+               i = data.insert(DataMap::value_type(key, ValueList())).first;
+       i->second.push_back(v);
+       changed = true;
+}
+
+void Cache::set_values(const Target *tgt, const string &k, const ValueList &v)
+{
+       data[Key(tgt->get_name(), k)] = v;
+       changed = true;
+}
+
+const string &Cache::get_value(const Target *tgt, const string &k)
+{
+       const ValueList &values = get_values(tgt, k);
+       if(values.empty())
+               throw logic_error("values.empty()");
+       return values.front();
+}
+
+const Cache::ValueList &Cache::get_values(const Target *tgt, const string &k)
+{
+       return get_item(data, Key(tgt->get_name(), k));
+}
+
+bool Cache::has_key(const Target *tgt, const string &k)
+{
+       return data.count(Key(tgt->get_name(), k));
+}
+
+void Cache::load()
+{
+       if(FS::Stat st = FS::stat(filename))
+       {
+               package.get_builder().get_logger().log("files", format("Reading %s", filename));
+               IO::BufferedFile in(filename.str());
+
+               while(!in.eof())
+               {
+                       Key key;
+                       key.first = read_string(in);
+                       key.second = read_string(in);
+                       if(key.first.empty() || key.second.empty())
+                               break;
+                       ValueList &values = data[key];
+                       for(unsigned count = read_count(in); count; --count)
+                               values.push_back(read_string(in));
+               }
+
+               mtime = st.get_modify_time();
+       }
+}
+
+void Cache::save() const
+{
+       if(data.empty() || !changed)
+               return;
+
+       package.get_builder().get_logger().log("files", format("Writing %s", filename));
+       IO::BufferedFile out(filename.str(), IO::M_WRITE);
+
+       for(DataMap::const_iterator i=data.begin(); i!=data.end(); ++i)
+       {
+               write_string(out, i->first.first);
+               write_string(out, i->first.second);
+               write_count(out, i->second.size());
+               for(ValueList::const_iterator j=i->second.begin(); j!=i->second.end(); ++j)
+                       write_string(out, *j);
+       }
+}
diff --git a/source/cache.h b/source/cache.h
new file mode 100644 (file)
index 0000000..86a5f47
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef CACHE_H_
+#define CACHE_H_
+
+#include <msp/time/timestamp.h>
+#include "misc.h"
+
+class SourcePackage;
+class Target;
+
+/**
+Stores data between build runs.  This can be used to avoid scanning files again
+every time builder is run, or to detect outside changes.
+
+Data is stored as lists of strings and keyed to target and an arbitrary
+identifier.  Any kind of strings can be stored, even ones that contain
+unprintable characters or nuls.
+*/
+class Cache
+{
+public:
+       typedef std::list<std::string> ValueList;
+private:
+       typedef std::pair<std::string, std::string> Key;
+       typedef std::map<Key, ValueList> DataMap;
+
+       SourcePackage &package;
+       Msp::FS::Path filename;
+       DataMap data;
+       Msp::Time::TimeStamp mtime;
+       bool changed;
+
+public:
+       Cache(SourcePackage &p);
+
+       /// Sets a key to a single value, replacing any existing values.
+       void set_value(const Target *, const std::string &, const std::string &);
+
+       /// Appends a value to a key.  If the key does not exist, it is created.
+       void append_value(const Target *, const std::string &, const std::string &);
+
+       /// Sets a key to a list of values, replacing any existing values.
+       void set_values(const Target *, const std::string &, const ValueList &);
+
+       /** Returns the first value from a key.  The key must exist and be
+       non-empty. */
+       const std::string &get_value(const Target *, const std::string &);
+
+       /// Returns the values from a key.  The key must exist.
+       const ValueList &get_values(const Target *, const std::string &);
+
+       /// Indicates whether a key exists.
+       bool has_key(const Target *, const std::string &);
+
+       /// Returns the last modification timestamp of the cache.
+       const Msp::Time::TimeStamp &get_mtime() const { return mtime; }
+
+       /** Loads the cache file and sets the last modification timestamp
+       accordingly. */
+       void load();
+
+       /** Saves the cache.  Does nothing if there is no data to save or nothing
+       has changed. */
+       void save() const;
+};
+
+#endif
index 5628e04adb0aed6310b015c2d0c228cac8c40f10..553128743d8651e50cd0195f4c868727e312c2c3 100644 (file)
@@ -28,11 +28,10 @@ void CSourceFile::find_dependencies()
                return;
 
        const SourcePackage &spkg = component->get_package();
-       string deps_key = FS::relative(path, spkg.get_source_directory()).str();
 
-       DependencyCache &deps_cache = spkg.get_dependency_cache();
-       if(mtime<deps_cache.get_mtime() && deps_cache.has_deps(deps_key))
-               includes = deps_cache.get_deps(deps_key);
+       Cache &cache = spkg.get_cache();
+       if(mtime<cache.get_mtime() && cache.has_key(this, "includes"))
+               includes = cache.get_values(this, "includes");
        else
        {
                IO::BufferedFile in(path.str());
@@ -46,7 +45,7 @@ void CSourceFile::find_dependencies()
                        if(RegMatch match = r_include.match(line))
                                includes.push_back(match[1].str);
 
-               deps_cache.set_deps(deps_key, includes);
+               cache.set_values(this, "includes", includes);
        }
 
        const BuildInfo::PathList &incpath = component->get_build_info().incpath;
diff --git a/source/dependencycache.cpp b/source/dependencycache.cpp
deleted file mode 100644 (file)
index a4211a3..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#include <msp/core/maputils.h>
-#include <msp/fs/stat.h>
-#include <msp/io/file.h>
-#include <msp/io/print.h>
-#include <msp/strings/utils.h>
-#include "builder.h"
-#include "dependencycache.h"
-#include "sourcepackage.h"
-
-using namespace std;
-using namespace Msp;
-
-DependencyCache::DependencyCache(SourcePackage &p):
-       package(p),
-       changed(false)
-{ }
-
-void DependencyCache::set_deps(const string &tgt, const StringList &d)
-{
-       deps[tgt] = d;
-       changed = true;
-}
-
-bool DependencyCache::has_deps(const string &tgt) const
-{
-       return deps.count(tgt);
-}
-
-const StringList &DependencyCache::get_deps(const string &tgt) const
-{
-       return get_item(deps, tgt);
-}
-
-void DependencyCache::save() const
-{
-       if(deps.empty() || !changed)
-               return;
-
-       FS::Path fn = package.get_source_directory()/".deps";
-       package.get_builder().get_logger().log("files", format("Writing %s", fn));
-       IO::BufferedFile out(fn.str(), IO::M_WRITE);
-
-       for(DepsMap::const_iterator i=deps.begin(); i!=deps.end(); ++i)
-       {
-               IO::print(out, i->first);
-               for(StringList::const_iterator j=i->second.begin(); j!=i->second.end(); ++j)
-                       IO::print(out, "|%s", *j);
-               IO::print(out, "\n");
-       }
-}
-
-void DependencyCache::load()
-{
-       FS::Path fn = package.get_source_directory()/".deps";
-
-       if(FS::Stat st = FS::stat(fn))
-       {
-               package.get_builder().get_logger().log("files", format("Reading %s", fn));
-               IO::BufferedFile in(fn.str());
-
-               string line;
-               while(in.getline(line))
-               {
-                       vector<string> parts = split(line, '|');
-                       deps[parts[0]] = StringList(parts.begin()+1, parts.end());
-               }
-
-               mtime = st.get_modify_time();
-       }
-}
diff --git a/source/dependencycache.h b/source/dependencycache.h
deleted file mode 100644 (file)
index 4160cec..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef DEPENDENCYCACHE_H_
-#define DEPENDENCYCACHE_H_
-
-#include <msp/time/timestamp.h>
-#include "misc.h"
-
-class Package;
-
-/**
-Stores dependencies to avoid expensive filesystem operations during DAG
-building phase.  The dependencies are stored in a map with target name as key
-and a list of strings as value.  The targets are free to store whatever they
-want here.
-*/
-class DependencyCache
-{
-private:
-       typedef std::map<std::string, StringList> DepsMap;
-
-       SourcePackage &package;
-       DepsMap deps;
-       Msp::Time::TimeStamp mtime;
-       bool changed;
-
-public:
-       DependencyCache(SourcePackage &p);
-
-       void set_deps(const std::string &tgt, const StringList &d);
-       bool has_deps(const std::string &tgt) const;
-       const StringList &get_deps(const std::string &tgt) const;
-       const Msp::Time::TimeStamp &get_mtime() const { return mtime; }
-       void load();
-
-       /** Saves the depencency cache.  Does nothing if the cache is empty or
-       nothing has changed. */
-       void save() const;
-};
-
-#endif
index 3b9f7f0ebebafcbd58f391fe39fe76cec57fa277..22330b2970dd4184db97d783a6646be4bc30da4f 100644 (file)
@@ -27,7 +27,7 @@ SourcePackage::SourcePackage(Builder &b, const string &n, const FS::Path &f):
        source_dir(FS::dirname(f)),
        build_type(0),
        config(*this),
-       deps_cache(*this)
+       cache(*this)
 {
        config.load();
 
@@ -107,7 +107,7 @@ void SourcePackage::create_build_info()
 
 void SourcePackage::create_targets()
 {
-       deps_cache.load();
+       cache.load();
 
        bool pc_needed = false;
        for(ComponentList::const_iterator i=components.begin(); i!=components.end(); ++i)
@@ -127,7 +127,7 @@ void SourcePackage::create_targets()
 void SourcePackage::save_caches()
 {
        config.save();
-       deps_cache.save();
+       cache.save();
 }
 
 
index b8d19090eed92aa5d653589d14296d50829442b8..97c9b32eb8ffa233ca980892d704a3c5ea1d8d6b 100644 (file)
@@ -4,10 +4,10 @@
 #include <stdexcept>
 #include <string>
 #include "buildinfo.h"
+#include "cache.h"
 #include "component.h"
 #include "condition.h"
 #include "config.h"
-#include "dependencycache.h"
 #include "feature.h"
 #include "package.h"
 
@@ -65,7 +65,7 @@ private:
        BuildInfo build_info;
        ComponentList components;
        Config config;
-       mutable DependencyCache deps_cache;
+       mutable Cache cache;
 
 public:
        SourcePackage(Builder &, const std::string &, const Msp::FS::Path &);
@@ -82,7 +82,7 @@ public:
        const BuildInfo &get_build_info() const { return build_info; }
        Builder &get_builder() const { return builder; }
 
-       DependencyCache &get_dependency_cache() const { return deps_cache; }
+       Cache &get_cache() const { return cache; }
 private:
        virtual void create_build_info();