From b2e6fcf7031cfaf995c65820d14d4aa390daf9fb Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Wed, 1 Jan 2014 20:31:34 -0800 Subject: Remove dead entries in .ninja_log and .ninja_deps while recompacting. For .ninja_deps, remove objects that have no in-edges or whose in-edges do not have a "deps" attribute. (This matches the behaviour of `-t deps`). BuildLog doesn't know about state, so let its recompact method take delegate that decides is a path is life or not, and implement it in NinjaMain. --- src/build_log.cc | 15 ++++++++++++--- src/build_log.h | 8 ++++++-- src/deps_log.cc | 7 +++++++ src/ninja.cc | 11 ++++++++--- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/build_log.cc b/src/build_log.cc index b92a06f..825a8f5 100644 --- a/src/build_log.cc +++ b/src/build_log.cc @@ -108,9 +108,9 @@ BuildLog::~BuildLog() { Close(); } -bool BuildLog::OpenForWrite(const string& path, string* err) { +bool BuildLog::OpenForWrite(const string& path, IsDead* is_dead, string* err) { if (needs_recompaction_) { - if (!Recompact(path, err)) + if (!Recompact(path, is_dead, err)) return false; } @@ -350,7 +350,7 @@ bool BuildLog::WriteEntry(FILE* f, const LogEntry& entry) { entry.output.c_str(), entry.command_hash) > 0; } -bool BuildLog::Recompact(const string& path, string* err) { +bool BuildLog::Recompact(const string& path, IsDead* is_dead, string* err) { METRIC_RECORD(".ninja_log recompact"); printf("Recompacting log...\n"); @@ -368,7 +368,13 @@ bool BuildLog::Recompact(const string& path, string* err) { return false; } + vector dead_outputs; for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) { + if (is_dead->IsPathDead(i->first)) { + dead_outputs.push_back(i->first); + continue; + } + if (!WriteEntry(f, *i->second)) { *err = strerror(errno); fclose(f); @@ -376,6 +382,9 @@ bool BuildLog::Recompact(const string& path, string* err) { } } + for (size_t i = 0; i < dead_outputs.size(); ++i) + entries_.erase(dead_outputs[i]); + fclose(f); if (unlink(path.c_str()) < 0) { *err = strerror(errno); diff --git a/src/build_log.h b/src/build_log.h index eeac5b3..bb474fc 100644 --- a/src/build_log.h +++ b/src/build_log.h @@ -25,6 +25,10 @@ using namespace std; struct Edge; +struct IsDead { + virtual bool IsPathDead(StringPiece s) = 0; +}; + /// Store a log of every command ran for every build. /// It has a few uses: /// @@ -36,7 +40,7 @@ struct BuildLog { BuildLog(); ~BuildLog(); - bool OpenForWrite(const string& path, string* err); + bool OpenForWrite(const string& path, IsDead* is_dead, string* err); // XXX bool RecordCommand(Edge* edge, int start_time, int end_time, TimeStamp restat_mtime = 0); void Close(); @@ -72,7 +76,7 @@ struct BuildLog { bool WriteEntry(FILE* f, const LogEntry& entry); /// Rewrite the known log entries, throwing away old data. - bool Recompact(const string& path, string* err); + bool Recompact(const string& path, IsDead* is_dead, string* err); // XXX typedef ExternalStringHashMap::Type Entries; const Entries& entries() const { return entries_; } diff --git a/src/deps_log.cc b/src/deps_log.cc index 4f1214a..0a3f7e5 100644 --- a/src/deps_log.cc +++ b/src/deps_log.cc @@ -325,6 +325,13 @@ bool DepsLog::Recompact(const string& path, string* err) { Deps* deps = deps_[old_id]; if (!deps) continue; // If nodes_[old_id] is a leaf, it has no deps. + Node* n = nodes_[old_id]; + Edge* e = n->in_edge(); + // FIXME: move this condition to a helper: (also used in src/ninja.cc) + if (!e || e->GetBinding("deps").empty()) { + continue; + } + if (!new_log.RecordDeps(nodes_[old_id], deps->mtime, deps->node_count, deps->nodes)) { new_log.Close(); diff --git a/src/ninja.cc b/src/ninja.cc index a313ecb..298d993 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -68,7 +68,7 @@ struct Options { /// The Ninja main() loads up a series of data structures; various tools need /// to poke into these, so store them as fields on an object. -struct NinjaMain { +struct NinjaMain : public IsDead { NinjaMain(const char* ninja_command, const BuildConfig& config) : ninja_command_(ninja_command), config_(config) {} @@ -137,6 +137,11 @@ struct NinjaMain { /// Dump the output requested by '-d stats'. void DumpMetrics(); + + virtual bool IsPathDead(StringPiece s) { + Node* n = state_.LookupNode(s); + return !n || !n->in_edge(); + } }; /// Subtools, accessible via "-t foo". @@ -789,14 +794,14 @@ bool NinjaMain::OpenBuildLog(bool recompact_only) { } if (recompact_only) { - bool success = build_log_.Recompact(log_path, &err); + bool success = build_log_.Recompact(log_path, this, &err); if (!success) Error("failed recompaction: %s", err.c_str()); return success; } if (!config_.dry_run) { - if (!build_log_.OpenForWrite(log_path, &err)) { + if (!build_log_.OpenForWrite(log_path, this, &err)) { Error("opening build log: %s", err.c_str()); return false; } -- cgit v0.12