22 #define __STDC_FORMAT_MACROS
42 const int kOldestSupportedVersion = 4;
47 #define BIG_CONSTANT(x) (x)
48 #else // defined(_MSC_VER)
49 #define BIG_CONSTANT(x) (x##LLU)
50 #endif // !defined(_MSC_VER)
52 uint64_t MurmurHash64A(
const void* key,
size_t len) {
53 static const uint64_t seed = 0xDECAFBADDECAFBADull;
58 const uint64_t * end = data + (len/8);
67 const unsigned char* data2 = (
const unsigned char*)data;
70 case 7: h ^=
uint64_t(data2[6]) << 48;
71 case 6: h ^=
uint64_t(data2[5]) << 40;
72 case 5: h ^=
uint64_t(data2[4]) << 32;
73 case 4: h ^=
uint64_t(data2[3]) << 24;
74 case 3: h ^=
uint64_t(data2[2]) << 16;
75 case 2: h ^=
uint64_t(data2[1]) << 8;
91 return MurmurHash64A(command.
str_, command.
len_);
98 int start_time,
int end_time,
TimeStamp restat_mtime)
99 : output(output), command_hash(command_hash),
100 start_time(start_time), end_time(end_time), restat_mtime(restat_mtime)
119 *err = strerror(errno);
122 setvbuf(
log_file_, NULL, _IOLBF, BUFSIZ);
131 *err = strerror(errno);
143 for (vector<Node*>::iterator out = edge->
outputs_.begin();
144 out != edge->
outputs_.end(); ++out) {
145 const string& path = (*out)->path();
146 Entries::iterator i =
entries_.find(path);
149 log_entry = i->second;
152 entries_.insert(Entries::value_type(log_entry->
output, log_entry));
180 bool ReadLine(
char** line_start,
char** line_end) {
197 size_t size_rest = (
buf_end_ -
buf_) - already_consumed;
200 size_t read = fread(buf_ + size_rest, 1,
sizeof(buf_) - size_rest,
file_);
223 FILE* file = fopen(path.c_str(),
"r");
227 *err = strerror(errno);
232 int unique_entry_count = 0;
233 int total_entry_count = 0;
236 char* line_start = 0;
238 while (reader.
ReadLine(&line_start, &line_end)) {
242 if (log_version < kOldestSupportedVersion) {
243 *err = (
"build log version invalid, perhaps due to being too old; "
246 unlink(path.c_str());
257 const char kFieldSeparator =
'\t';
259 char* start = line_start;
260 char* end = (
char*)memchr(start, kFieldSeparator, line_end - start);
265 int start_time = 0, end_time = 0;
268 start_time = atoi(start);
271 end = (
char*)memchr(start, kFieldSeparator, line_end - start);
275 end_time = atoi(start);
278 end = (
char*)memchr(start, kFieldSeparator, line_end - start);
282 restat_mtime = atol(start);
285 end = (
char*)memchr(start, kFieldSeparator, line_end - start);
288 string output = string(start, end - start);
294 Entries::iterator i =
entries_.find(output);
300 ++unique_entry_count;
307 if (log_version >= 5) {
308 char c = *end; *end =
'\0';
325 int kMinCompactionEntryCount = 100;
326 int kCompactionRatio = 3;
329 }
else if (total_entry_count > kMinCompactionEntryCount &&
330 total_entry_count > unique_entry_count * kCompactionRatio) {
338 Entries::iterator i =
entries_.find(path);
345 fprintf(f,
"%d\t%d\t%d\t%s\t%" PRIx64 "\n",
352 printf(
"Recompacting log...\n");
354 string temp_path = path +
".recompact";
355 FILE* f = fopen(temp_path.c_str(),
"wb");
357 *err = strerror(errno);
362 *err = strerror(errno);
372 if (unlink(path.c_str()) < 0) {
373 *err = strerror(errno);
377 if (rename(temp_path.c_str(), path.c_str()) < 0) {
378 *err = strerror(errno);
bool OpenForWrite(const string &path, string *err)
const int kCurrentVersion
const char kFileSignature[]
StringPiece represents a slice of a string whose memory is managed externally.
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.
void SetCloseOnExec(int fd)
Mark a file descriptor to not be inherited on exec()s.
void RecordCommand(Edge *edge, int start_time, int end_time, TimeStamp restat_mtime=0)
bool Recompact(const string &path, string *err)
Rewrite the known log entries, throwing away old data.
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.
void WriteEntry(FILE *f, const LogEntry &entry)
Serialize an entry into a log file.
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)
vector< Node * > outputs_