23 #elif defined(_MSC_VER) && (_MSC_VER < 1900) 24 typedef __int32 int32_t;
25 typedef unsigned __int32 uint32_t;
49 if (needs_recompaction_) {
50 if (!Recompact(path, err))
61 const vector<Node*>& nodes) {
62 return RecordDeps(node, mtime, nodes.size(),
63 nodes.empty() ? NULL : (
Node**)&nodes.front());
67 int node_count,
Node** nodes) {
69 bool made_change =
false;
77 for (
int i = 0; i < node_count; ++i) {
78 if (nodes[i]->
id() < 0) {
79 if (!RecordId(nodes[i]))
87 Deps* deps = GetDeps(node);
89 deps->
mtime != mtime ||
93 for (
int i = 0; i < node_count; ++i) {
94 if (deps->
nodes[i] != nodes[i]) {
107 unsigned size = 4 * (1 + 2 + node_count);
113 if (!OpenForWriteIfNeeded()) {
117 if (fwrite(&size, 4, 1, file_) < 1)
120 if (fwrite(&
id, 4, 1, file_) < 1)
122 uint32_t mtime_part =
static_cast<uint32_t
>(mtime & 0xffffffff);
123 if (fwrite(&mtime_part, 4, 1, file_) < 1)
125 mtime_part =
static_cast<uint32_t
>((mtime >> 32) & 0xffffffff);
126 if (fwrite(&mtime_part, 4, 1, file_) < 1)
128 for (
int i = 0; i < node_count; ++i) {
130 if (fwrite(&
id, 4, 1, file_) < 1)
133 if (fflush(file_) != 0)
137 Deps* deps =
new Deps(mtime, node_count);
138 for (
int i = 0; i < node_count; ++i)
139 deps->
nodes[i] = nodes[i];
140 UpdateDeps(node->
id(), deps);
146 OpenForWriteIfNeeded();
155 FILE* f = fopen(path.c_str(),
"rb");
159 *err = strerror(errno);
163 bool valid_header =
true;
165 if (!fgets(buf,
sizeof(buf), f) || fread(&version, 4, 1, f) < 1)
166 valid_header =
false;
174 *err =
"deps log version change; rebuilding";
176 *err =
"bad deps log signature or version; starting over";
178 unlink(path.c_str());
185 bool read_failed =
false;
186 int unique_dep_record_count = 0;
187 int total_dep_record_count = 0;
192 if (fread(&size, 4, 1, f) < 1) {
197 bool is_deps = (size >> 31) != 0;
198 size = size & 0x7FFFFFFF;
206 assert(size % 4 == 0);
207 int* deps_data =
reinterpret_cast<int*
>(buf);
208 int out_id = deps_data[0];
211 (
uint64_t)(
unsigned int)deps_data[1]);
213 int deps_count = (size / 4) - 3;
215 Deps* deps =
new Deps(mtime, deps_count);
216 for (
int i = 0; i < deps_count; ++i) {
217 assert(deps_data[i] < (
int)nodes_.size());
218 assert(nodes_[deps_data[i]]);
219 deps->
nodes[i] = nodes_[deps_data[i]];
222 total_dep_record_count++;
223 if (!UpdateDeps(out_id, deps))
224 ++unique_dep_record_count;
226 int path_size = size - 4;
227 assert(path_size > 0);
229 if (buf[path_size - 1] ==
'\0') --path_size;
230 if (buf[path_size - 1] ==
'\0') --path_size;
231 if (buf[path_size - 1] ==
'\0') --path_size;
244 unsigned checksum = *
reinterpret_cast<unsigned*
>(buf + size - 4);
245 int expected_id = ~checksum;
246 int id = nodes_.size();
247 if (
id != expected_id) {
252 assert(node->
id() < 0);
254 nodes_.push_back(node);
262 *err = strerror(ferror(f));
264 *err =
"premature end of file";
273 *err +=
"; recovering";
280 int kMinCompactionEntryCount = 1000;
281 int kCompactionRatio = 3;
282 if (total_dep_record_count > kMinCompactionEntryCount &&
283 total_dep_record_count > unique_dep_record_count * kCompactionRatio) {
284 needs_recompaction_ =
true;
293 if (node->
id() < 0 || node->
id() >= (int)deps_.size())
295 return deps_[node->
id()];
302 string temp_path = path +
".recompact";
306 unlink(temp_path.c_str());
309 if (!new_log.OpenForWrite(temp_path, err))
314 for (vector<Node*>::iterator i = nodes_.begin(); i != nodes_.end(); ++i)
318 for (
int old_id = 0; old_id < (int)deps_.size(); ++old_id) {
319 Deps* deps = deps_[old_id];
322 if (!IsDepsEntryLiveFor(nodes_[old_id]))
325 if (!new_log.RecordDeps(nodes_[old_id], deps->
mtime,
335 deps_.swap(new_log.deps_);
336 nodes_.swap(new_log.nodes_);
338 if (unlink(path.c_str()) < 0) {
339 *err = strerror(errno);
343 if (rename(temp_path.c_str(), path.c_str()) < 0) {
344 *err = strerror(errno);
362 if (out_id >= (
int)deps_.size())
363 deps_.resize(out_id + 1);
365 bool delete_old = deps_[out_id] != NULL;
367 delete deps_[out_id];
368 deps_[out_id] = deps;
373 int path_size = node->
path().size();
374 int padding = (4 - path_size % 4) % 4;
376 unsigned size = path_size + padding + 4;
382 if (!OpenForWriteIfNeeded()) {
385 if (fwrite(&size, 4, 1, file_) < 1)
387 if (fwrite(node->
path().data(), path_size, 1, file_) < 1) {
388 assert(!node->
path().empty());
391 if (padding && fwrite(
"\0\0", padding, 1, file_) < 1)
393 int id = nodes_.size();
394 unsigned checksum = ~(unsigned)
id;
395 if (fwrite(&checksum, 4, 1, file_) < 1)
397 if (fflush(file_) != 0)
401 nodes_.push_back(node);
407 if (file_path_.empty()) {
410 file_ = fopen(file_path_.c_str(),
"ab");
423 fseek(file_, 0, SEEK_END);
425 if (ftell(file_) == 0) {
433 if (fflush(file_) != 0) {
const int kCurrentVersion
const char kFileSignature[]
Node * GetNode(StringPiece path, uint64_t slash_bits)
bool OpenForWriteIfNeeded()
Should be called before using file_.
StringPiece represents a slice of a string whose memory is managed externally.
Information about a node in the dependency graph: the file, whether it's dirty, mtime, etc.
const unsigned kMaxRecordSize
LoadStatus Load(const std::string &path, State *state, std::string *err)
const std::string & path() const
bool Recompact(const std::string &path, std::string *err)
Rewrite the known log entries, throwing away old data.
void SetCloseOnExec(int fd)
Mark a file descriptor to not be inherited on exec()s.
As build commands run they can output extra dependency information (e.g.
bool RecordDeps(Node *node, TimeStamp mtime, const std::vector< Node *> &nodes)
Deps * GetDeps(Node *node)
bool RecordId(Node *node)
#define METRIC_RECORD(name)
The primary interface to metrics.
bool OpenForWrite(const std::string &path, std::string *err)
bool Truncate(const string &path, size_t size, string *err)
std::string GetBinding(const std::string &key) const
Returns the shell-escaped value of |key|.
Global state (file status) for a single run.
unsigned long long uint64_t
bool UpdateDeps(int out_id, Deps *deps)
bool IsDepsEntryLiveFor(Node *node)
Returns if the deps entry for a node is still reachable from the manifest.