1// Copyright 2011 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef NINJA_BUILD_LOG_H_
16#define NINJA_BUILD_LOG_H_
17
18#include <string>
19#include <stdio.h>
20
21#include "hash_map.h"
22#include "load_status.h"
23#include "timestamp.h"
24#include "util.h" // uint64_t
25
26struct DiskInterface;
27struct Edge;
28
29/// Can answer questions about the manifest for the BuildLog.
30struct BuildLogUser {
31 /// Return if a given output is no longer part of the build manifest.
32 /// This is only called during recompaction and doesn't have to be fast.
33 virtual bool IsPathDead(StringPiece s) const = 0;
34};
35
36/// Store a log of every command ran for every build.
37/// It has a few uses:
38///
39/// 1) (hashes of) command lines for existing output files, so we know
40/// when we need to rebuild due to the command changing
41/// 2) timing information, perhaps for generating reports
42/// 3) restat information
43struct BuildLog {
44 BuildLog();
45 ~BuildLog();
46
47 /// Prepares writing to the log file without actually opening it - that will
48 /// happen when/if it's needed
49 bool OpenForWrite(const std::string& path, const BuildLogUser& user,
50 std::string* err);
51 bool RecordCommand(Edge* edge, int start_time, int end_time,
52 TimeStamp mtime = 0);
53 void Close();
54
55 /// Load the on-disk log.
56 LoadStatus Load(const std::string& path, std::string* err);
57
58 struct LogEntry {
59 std::string output;
60 uint64_t command_hash;
61 int start_time;
62 int end_time;
63 TimeStamp mtime;
64
65 static uint64_t HashCommand(StringPiece command);
66
67 // Used by tests.
68 bool operator==(const LogEntry& o) {
69 return output == o.output && command_hash == o.command_hash &&
70 start_time == o.start_time && end_time == o.end_time &&
71 mtime == o.mtime;
72 }
73
74 explicit LogEntry(const std::string& output);
75 LogEntry(const std::string& output, uint64_t command_hash,
76 int start_time, int end_time, TimeStamp mtime);
77 };
78
79 /// Lookup a previously-run command by its output path.
80 LogEntry* LookupByOutput(const std::string& path);
81
82 /// Serialize an entry into a log file.
83 bool WriteEntry(FILE* f, const LogEntry& entry);
84
85 /// Rewrite the known log entries, throwing away old data.
86 bool Recompact(const std::string& path, const BuildLogUser& user,
87 std::string* err);
88
89 /// Restat all outputs in the log
90 bool Restat(StringPiece path, const DiskInterface& disk_interface,
91 int output_count, char** outputs, std::string* err);
92
93 typedef ExternalStringHashMap<LogEntry*>::Type Entries;
94 const Entries& entries() const { return entries_; }
95
96 private:
97 /// Should be called before using log_file_. When false is returned, errno
98 /// will be set.
99 bool OpenForWriteIfNeeded();
100
101 Entries entries_;
102 FILE* log_file_;
103 std::string log_file_path_;
104 bool needs_recompaction_;
105};
106
107#endif // NINJA_BUILD_LOG_H_
108