18 #ifndef __STDC_FORMAT_MACROS 19 #define __STDC_FORMAT_MACROS 38 #if defined(_MSC_VER) && (_MSC_VER < 1800) 39 #define strtoll _strtoi64 52 const int kOldestSupportedVersion = 4;
57 #define BIG_CONSTANT(x) (x) 58 #else // defined(_MSC_VER) 59 #define BIG_CONSTANT(x) (x##LLU) 60 #endif // !defined(_MSC_VER) 62 uint64_t MurmurHash64A(
const void* key,
size_t len) {
63 static const uint64_t seed = 0xDECAFBADDECAFBADull;
67 const unsigned char* data = (
const unsigned char*)key;
70 memcpy(&k, data,
sizeof k);
81 case 7: h ^=
uint64_t(data[6]) << 48;
83 case 6: h ^=
uint64_t(data[5]) << 40;
85 case 5: h ^=
uint64_t(data[4]) << 32;
87 case 4: h ^=
uint64_t(data[3]) << 24;
89 case 3: h ^=
uint64_t(data[2]) << 16;
108 return MurmurHash64A(command.
str_, command.
len_);
115 int start_time,
int end_time,
TimeStamp restat_mtime)
116 : output(output), command_hash(command_hash),
117 start_time(start_time), end_time(end_time), mtime(restat_mtime)
136 *err = strerror(errno);
139 setvbuf(
log_file_, NULL, _IOLBF, BUFSIZ);
148 *err = strerror(errno);
160 for (vector<Node*>::iterator out = edge->
outputs_.begin();
161 out != edge->
outputs_.end(); ++out) {
162 const string& path = (*out)->path();
163 Entries::iterator i =
entries_.find(path);
166 log_entry = i->second;
169 entries_.insert(Entries::value_type(log_entry->
output, log_entry));
174 log_entry->
mtime = mtime;
203 bool ReadLine(
char** line_start,
char** line_end) {
220 size_t size_rest = (
buf_end_ -
buf_) - already_consumed;
223 size_t read = fread(
buf_ + size_rest, 1,
sizeof(
buf_) - size_rest,
file_);
246 FILE* file = fopen(path.c_str(),
"r");
250 *err = strerror(errno);
255 int unique_entry_count = 0;
256 int total_entry_count = 0;
259 char* line_start = 0;
261 while (reader.
ReadLine(&line_start, &line_end)) {
265 if (log_version < kOldestSupportedVersion) {
266 *err = (
"build log version invalid, perhaps due to being too old; " 269 unlink(path.c_str());
280 const char kFieldSeparator =
'\t';
282 char* start = line_start;
283 char* end = (
char*)memchr(start, kFieldSeparator, line_end - start);
288 int start_time = 0, end_time = 0;
291 start_time = atoi(start);
294 end = (
char*)memchr(start, kFieldSeparator, line_end - start);
298 end_time = atoi(start);
301 end = (
char*)memchr(start, kFieldSeparator, line_end - start);
305 restat_mtime = strtoll(start, NULL, 10);
308 end = (
char*)memchr(start, kFieldSeparator, line_end - start);
311 string output = string(start, end - start);
317 Entries::iterator i =
entries_.find(output);
323 ++unique_entry_count;
329 entry->
mtime = restat_mtime;
330 if (log_version >= 5) {
331 char c = *end; *end =
'\0';
348 int kMinCompactionEntryCount = 100;
349 int kCompactionRatio = 3;
352 }
else if (total_entry_count > kMinCompactionEntryCount &&
353 total_entry_count > unique_entry_count * kCompactionRatio) {
361 Entries::iterator i =
entries_.find(path);
368 return fprintf(f,
"%d\t%d\t%" PRId64 "\t%s\t%" PRIx64 "\n",
378 string temp_path = path +
".recompact";
379 FILE* f = fopen(temp_path.c_str(),
"wb");
381 *err = strerror(errno);
386 *err = strerror(errno);
391 vector<StringPiece> dead_outputs;
394 dead_outputs.push_back(i->first);
399 *err = strerror(errno);
405 for (
size_t i = 0; i < dead_outputs.size(); ++i)
409 if (unlink(path.c_str()) < 0) {
410 *err = strerror(errno);
414 if (rename(temp_path.c_str(), path.c_str()) < 0) {
415 *err = strerror(errno);
const int kCurrentVersion
const char kFileSignature[]
bool RecordCommand(Edge *edge, int start_time, int end_time, TimeStamp mtime=0)
bool Recompact(const string &path, const BuildLogUser &user, string *err)
Rewrite the known log entries, throwing away old data.
StringPiece represents a slice of a string whose memory is managed externally.
bool WriteEntry(FILE *f, const LogEntry &entry)
Serialize an entry into a log file.
An edge in the dependency graph; links between Nodes using Rules.
string EvaluateCommand(bool incl_rsp_file=false)
Expand all variables in a command and return it as a string.
virtual bool IsPathDead(StringPiece s) const =0
Return if a given output is no longer part of the build manifest.
void SetCloseOnExec(int fd)
Mark a file descriptor to not be inherited on exec()s.
bool OpenForWrite(const string &path, const BuildLogUser &user, string *err)
#define NINJA_FALLTHROUGH
LogEntry(const string &output)
#define METRIC_RECORD(name)
The primary interface to metrics.
static uint64_t HashCommand(StringPiece command)
LogEntry * LookupByOutput(const string &path)
Lookup a previously-run command by its output path.
unsigned long long uint64_t
bool Load(const string &path, string *err)
Load the on-disk log.
bool ReadLine(char **line_start, char **line_end)
Can answer questions about the manifest for the BuildLog.
vector< Node * > outputs_