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