1695b41eeSopenharmony_ci// Copyright 2011 Google Inc. All Rights Reserved.
2695b41eeSopenharmony_ci//
3695b41eeSopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4695b41eeSopenharmony_ci// you may not use this file except in compliance with the License.
5695b41eeSopenharmony_ci// You may obtain a copy of the License at
6695b41eeSopenharmony_ci//
7695b41eeSopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8695b41eeSopenharmony_ci//
9695b41eeSopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10695b41eeSopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11695b41eeSopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12695b41eeSopenharmony_ci// See the License for the specific language governing permissions and
13695b41eeSopenharmony_ci// limitations under the License.
14695b41eeSopenharmony_ci
15695b41eeSopenharmony_ci#include "state.h"
16695b41eeSopenharmony_ci
17695b41eeSopenharmony_ci#include <assert.h>
18695b41eeSopenharmony_ci#include <stdio.h>
19695b41eeSopenharmony_ci
20695b41eeSopenharmony_ci#include "edit_distance.h"
21695b41eeSopenharmony_ci#include "graph.h"
22695b41eeSopenharmony_ci#include "util.h"
23695b41eeSopenharmony_ci
24695b41eeSopenharmony_ciusing namespace std;
25695b41eeSopenharmony_ci
26695b41eeSopenharmony_civoid Pool::EdgeScheduled(const Edge& edge) {
27695b41eeSopenharmony_ci  if (depth_ != 0)
28695b41eeSopenharmony_ci    current_use_ += edge.weight();
29695b41eeSopenharmony_ci}
30695b41eeSopenharmony_ci
31695b41eeSopenharmony_civoid Pool::EdgeFinished(const Edge& edge) {
32695b41eeSopenharmony_ci  if (depth_ != 0)
33695b41eeSopenharmony_ci    current_use_ -= edge.weight();
34695b41eeSopenharmony_ci}
35695b41eeSopenharmony_ci
36695b41eeSopenharmony_civoid Pool::DelayEdge(Edge* edge) {
37695b41eeSopenharmony_ci  assert(depth_ != 0);
38695b41eeSopenharmony_ci  delayed_.insert(edge);
39695b41eeSopenharmony_ci}
40695b41eeSopenharmony_ci
41695b41eeSopenharmony_civoid Pool::RetrieveReadyEdges(EdgeSet* ready_queue) {
42695b41eeSopenharmony_ci  DelayedEdges::iterator it = delayed_.begin();
43695b41eeSopenharmony_ci  while (it != delayed_.end()) {
44695b41eeSopenharmony_ci    Edge* edge = *it;
45695b41eeSopenharmony_ci    if (current_use_ + edge->weight() > depth_)
46695b41eeSopenharmony_ci      break;
47695b41eeSopenharmony_ci    ready_queue->insert(edge);
48695b41eeSopenharmony_ci    EdgeScheduled(*edge);
49695b41eeSopenharmony_ci    ++it;
50695b41eeSopenharmony_ci  }
51695b41eeSopenharmony_ci  delayed_.erase(delayed_.begin(), it);
52695b41eeSopenharmony_ci}
53695b41eeSopenharmony_ci
54695b41eeSopenharmony_civoid Pool::Dump() const {
55695b41eeSopenharmony_ci  printf("%s (%d/%d) ->\n", name_.c_str(), current_use_, depth_);
56695b41eeSopenharmony_ci  for (DelayedEdges::const_iterator it = delayed_.begin();
57695b41eeSopenharmony_ci       it != delayed_.end(); ++it)
58695b41eeSopenharmony_ci  {
59695b41eeSopenharmony_ci    printf("\t");
60695b41eeSopenharmony_ci    (*it)->Dump();
61695b41eeSopenharmony_ci  }
62695b41eeSopenharmony_ci}
63695b41eeSopenharmony_ci
64695b41eeSopenharmony_ciPool State::kDefaultPool("", 0);
65695b41eeSopenharmony_ciPool State::kConsolePool("console", 1);
66695b41eeSopenharmony_ciconst Rule State::kPhonyRule("phony");
67695b41eeSopenharmony_ci
68695b41eeSopenharmony_ciState::State() {
69695b41eeSopenharmony_ci  bindings_.AddRule(&kPhonyRule);
70695b41eeSopenharmony_ci  AddPool(&kDefaultPool);
71695b41eeSopenharmony_ci  AddPool(&kConsolePool);
72695b41eeSopenharmony_ci}
73695b41eeSopenharmony_ci
74695b41eeSopenharmony_civoid State::AddPool(Pool* pool) {
75695b41eeSopenharmony_ci  assert(LookupPool(pool->name()) == NULL);
76695b41eeSopenharmony_ci  pools_[pool->name()] = pool;
77695b41eeSopenharmony_ci}
78695b41eeSopenharmony_ci
79695b41eeSopenharmony_ciPool* State::LookupPool(const string& pool_name) {
80695b41eeSopenharmony_ci  map<string, Pool*>::iterator i = pools_.find(pool_name);
81695b41eeSopenharmony_ci  if (i == pools_.end())
82695b41eeSopenharmony_ci    return NULL;
83695b41eeSopenharmony_ci  return i->second;
84695b41eeSopenharmony_ci}
85695b41eeSopenharmony_ci
86695b41eeSopenharmony_ciEdge* State::AddEdge(const Rule* rule) {
87695b41eeSopenharmony_ci  Edge* edge = new Edge();
88695b41eeSopenharmony_ci  edge->rule_ = rule;
89695b41eeSopenharmony_ci  edge->pool_ = &State::kDefaultPool;
90695b41eeSopenharmony_ci  edge->env_ = &bindings_;
91695b41eeSopenharmony_ci  edge->id_ = edges_.size();
92695b41eeSopenharmony_ci  edges_.push_back(edge);
93695b41eeSopenharmony_ci  return edge;
94695b41eeSopenharmony_ci}
95695b41eeSopenharmony_ci
96695b41eeSopenharmony_ciNode* State::GetNode(StringPiece path, uint64_t slash_bits) {
97695b41eeSopenharmony_ci  Node* node = LookupNode(path);
98695b41eeSopenharmony_ci  if (node)
99695b41eeSopenharmony_ci    return node;
100695b41eeSopenharmony_ci  node = new Node(path.AsString(), slash_bits);
101695b41eeSopenharmony_ci  paths_[node->path()] = node;
102695b41eeSopenharmony_ci  return node;
103695b41eeSopenharmony_ci}
104695b41eeSopenharmony_ci
105695b41eeSopenharmony_ciNode* State::LookupNode(StringPiece path) const {
106695b41eeSopenharmony_ci  Paths::const_iterator i = paths_.find(path);
107695b41eeSopenharmony_ci  if (i != paths_.end())
108695b41eeSopenharmony_ci    return i->second;
109695b41eeSopenharmony_ci  return NULL;
110695b41eeSopenharmony_ci}
111695b41eeSopenharmony_ci
112695b41eeSopenharmony_ciNode* State::SpellcheckNode(const string& path) {
113695b41eeSopenharmony_ci  const bool kAllowReplacements = true;
114695b41eeSopenharmony_ci  const int kMaxValidEditDistance = 3;
115695b41eeSopenharmony_ci
116695b41eeSopenharmony_ci  int min_distance = kMaxValidEditDistance + 1;
117695b41eeSopenharmony_ci  Node* result = NULL;
118695b41eeSopenharmony_ci  for (Paths::iterator i = paths_.begin(); i != paths_.end(); ++i) {
119695b41eeSopenharmony_ci    int distance = EditDistance(
120695b41eeSopenharmony_ci        i->first, path, kAllowReplacements, kMaxValidEditDistance);
121695b41eeSopenharmony_ci    if (distance < min_distance && i->second) {
122695b41eeSopenharmony_ci      min_distance = distance;
123695b41eeSopenharmony_ci      result = i->second;
124695b41eeSopenharmony_ci    }
125695b41eeSopenharmony_ci  }
126695b41eeSopenharmony_ci  return result;
127695b41eeSopenharmony_ci}
128695b41eeSopenharmony_ci
129695b41eeSopenharmony_civoid State::AddIn(Edge* edge, StringPiece path, uint64_t slash_bits) {
130695b41eeSopenharmony_ci  Node* node = GetNode(path, slash_bits);
131695b41eeSopenharmony_ci  node->set_generated_by_dep_loader(false);
132695b41eeSopenharmony_ci  edge->inputs_.push_back(node);
133695b41eeSopenharmony_ci  node->AddOutEdge(edge);
134695b41eeSopenharmony_ci}
135695b41eeSopenharmony_ci
136695b41eeSopenharmony_cibool State::AddOut(Edge* edge, StringPiece path, uint64_t slash_bits) {
137695b41eeSopenharmony_ci  Node* node = GetNode(path, slash_bits);
138695b41eeSopenharmony_ci  if (node->in_edge()) {
139695b41eeSopenharmony_ci    return false;
140695b41eeSopenharmony_ci  }
141695b41eeSopenharmony_ci  edge->outputs_.push_back(node);
142695b41eeSopenharmony_ci  node->set_in_edge(edge);
143695b41eeSopenharmony_ci  node->set_generated_by_dep_loader(false);
144695b41eeSopenharmony_ci  return true;
145695b41eeSopenharmony_ci}
146695b41eeSopenharmony_ci
147695b41eeSopenharmony_civoid State::AddValidation(Edge* edge, StringPiece path, uint64_t slash_bits) {
148695b41eeSopenharmony_ci  Node* node = GetNode(path, slash_bits);
149695b41eeSopenharmony_ci  edge->validations_.push_back(node);
150695b41eeSopenharmony_ci  node->AddValidationOutEdge(edge);
151695b41eeSopenharmony_ci  node->set_generated_by_dep_loader(false);
152695b41eeSopenharmony_ci}
153695b41eeSopenharmony_ci
154695b41eeSopenharmony_cibool State::AddDefault(StringPiece path, string* err) {
155695b41eeSopenharmony_ci  Node* node = LookupNode(path);
156695b41eeSopenharmony_ci  if (!node) {
157695b41eeSopenharmony_ci    *err = "unknown target '" + path.AsString() + "'";
158695b41eeSopenharmony_ci    return false;
159695b41eeSopenharmony_ci  }
160695b41eeSopenharmony_ci  defaults_.push_back(node);
161695b41eeSopenharmony_ci  return true;
162695b41eeSopenharmony_ci}
163695b41eeSopenharmony_ci
164695b41eeSopenharmony_civector<Node*> State::RootNodes(string* err) const {
165695b41eeSopenharmony_ci  vector<Node*> root_nodes;
166695b41eeSopenharmony_ci  // Search for nodes with no output.
167695b41eeSopenharmony_ci  for (vector<Edge*>::const_iterator e = edges_.begin();
168695b41eeSopenharmony_ci       e != edges_.end(); ++e) {
169695b41eeSopenharmony_ci    for (vector<Node*>::const_iterator out = (*e)->outputs_.begin();
170695b41eeSopenharmony_ci         out != (*e)->outputs_.end(); ++out) {
171695b41eeSopenharmony_ci      if ((*out)->out_edges().empty())
172695b41eeSopenharmony_ci        root_nodes.push_back(*out);
173695b41eeSopenharmony_ci    }
174695b41eeSopenharmony_ci  }
175695b41eeSopenharmony_ci
176695b41eeSopenharmony_ci  if (!edges_.empty() && root_nodes.empty())
177695b41eeSopenharmony_ci    *err = "could not determine root nodes of build graph";
178695b41eeSopenharmony_ci
179695b41eeSopenharmony_ci  return root_nodes;
180695b41eeSopenharmony_ci}
181695b41eeSopenharmony_ci
182695b41eeSopenharmony_civector<Node*> State::DefaultNodes(string* err) const {
183695b41eeSopenharmony_ci  return defaults_.empty() ? RootNodes(err) : defaults_;
184695b41eeSopenharmony_ci}
185695b41eeSopenharmony_ci
186695b41eeSopenharmony_civoid State::Reset() {
187695b41eeSopenharmony_ci  for (Paths::iterator i = paths_.begin(); i != paths_.end(); ++i)
188695b41eeSopenharmony_ci    i->second->ResetState();
189695b41eeSopenharmony_ci  for (vector<Edge*>::iterator e = edges_.begin(); e != edges_.end(); ++e) {
190695b41eeSopenharmony_ci    (*e)->outputs_ready_ = false;
191695b41eeSopenharmony_ci    (*e)->deps_loaded_ = false;
192695b41eeSopenharmony_ci    (*e)->mark_ = Edge::VisitNone;
193695b41eeSopenharmony_ci  }
194695b41eeSopenharmony_ci}
195695b41eeSopenharmony_ci
196695b41eeSopenharmony_civoid State::Dump() {
197695b41eeSopenharmony_ci  for (Paths::iterator i = paths_.begin(); i != paths_.end(); ++i) {
198695b41eeSopenharmony_ci    Node* node = i->second;
199695b41eeSopenharmony_ci    printf("%s %s [id:%d]\n",
200695b41eeSopenharmony_ci           node->path().c_str(),
201695b41eeSopenharmony_ci           node->status_known() ? (node->dirty() ? "dirty" : "clean")
202695b41eeSopenharmony_ci                                : "unknown",
203695b41eeSopenharmony_ci           node->id());
204695b41eeSopenharmony_ci  }
205695b41eeSopenharmony_ci  if (!pools_.empty()) {
206695b41eeSopenharmony_ci    printf("resource_pools:\n");
207695b41eeSopenharmony_ci    for (map<string, Pool*>::const_iterator it = pools_.begin();
208695b41eeSopenharmony_ci         it != pools_.end(); ++it)
209695b41eeSopenharmony_ci    {
210695b41eeSopenharmony_ci      if (!it->second->name().empty()) {
211695b41eeSopenharmony_ci        it->second->Dump();
212695b41eeSopenharmony_ci      }
213695b41eeSopenharmony_ci    }
214695b41eeSopenharmony_ci  }
215695b41eeSopenharmony_ci}
216