/src/ninja/src/deps_log.h
Line | Count | Source |
1 | | // Copyright 2012 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_DEPS_LOG_H_ |
16 | | #define NINJA_DEPS_LOG_H_ |
17 | | |
18 | | #include <string> |
19 | | #include <vector> |
20 | | |
21 | | #include <stdio.h> |
22 | | |
23 | | #include "load_status.h" |
24 | | #include "timestamp.h" |
25 | | |
26 | | struct Node; |
27 | | struct State; |
28 | | |
29 | | /// As build commands run they can output extra dependency information |
30 | | /// (e.g. header dependencies for C source) dynamically. DepsLog collects |
31 | | /// that information at build time and uses it for subsequent builds. |
32 | | /// |
33 | | /// The on-disk format is based on two primary design constraints: |
34 | | /// - it must be written to as a stream (during the build, which may be |
35 | | /// interrupted); |
36 | | /// - it can be read all at once on startup. (Alternative designs, where |
37 | | /// it contains indexing information, were considered and discarded as |
38 | | /// too complicated to implement; if the file is small than reading it |
39 | | /// fully on startup is acceptable.) |
40 | | /// Here are some stats from the Windows Chrome dependency files, to |
41 | | /// help guide the design space. The total text in the files sums to |
42 | | /// 90mb so some compression is warranted to keep load-time fast. |
43 | | /// There's about 10k files worth of dependencies that reference about |
44 | | /// 40k total paths totalling 2mb of unique strings. |
45 | | /// |
46 | | /// Based on these stats, here's the current design. |
47 | | /// The file is structured as version header followed by a sequence of records. |
48 | | /// Each record is either a path string or a dependency list. |
49 | | /// Numbering the path strings in file order gives them dense integer ids. |
50 | | /// A dependency list maps an output id to a list of input ids. |
51 | | /// |
52 | | /// Concretely, a record is: |
53 | | /// four bytes record length, high bit indicates record type |
54 | | /// (but max record sizes are capped at 512kB) |
55 | | /// path records contain the string name of the path, followed by up to 3 |
56 | | /// padding bytes to align on 4 byte boundaries, followed by the |
57 | | /// one's complement of the expected index of the record (to detect |
58 | | /// concurrent writes of multiple ninja processes to the log). |
59 | | /// dependency records are an array of 4-byte integers |
60 | | /// [output path id, |
61 | | /// output path mtime (lower 4 bytes), output path mtime (upper 4 bytes), |
62 | | /// input path id, input path id...] |
63 | | /// (The mtime is compared against the on-disk output path mtime |
64 | | /// to verify the stored data is up-to-date.) |
65 | | /// If two records reference the same output the latter one in the file |
66 | | /// wins, allowing updates to just be appended to the file. A separate |
67 | | /// repacking step can run occasionally to remove dead records. |
68 | | struct DepsLog { |
69 | 0 | DepsLog() : needs_recompaction_(false), file_(NULL) {} |
70 | | ~DepsLog(); |
71 | | |
72 | | // Writing (build-time) interface. |
73 | | bool OpenForWrite(const std::string& path, std::string* err); |
74 | | bool RecordDeps(Node* node, TimeStamp mtime, const std::vector<Node*>& nodes); |
75 | | bool RecordDeps(Node* node, TimeStamp mtime, int node_count, |
76 | | Node* const* nodes); |
77 | | void Close(); |
78 | | |
79 | | // Reading (startup-time) interface. |
80 | | struct Deps { |
81 | | Deps(int64_t mtime, int node_count) |
82 | 0 | : mtime(mtime), node_count(node_count), nodes(new Node*[node_count]) {} |
83 | 0 | ~Deps() { delete [] nodes; } |
84 | | TimeStamp mtime; |
85 | | int node_count; |
86 | | Node** nodes; |
87 | | }; |
88 | | LoadStatus Load(const std::string& path, State* state, std::string* err); |
89 | | Deps* GetDeps(Node* node); |
90 | | Node* GetFirstReverseDepsNode(Node* node); |
91 | | |
92 | | /// Rewrite the known log entries, throwing away old data. |
93 | | bool Recompact(const std::string& path, std::string* err); |
94 | | |
95 | | /// Returns if the deps entry for a node is still reachable from the manifest. |
96 | | /// |
97 | | /// The deps log can contain deps entries for files that were built in the |
98 | | /// past but are no longer part of the manifest. This function returns if |
99 | | /// this is the case for a given node. This function is slow, don't call |
100 | | /// it from code that runs on every build. |
101 | | static bool IsDepsEntryLiveFor(const Node* node); |
102 | | |
103 | | /// Used for tests. |
104 | 0 | const std::vector<Node*>& nodes() const { return nodes_; } |
105 | 0 | const std::vector<Deps*>& deps() const { return deps_; } |
106 | | |
107 | | private: |
108 | | // Updates the in-memory representation. Takes ownership of |deps|. |
109 | | // Returns true if a prior deps record was deleted. |
110 | | bool UpdateDeps(int out_id, Deps* deps); |
111 | | // Write a node name record, assigning it an id. |
112 | | bool RecordId(Node* node); |
113 | | |
114 | | /// Should be called before using file_. When false is returned, errno will |
115 | | /// be set. |
116 | | bool OpenForWriteIfNeeded(); |
117 | | |
118 | | bool needs_recompaction_; |
119 | | FILE* file_; |
120 | | std::string file_path_; |
121 | | |
122 | | /// Maps id -> Node. |
123 | | std::vector<Node*> nodes_; |
124 | | /// Maps id -> deps of that id. |
125 | | std::vector<Deps*> deps_; |
126 | | |
127 | | friend struct DepsLogTest; |
128 | | }; |
129 | | |
130 | | #endif // NINJA_DEPS_LOG_H_ |