• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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_STATUS_H_
16 #define NINJA_STATUS_H_
17 
18 #include <map>
19 #include <string>
20 
21 #include "build.h"
22 #include "line_printer.h"
23 
24 /// Abstract interface to object that tracks the status of a build:
25 /// completion fraction, printing updates.
26 struct Status {
27     virtual void EdgeAddedToPlan(const Edge* edge) = 0;
28     virtual void EdgeRemovedFromPlan(const Edge* edge) = 0;
29     virtual void BuildEdgeStarted(const Edge* edge,
30                                                                 int64_t start_time_millis) = 0;
31     virtual void BuildEdgeFinished(Edge* edge, int64_t start_time_millis,
32                                                                   int64_t end_time_millis, bool success,
33                                                                   const std::string& output) = 0;
34     virtual void BuildLoadDyndeps() = 0;
35     virtual void BuildStarted() = 0;
36     virtual void BuildFinished() = 0;
37 
38     virtual void Info(const char* msg, ...) = 0;
39     virtual void Warning(const char* msg, ...) = 0;
40     virtual void Error(const char* msg, ...) = 0;
41 
~StatusStatus42     virtual ~Status() { }
43 };
44 
45 /// Implementation of the Status interface that prints the status as
46 /// human-readable strings to stdout
47 struct StatusPrinter : Status {
48     explicit StatusPrinter(const BuildConfig& config);
49 
50     /// Callbacks for the Plan to notify us about adding/removing Edge's.
51     virtual void EdgeAddedToPlan(const Edge* edge);
52     virtual void EdgeRemovedFromPlan(const Edge* edge);
53 
54     virtual void BuildEdgeStarted(const Edge* edge, int64_t start_time_millis);
55     virtual void BuildEdgeFinished(Edge* edge, int64_t start_time_millis,
56                                                                   int64_t end_time_millis, bool success,
57                                                                   const std::string& output);
58     virtual void BuildLoadDyndeps();
59     virtual void BuildStarted();
60     virtual void BuildFinished();
61 
62     virtual void Info(const char* msg, ...);
63     virtual void Warning(const char* msg, ...);
64     virtual void Error(const char* msg, ...);
65 
~StatusPrinterStatusPrinter66     virtual ~StatusPrinter() { }
67 
68     /// Format the progress status string by replacing the placeholders.
69     /// See the user manual for more information about the available
70     /// placeholders.
71     /// @param progress_status_format The format of the progress status.
72     /// @param status The status of the edge.
73     std::string FormatProgressStatus(const char* progress_status_format,
74                                                                       int64_t time_millis) const;
75 
76   private:
77     void PrintStatus(const Edge* edge, int64_t time_millis);
78 
79     const BuildConfig& config_;
80 
81     int started_edges_, finished_edges_, total_edges_, running_edges_;
82 
83     /// How much wall clock elapsed so far?
84     int64_t time_millis_ = 0;
85 
86     /// How much cpu clock elapsed so far?
87     int64_t cpu_time_millis_ = 0;
88 
89     /// What percentage of predicted total time have elapsed already?
90     double time_predicted_percentage_ = 0.0;
91 
92     /// Out of all the edges, for how many do we know previous time?
93     int eta_predictable_edges_total_ = 0;
94     /// And how much time did they all take?
95     int64_t eta_predictable_cpu_time_total_millis_ = 0;
96 
97     /// Out of all the non-finished edges, for how many do we know previous time?
98     int eta_predictable_edges_remaining_ = 0;
99     /// And how much time will they all take?
100     int64_t eta_predictable_cpu_time_remaining_millis_ = 0;
101 
102     /// For how many edges we don't know the previous run time?
103     int eta_unpredictable_edges_remaining_ = 0;
104 
105     void RecalculateProgressPrediction();
106 
107     /// Prints progress output.
108     LinePrinter printer_;
109 
110     /// The custom progress status format to use.
111     const char* progress_status_format_;
112 
113     template<size_t S>
SnprintfRateStatusPrinter114     void SnprintfRate(double rate, char(&buf)[S], const char* format) const {
115         if (rate == -1)
116             snprintf(buf, S, "?");
117         else
118             snprintf(buf, S, format, rate);
119     }
120 
121     struct SlidingRateInfo {
SlidingRateInfoStatusPrinter::SlidingRateInfo122         SlidingRateInfo(int n) : rate_(-1), N(n), last_update_(-1) {}
123 
rateStatusPrinter::SlidingRateInfo124         double rate() { return rate_; }
125 
UpdateRateStatusPrinter::SlidingRateInfo126         void UpdateRate(int update_hint, int64_t time_millis) {
127             if (update_hint == last_update_)
128                 return;
129             last_update_ = update_hint;
130 
131             if (times_.size() == N)
132                 times_.pop();
133             times_.push(time_millis);
134             if (times_.back() != times_.front())
135                 rate_ = times_.size() / ((times_.back() - times_.front()) / 1e3);
136         }
137 
138     private:
139         double rate_;
140         const size_t N;
141         std::queue<double> times_;
142         int last_update_;
143     };
144 
145     mutable SlidingRateInfo current_rate_;
146 };
147 
148 #endif // NINJA_STATUS_H_
149