Ninja
state.cc
Go to the documentation of this file.
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 #include "state.h"
16 
17 #include <assert.h>
18 #include <stdio.h>
19 
20 #include "edit_distance.h"
21 #include "graph.h"
22 #include "util.h"
23 
24 using namespace std;
25 
26 void Pool::EdgeScheduled(const Edge& edge) {
27  if (depth_ != 0)
28  current_use_ += edge.weight();
29 }
30 
31 void Pool::EdgeFinished(const Edge& edge) {
32  if (depth_ != 0)
33  current_use_ -= edge.weight();
34 }
35 
36 void Pool::DelayEdge(Edge* edge) {
37  assert(depth_ != 0);
38  delayed_.insert(edge);
39 }
40 
42  DelayedEdges::iterator it = delayed_.begin();
43  while (it != delayed_.end()) {
44  Edge* edge = *it;
45  if (current_use_ + edge->weight() > depth_)
46  break;
47  ready_queue->push(edge);
48  EdgeScheduled(*edge);
49  ++it;
50  }
51  delayed_.erase(delayed_.begin(), it);
52 }
53 
54 void Pool::Dump() const {
55  printf("%s (%d/%d) ->\n", name_.c_str(), current_use_, depth_);
56  for (DelayedEdges::const_iterator it = delayed_.begin();
57  it != delayed_.end(); ++it)
58  {
59  printf("\t");
60  (*it)->Dump();
61  }
62 }
63 
65 Pool State::kConsolePool("console", 1);
66 
68  bindings_.AddRule(Rule::Phony());
69  AddPool(&kDefaultPool);
70  AddPool(&kConsolePool);
71 }
72 
73 void State::AddPool(Pool* pool) {
74  assert(LookupPool(pool->name()) == NULL);
75  pools_[pool->name()] = pool;
76 }
77 
78 Pool* State::LookupPool(const string& pool_name) {
79  map<string, Pool*>::iterator i = pools_.find(pool_name);
80  if (i == pools_.end())
81  return NULL;
82  return i->second;
83 }
84 
85 Edge* State::AddEdge(const Rule* rule) {
86  Edge* edge = new Edge();
87  edge->rule_ = rule;
88  edge->pool_ = &State::kDefaultPool;
89  edge->env_ = &bindings_;
90  edge->id_ = edges_.size();
91  edges_.push_back(edge);
92  return edge;
93 }
94 
96  Node* node = LookupNode(path);
97  if (node)
98  return node;
99  node = new Node(path.AsString(), slash_bits);
100  paths_[node->path()] = node;
101  return node;
102 }
103 
105  Paths::const_iterator i = paths_.find(path);
106  if (i != paths_.end())
107  return i->second;
108  return NULL;
109 }
110 
111 Node* State::SpellcheckNode(const string& path) {
112  const bool kAllowReplacements = true;
113  const int kMaxValidEditDistance = 3;
114 
115  int min_distance = kMaxValidEditDistance + 1;
116  Node* result = NULL;
117  for (Paths::iterator i = paths_.begin(); i != paths_.end(); ++i) {
118  int distance = EditDistance(
119  i->first, path, kAllowReplacements, kMaxValidEditDistance);
120  if (distance < min_distance && i->second) {
121  min_distance = distance;
122  result = i->second;
123  }
124  }
125  return result;
126 }
127 
128 void State::AddIn(Edge* edge, StringPiece path, uint64_t slash_bits) {
129  Node* node = GetNode(path, slash_bits);
130  node->set_generated_by_dep_loader(false);
131  edge->inputs_.push_back(node);
132  node->AddOutEdge(edge);
133 }
134 
135 bool State::AddOut(Edge* edge, StringPiece path, uint64_t slash_bits,
136  std::string* err) {
137  Node* node = GetNode(path, slash_bits);
138  if (Edge* other = node->in_edge()) {
139  if (other == edge) {
140  *err = path.AsString() + " is defined as an output multiple times";
141  } else {
142  *err = "multiple rules generate " + path.AsString();
143  }
144  return false;
145  }
146  edge->outputs_.push_back(node);
147  node->set_in_edge(edge);
148  node->set_generated_by_dep_loader(false);
149  return true;
150 }
151 
152 void State::AddValidation(Edge* edge, StringPiece path, uint64_t slash_bits) {
153  Node* node = GetNode(path, slash_bits);
154  edge->validations_.push_back(node);
155  node->AddValidationOutEdge(edge);
156  node->set_generated_by_dep_loader(false);
157 }
158 
159 bool State::AddDefault(StringPiece path, string* err) {
160  Node* node = LookupNode(path);
161  if (!node) {
162  *err = "unknown target '" + path.AsString() + "'";
163  return false;
164  }
165  defaults_.push_back(node);
166  return true;
167 }
168 
169 vector<Node*> State::RootNodes(string* err) const {
170  vector<Node*> root_nodes;
171  // Search for nodes with no output.
172  for (vector<Edge*>::const_iterator e = edges_.begin();
173  e != edges_.end(); ++e) {
174  for (vector<Node*>::const_iterator out = (*e)->outputs_.begin();
175  out != (*e)->outputs_.end(); ++out) {
176  if ((*out)->out_edges().empty())
177  root_nodes.push_back(*out);
178  }
179  }
180 
181  if (!edges_.empty() && root_nodes.empty())
182  *err = "could not determine root nodes of build graph";
183 
184  return root_nodes;
185 }
186 
187 vector<Node*> State::DefaultNodes(string* err) const {
188  return defaults_.empty() ? RootNodes(err) : defaults_;
189 }
190 
191 void State::Reset() {
192  for (Paths::iterator i = paths_.begin(); i != paths_.end(); ++i)
193  i->second->ResetState();
194  for (vector<Edge*>::iterator e = edges_.begin(); e != edges_.end(); ++e) {
195  (*e)->outputs_ready_ = false;
196  (*e)->deps_loaded_ = false;
197  (*e)->mark_ = Edge::VisitNone;
198  }
199 }
200 
201 void State::Dump() {
202  for (Paths::iterator i = paths_.begin(); i != paths_.end(); ++i) {
203  Node* node = i->second;
204  printf("%s %s [id:%d]\n",
205  node->path().c_str(),
206  node->status_known() ? (node->dirty() ? "dirty" : "clean")
207  : "unknown",
208  node->id());
209  }
210  if (!pools_.empty()) {
211  printf("resource_pools:\n");
212  for (map<string, Pool*>::const_iterator it = pools_.begin();
213  it != pools_.end(); ++it)
214  {
215  if (!it->second->name().empty()) {
216  it->second->Dump();
217  }
218  }
219  }
220 }
int EditDistance(const StringPiece &s1, const StringPiece &s2, bool allow_replacements, int max_edit_distance)
Definition: hash_map.h:26
An edge in the dependency graph; links between Nodes using Rules.
Definition: graph.h:175
std::vector< Node * > outputs_
Definition: graph.h:217
int weight() const
Definition: graph.h:232
const Rule * rule_
Definition: graph.h:214
@ VisitNone
Definition: graph.h:177
Pool * pool_
Definition: graph.h:215
std::vector< Node * > validations_
Definition: graph.h:218
BindingEnv * env_
Definition: graph.h:220
std::vector< Node * > inputs_
Definition: graph.h:216
size_t id_
Definition: graph.h:222
Information about a node in the dependency graph: the file, whether it's dirty, mtime,...
Definition: graph.h:42
void set_in_edge(Edge *edge)
Definition: graph.h:101
int id() const
Definition: graph.h:111
void AddValidationOutEdge(Edge *edge)
Definition: graph.h:117
bool dirty() const
Definition: graph.h:93
void AddOutEdge(Edge *edge)
Definition: graph.h:116
const std::string & path() const
Definition: graph.h:82
Edge * in_edge() const
Definition: graph.h:100
bool status_known() const
Definition: graph.h:78
void set_generated_by_dep_loader(bool value)
Definition: graph.h:107
A pool for delayed edges.
Definition: state.h:40
void DelayEdge(Edge *edge)
adds the given edge to this Pool to be delayed.
Definition: state.cc:36
void RetrieveReadyEdges(EdgePriorityQueue *ready_queue)
Pool will add zero or more edges to the ready_queue.
Definition: state.cc:41
void EdgeScheduled(const Edge &edge)
informs this Pool that the given edge is committed to be run.
Definition: state.cc:26
const std::string & name() const
Definition: state.h:47
void EdgeFinished(const Edge &edge)
informs this Pool that the given edge is no longer runnable, and should relinquish its resources back...
Definition: state.cc:31
void Dump() const
Dump the Pool and its edges (useful for debugging).
Definition: state.cc:54
An invocable build command and associated metadata (description, etc.).
Definition: eval_env.h:66
static std::unique_ptr< Rule > Phony()
Definition: eval_env.cc:66
std::vector< Node * > RootNodes(std::string *error) const
Definition: state.cc:169
void AddValidation(Edge *edge, StringPiece path, uint64_t slash_bits)
Definition: state.cc:152
static Pool kConsolePool
Definition: state.h:97
std::vector< Node * > DefaultNodes(std::string *error) const
Definition: state.cc:187
bool AddDefault(StringPiece path, std::string *error)
Definition: state.cc:159
void AddPool(Pool *pool)
Definition: state.cc:73
Edge * AddEdge(const Rule *rule)
Definition: state.cc:85
Node * SpellcheckNode(const std::string &path)
Definition: state.cc:111
Node * GetNode(StringPiece path, uint64_t slash_bits)
Definition: state.cc:95
static Pool kDefaultPool
Definition: state.h:96
void AddIn(Edge *edge, StringPiece path, uint64_t slash_bits)
Add input / output / validation nodes to a given edge.
Definition: state.cc:128
Node * LookupNode(StringPiece path) const
Definition: state.cc:104
State()
Definition: state.cc:67
Pool * LookupPool(const std::string &pool_name)
Definition: state.cc:78
void Reset()
Reset state.
Definition: state.cc:191
void Dump()
Dump the nodes and Pools (useful for debugging).
Definition: state.cc:201
bool AddOut(Edge *edge, StringPiece path, uint64_t slash_bits, std::string *err)
Definition: state.cc:135
StringPiece represents a slice of a string whose memory is managed externally.
Definition: string_piece.h:25
std::string AsString() const
Convert the slice into a full-fledged std::string, copying the data into a new string.
Definition: string_piece.h:46
unsigned long long uint64_t
Definition: win32port.h:29