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