recompute dirtiness from stats

This commit is contained in:
Evan Martin 2010-10-18 12:24:01 -07:00
parent 72204eaa2c
commit 5ce0da16ca

43
ninja.h
View File

@ -13,10 +13,11 @@ struct Node;
struct FileStat { struct FileStat {
FileStat(const string& path) : path_(path), mtime_(0), node_(NULL) {} FileStat(const string& path) : path_(path), mtime_(0), node_(NULL) {}
void Touch(int mtime); void Touch(int mtime);
void Stat(); // Return true if the mtime changed.
bool Stat();
string path_; string path_;
int mtime_; time_t mtime_;
Node* node_; Node* node_;
}; };
@ -103,6 +104,7 @@ struct Edge {
Edge() : rule_(NULL) {} Edge() : rule_(NULL) {}
void MarkDirty(Node* node); void MarkDirty(Node* node);
void RecomputeDirty();
string EvaluateCommand(); // XXX move to env, take env ptr string EvaluateCommand(); // XXX move to env, take env ptr
Rule* rule_; Rule* rule_;
@ -121,16 +123,22 @@ void FileStat::Touch(int mtime) {
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
void FileStat::Stat() { bool FileStat::Stat() {
struct stat st; struct stat st;
if (stat(path_.c_str(), &st) < 0) { if (stat(path_.c_str(), &st) < 0) {
if (errno == ENOENT) { if (errno == ENOENT) {
mtime_ = 0; st.st_mtime = 0;
} else { } else {
fprintf(stderr, "stat(%s): %s\n", path_.c_str(), strerror(errno)); fprintf(stderr, "stat(%s): %s\n", path_.c_str(), strerror(errno));
return false;
} }
} }
if (st.st_mtime == mtime_)
return false;
mtime_ = st.st_mtime; mtime_ = st.st_mtime;
return true;
} }
void Node::MarkDirty() { void Node::MarkDirty() {
@ -143,6 +151,20 @@ void Node::MarkDirty() {
(*i)->MarkDirty(this); (*i)->MarkDirty(this);
} }
void Edge::RecomputeDirty() {
time_t min_mtime = -1;
for (vector<Node*>::iterator i = outputs_.begin(); i != outputs_.end(); ++i) {
min_mtime = min(min_mtime, (*i)->file_->mtime_);
}
for (vector<Node*>::iterator i = inputs_.begin(); i != inputs_.end(); ++i) {
if ((*i)->file_->mtime_ > min_mtime) {
MarkDirty(*i);
break;
}
}
}
void Edge::MarkDirty(Node* node) { void Edge::MarkDirty(Node* node) {
vector<Node*>::iterator i = find(inputs_.begin(), inputs_.end(), node); vector<Node*>::iterator i = find(inputs_.begin(), inputs_.end(), node);
if (i == inputs_.end()) if (i == inputs_.end())
@ -202,8 +224,21 @@ void StatCache::Dump() {
} }
void StatCache::Reload() { void StatCache::Reload() {
set<Edge*> leaf_edges;
for (Paths::iterator i = paths_.begin(); i != paths_.end(); ++i) { for (Paths::iterator i = paths_.begin(); i != paths_.end(); ++i) {
i->second->Stat(); i->second->Stat();
Node* node = i->second->node_;
node->dirty_ = false;
if (!node->in_edge_) {
for (vector<Edge*>::iterator j = node->out_edges_.begin();
j != node->out_edges_.end(); ++j) {
leaf_edges.insert(*j);
}
}
}
for (set<Edge*>::iterator i = leaf_edges.begin(); i != leaf_edges.end(); ++i) {
(*i)->RecomputeDirty();
} }
} }