| // Copyright 2016 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef NINJA_STATUS_H_ |
| #define NINJA_STATUS_H_ |
| |
| #include <memory> |
| #include <queue> |
| #include <string> |
| #include <unordered_map> |
| |
| #include "async_loop.h" |
| #include "build.h" |
| #include "line_printer.h" |
| |
| /// Abstract interface to object that tracks the status of a build: |
| /// completion fraction, printing updates. |
| struct Status { |
| virtual void PlanHasTotalEdges(int total) = 0; |
| virtual void BuildEdgeStarted(const Edge* edge) = 0; |
| virtual void BuildEdgeFinished(Edge* edge, bool success, |
| const std::string& output) = 0; |
| virtual void BuildLoadDyndeps() = 0; |
| virtual void BuildStarted() = 0; |
| virtual void BuildFinished() = 0; |
| |
| virtual void Info(const char* msg, ...) = 0; |
| virtual void Warning(const char* msg, ...) = 0; |
| virtual void Error(const char* msg, ...) = 0; |
| |
| virtual ~Status() { } |
| }; |
| |
| /// Implementation of the Status interface that prints the status as |
| /// human-readable strings to stdout |
| struct StatusPrinter : Status { |
| explicit StatusPrinter(const BuildConfig& config); |
| void PlanHasTotalEdges(int total) override; |
| void BuildEdgeStarted(const Edge* edge) override; |
| void BuildEdgeFinished(Edge* edge, bool success, |
| const std::string& output) override; |
| void BuildLoadDyndeps() override; |
| void BuildStarted() override; |
| void BuildFinished() override; |
| |
| void Info(const char* msg, ...) override; |
| void Warning(const char* msg, ...) override; |
| void Error(const char* msg, ...) override; |
| |
| virtual ~StatusPrinter(); |
| |
| /// Format the progress status string by replacing the placeholders. |
| /// See the user manual for more information about the available |
| /// placeholders. |
| /// @param progress_status_format The format of the progress status. |
| /// @param status The status of the edge. |
| std::string FormatProgressStatus(const char* progress_status_format, |
| int64_t time_millis) const; |
| |
| private: |
| void PrintStatus(const Edge* edge, int64_t time_millis); |
| |
| void BuildRefresh(int64_t current_time_ms); |
| void EnableTimer(); |
| void DisableTimer(); |
| |
| int64_t GetCurrentBuildTimeMs() const; |
| |
| const BuildConfig& config_; |
| |
| int started_edges_, finished_edges_, total_edges_, running_edges_; |
| int64_t time_millis_; |
| |
| /// Prints progress output. |
| LinePrinter printer_; |
| |
| /// The custom progress status format to use. |
| const char* progress_status_format_; |
| |
| struct SlidingRateInfo { |
| SlidingRateInfo(int n) : rate_(-1), N(n), last_update_(-1) {} |
| |
| double rate() { return rate_; } |
| |
| void UpdateRate(int update_hint, int64_t time_millis) { |
| if (update_hint == last_update_) |
| return; |
| last_update_ = update_hint; |
| |
| if (times_.size() == N) |
| times_.pop(); |
| times_.push(time_millis); |
| if (times_.back() != times_.front()) |
| rate_ = times_.size() / ((times_.back() - times_.front()) / 1e3); |
| } |
| |
| private: |
| double rate_; |
| const size_t N; |
| std::queue<double> times_; |
| int last_update_; |
| }; |
| |
| /// Called to refresh the pending list if needed. |
| void BuildRefresh(); |
| |
| mutable SlidingRateInfo current_rate_; |
| |
| /// Support for printing pending edges below the status on smart terminals. |
| void PrintPendingEdges(int64_t cur_time_millis); |
| void ClearPendingEdges(); |
| |
| std::string format_; |
| int64_t refresh_timeout_ms_ = -1; |
| size_t max_pending_height_ = 0; |
| size_t last_pending_height_ = 0; |
| int64_t start_build_time_ms_ = 0; |
| int64_t last_update_time_ms_ = -1; |
| std::string last_status_; |
| |
| AsyncLoop* async_loop_ = nullptr; |
| AsyncTimer timer_; |
| |
| // Record pending edges |
| using EdgeMap = std::unordered_map<const Edge*, int64_t>; |
| EdgeMap pending_edges_; |
| |
| // Used on each PrintPendingEdges() call to minimize heap allocations. |
| // Note that EdgeMap::value_type.first has type |const Edge* const| and |
| // thus EdgeMap::value_type is not copyable and cannot be used as an |
| // std::vector<> item type. |
| using EdgeInfo = std::pair<const Edge*, int64_t>; |
| std::vector<EdgeInfo> sorted_pending_edges_; |
| }; |
| |
| #endif // NINJA_STATUS_H_ |