18 #ifndef __STDC_FORMAT_MACROS
19 #define __STDC_FORMAT_MACROS
40 #if defined(_MSC_VER) && (_MSC_VER < 1800)
41 #define strtoll _strtoi64
54 const int kOldestSupportedVersion = 7;
67 int start_time,
int end_time,
TimeStamp mtime)
68 : output(output), command_hash(command_hash), start_time(start_time),
69 end_time(end_time), mtime(mtime) {}
94 for (std::vector<Node*>::iterator out = edge->
outputs_.begin();
95 out != edge->
outputs_.end(); ++out) {
96 const std::string& path = (*out)->path();
97 Entries::iterator i =
entries_.find(path);
100 log_entry = i->second.get();
104 entries_.emplace(log_entry->
output, std::unique_ptr<LogEntry>(log_entry));
109 log_entry->
mtime = mtime;
140 if (setvbuf(
log_file_, NULL, _IOLBF, BUFSIZ) != 0) {
159 : file_(file), buf_end_(buf_), line_start_(buf_), line_end_(NULL) {
160 memset(buf_, 0,
sizeof(buf_));
167 bool ReadLine(
char** line_start,
char** line_end) {
168 if (line_start_ >= buf_end_ || !line_end_) {
170 size_t size_read = fread(buf_, 1,
sizeof(buf_), file_);
174 buf_end_ = buf_ + size_read;
177 line_start_ = line_end_ + 1;
180 line_end_ =
static_cast<char*
>(memchr(line_start_,
'\n', buf_end_ - line_start_));
183 size_t already_consumed = line_start_ - buf_;
184 size_t size_rest = (buf_end_ - buf_) - already_consumed;
185 memmove(buf_, line_start_, size_rest);
187 size_t read = fread(buf_ + size_rest, 1,
sizeof(buf_) - size_rest, file_);
188 buf_end_ = buf_ + size_rest + read;
190 line_end_ =
static_cast<char*
>(memchr(line_start_,
'\n', buf_end_ - line_start_));
193 *line_start = line_start_;
194 *line_end = line_end_;
200 char buf_[256 << 10];
210 FILE* file = fopen(path.c_str(),
"r");
214 *err = strerror(errno);
219 int unique_entry_count = 0;
220 int total_entry_count = 0;
223 char* line_start = 0;
225 while (reader.
ReadLine(&line_start, &line_end)) {
229 bool invalid_log_version =
false;
230 if (log_version < kOldestSupportedVersion) {
231 invalid_log_version =
true;
232 *err =
"build log version is too old; starting over";
235 invalid_log_version =
true;
236 *err =
"build log version is too new; starting over";
238 if (invalid_log_version) {
251 const char kFieldSeparator =
'\t';
253 char* start = line_start;
254 char* end =
static_cast<char*
>(memchr(start, kFieldSeparator, line_end - start));
259 int start_time = 0, end_time = 0;
262 start_time = atoi(start);
265 end =
static_cast<char*
>(memchr(start, kFieldSeparator, line_end - start));
269 end_time = atoi(start);
272 end =
static_cast<char*
>(memchr(start, kFieldSeparator, line_end - start));
276 mtime = strtoll(start, NULL, 10);
279 end =
static_cast<char*
>(memchr(start, kFieldSeparator, line_end - start));
282 std::string output(start, end - start);
288 Entries::iterator i =
entries_.find(output);
290 entry = i->second.get();
292 entry =
new LogEntry(std::move(output));
294 entries_.emplace(entry->
output, std::unique_ptr<LogEntry>(entry));
295 ++unique_entry_count;
301 entry->
mtime = mtime;
302 char c = *end; *end =
'\0';
315 int kMinCompactionEntryCount = 100;
316 int kCompactionRatio = 3;
319 }
else if (total_entry_count > kMinCompactionEntryCount &&
320 total_entry_count > unique_entry_count * kCompactionRatio) {
328 Entries::iterator i =
entries_.find(path);
330 return i->second.get();
335 return fprintf(f,
"%d\t%d\t%" PRId64 "\t%s\t%" PRIx64 "\n",
345 std::string temp_path = path +
".recompact";
346 FILE* f = fopen(temp_path.c_str(),
"wb");
348 *err = strerror(errno);
353 *err = strerror(errno);
358 std::vector<StringPiece> dead_outputs;
361 dead_outputs.push_back(pair.first);
366 *err = strerror(errno);
377 *err = strerror(errno);
381 if (rename(temp_path.c_str(), path.c_str()) < 0) {
382 *err = strerror(errno);
391 const int output_count,
char** outputs,
392 std::string*
const err) {
396 std::string temp_path = path.
AsString() +
".restat";
397 FILE* f = fopen(temp_path.c_str(),
"wb");
399 *err = strerror(errno);
404 *err = strerror(errno);
409 bool skip = output_count > 0;
410 for (
int j = 0; j < output_count; ++j) {
411 if (pair.second->output == outputs[j]) {
417 const TimeStamp mtime = disk_interface.
Stat(pair.second->output, err);
422 pair.second->mtime = mtime;
426 *err = strerror(errno);
434 *err = strerror(errno);
438 if (rename(temp_path.c_str(), path.
str_) < 0) {
439 *err = strerror(errno);
static const int32_t kCurrentVersion
static const char kFileSignature[]
#define METRIC_RECORD(name)
The primary interface to metrics.
RAPIDHASH_INLINE uint64_t rapidhash(const void *key, size_t len) RAPIDHASH_NOEXCEPT
Can answer questions about the manifest for the BuildLog.
virtual bool IsPathDead(StringPiece s) const =0
Return if a given output is no longer part of the build manifest.
LogEntry(std::string output)
static uint64_t HashCommand(StringPiece command)
LogEntry * LookupByOutput(const std::string &path)
Lookup a previously-run command by its output path.
bool OpenForWriteIfNeeded()
Should be called before using log_file_.
LoadStatus Load(const std::string &path, std::string *err)
Load the on-disk log.
bool Recompact(const std::string &path, const BuildLogUser &user, std::string *err)
Rewrite the known log entries, throwing away old data.
bool WriteEntry(FILE *f, const LogEntry &entry)
Serialize an entry into a log file.
bool Restat(StringPiece path, const DiskInterface &disk_interface, int output_count, char **outputs, std::string *err)
Restat all outputs in the log.
std::string log_file_path_
bool OpenForWrite(const std::string &path, const BuildLogUser &user, std::string *err)
Prepares writing to the log file without actually opening it - that will happen when/if it's needed.
bool RecordCommand(Edge *edge, int start_time, int end_time, TimeStamp mtime=0)
Interface for accessing the disk.
virtual TimeStamp Stat(const std::string &path, std::string *err) const =0
stat() a file, returning the mtime, or 0 if missing and -1 on other errors.
An edge in the dependency graph; links between Nodes using Rules.
std::vector< Node * > outputs_
std::string EvaluateCommand(bool incl_rsp_file=false) const
Expand all variables in a command and return it as a string.
bool ReadLine(char **line_start, char **line_end)
StringPiece represents a slice of a string whose memory is managed externally.
std::string AsString() const
Convert the slice into a full-fledged std::string, copying the data into a new string.
int platformAwareUnlink(const char *filename)
void SetCloseOnExec(int fd)
Mark a file descriptor to not be inherited on exec()s.
unsigned long long uint64_t