Line data Source code
1 : /*! 2 : * \file esys/repo/progress/consoleobserver.h 3 : * \brief Plain-console SyncEvent observer (\\r status line) 4 : * 5 : * \cond 6 : * __legal_b__ 7 : * 8 : * Copyright (c) 2026 Michel Gillet 9 : * Distributed under the MIT License. 10 : * (See accompanying file LICENSE.txt or 11 : * copy at https://opensource.org/licenses/MIT) 12 : * 13 : * __legal_e__ 14 : * \endcond 15 : * 16 : */ 17 : 18 : #pragma once 19 : 20 : #include "esys/repo/esysrepo_defs.h" 21 : #include "esys/repo/progress/observer.h" 22 : #include "esys/repo/progress/repophase.h" 23 : #include "esys/repo/progress/transfercounters.h" 24 : 25 : #include <cstddef> 26 : #include <map> 27 : #include <mutex> 28 : #include <ostream> 29 : #include <string> 30 : 31 : namespace esys::repo::progress 32 : { 33 : 34 : /*! \class ConsoleObserver esys/repo/progress/consoleobserver.h 35 : * "esys/repo/progress/consoleobserver.h" 36 : * \brief Folds SyncEvents into the classic compact \\r status line 37 : * 38 : * Thread-safe: workers may call on_sync_event concurrently; format_status_line 39 : * may run from a redraw thread. 40 : */ 41 : class ESYSREPO_API ConsoleObserver : public Observer 42 : { 43 : public: 44 : //! Default constructor 45 : ConsoleObserver(); 46 : 47 : //! Destructor 48 : ~ConsoleObserver() override; 49 : 50 : void on_sync_event(const SyncEvent &event) override; 51 : 52 : //! Enable or disable status-line updates (quiet / non-interactive) 53 : /*! 54 : * \param[in] enabled when false, format_status_line returns empty 55 : */ 56 : void set_enabled(bool enabled); 57 : 58 : //! Whether status-line rendering is enabled 59 : /*! 60 : * \return true if enabled 61 : */ 62 : bool get_enabled() const; 63 : 64 : //! Build the current compact status line (no leading \\r) 65 : /*! 66 : * \return status text, or empty if disabled / nothing running 67 : */ 68 : std::string format_status_line() const; 69 : 70 : //! Write format_status_line() to the stream 71 : /*! 72 : * \param[out] os the output stream 73 : */ 74 : void print_status_line(std::ostream &os) const; 75 : 76 : private: 77 : //!< \cond DOXY_IMPL 78 492 : struct ActiveRepo 79 : { 80 : std::size_t m_repo_index = 0; 81 : RepoPhase m_phase = RepoPhase::NOT_SET; 82 : TransferCounters m_counters; 83 : int m_percentage = -1; 84 : bool m_done = false; 85 : }; 86 : 87 : void apply_assigned(const RepoAssignedEvent &event); 88 : void apply_progress(const RepoProgressEvent &event); 89 : void apply_done(const RepoDoneEvent &event); 90 : void apply_failed(const RepoFailedEvent &event); 91 : 92 : void erase_repo(std::size_t repo_index); 93 : ActiveRepo *find_repo(std::size_t repo_index); 94 : static int percentage_from_counters(RepoPhase phase, const TransferCounters &counters); 95 : static int step_from_phase(RepoPhase phase); 96 : static void append_repo_token(std::ostream &os, const ActiveRepo &repo); 97 : 98 : mutable std::mutex m_mutex; 99 : bool m_enabled = true; 100 : //! Active repos keyed by worker id for stable slot order 101 : std::map<int, ActiveRepo> m_by_worker; 102 : //!< \endcond 103 : }; 104 : 105 : } // namespace esys::repo::progress