From 7bf0b5d013b88b0408031e2d6594357e71c8138f Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 18 Jul 2012 20:49:21 +0300 Subject: [PATCH] Replace DependencyCache with a more generic cache --- source/cache.cpp | 144 +++++++++++++++++++++++++++++++++++++ source/cache.h | 66 +++++++++++++++++ source/csourcefile.cpp | 9 ++- source/dependencycache.cpp | 70 ------------------ source/dependencycache.h | 39 ---------- source/sourcepackage.cpp | 6 +- source/sourcepackage.h | 6 +- 7 files changed, 220 insertions(+), 120 deletions(-) create mode 100644 source/cache.cpp create mode 100644 source/cache.h delete mode 100644 source/dependencycache.cpp delete mode 100644 source/dependencycache.h diff --git a/source/cache.cpp b/source/cache.cpp new file mode 100644 index 0000000..70f4120 --- /dev/null +++ b/source/cache.cpp @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include +#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 index 0000000..86a5f47 --- /dev/null +++ b/source/cache.h @@ -0,0 +1,66 @@ +#ifndef CACHE_H_ +#define CACHE_H_ + +#include +#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 ValueList; +private: + typedef std::pair Key; + typedef std::map 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 diff --git a/source/csourcefile.cpp b/source/csourcefile.cpp index 5628e04..5531287 100644 --- a/source/csourcefile.cpp +++ b/source/csourcefile.cpp @@ -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(mtimeget_build_info().incpath; diff --git a/source/dependencycache.cpp b/source/dependencycache.cpp deleted file mode 100644 index a4211a3..0000000 --- a/source/dependencycache.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include -#include -#include -#include -#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 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 index 4160cec..0000000 --- a/source/dependencycache.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef DEPENDENCYCACHE_H_ -#define DEPENDENCYCACHE_H_ - -#include -#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 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 diff --git a/source/sourcepackage.cpp b/source/sourcepackage.cpp index 3b9f7f0..22330b2 100644 --- a/source/sourcepackage.cpp +++ b/source/sourcepackage.cpp @@ -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(); } diff --git a/source/sourcepackage.h b/source/sourcepackage.h index b8d1909..97c9b32 100644 --- a/source/sourcepackage.h +++ b/source/sourcepackage.h @@ -4,10 +4,10 @@ #include #include #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(); -- 2.45.2