File: download_callbacks.cpp

package info (click to toggle)
dnf5 5.4.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 17,960 kB
  • sloc: cpp: 94,312; python: 3,370; xml: 1,073; ruby: 600; sql: 250; ansic: 232; sh: 104; perl: 62; makefile: 30
file content (128 lines) | stat: -rw-r--r-- 4,987 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright Contributors to the DNF5 project.
// Copyright Contributors to the libdnf project.
// SPDX-License-Identifier: GPL-2.0-or-later
//
// This file is part of libdnf: https://github.com/rpm-software-management/libdnf/
//
// Libdnf is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// Libdnf is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libdnf.  If not, see <https://www.gnu.org/licenses/>.

#include "download_callbacks.hpp"

namespace dnf5 {

void DownloadCallbacks::set_number_widget_visible(bool value) {
    number_widget_visible = value;
}

void DownloadCallbacks::set_show_total_bar_limit(std::size_t limit) {
    show_total_bar_limit = limit;
    if (multi_progress_bar) {
        multi_progress_bar->set_total_bar_visible_limit(limit);
    }
}

void * DownloadCallbacks::add_new_download(
    [[maybe_unused]] void * user_data, const char * description, double total_to_download) {
    if (!multi_progress_bar) {
        multi_progress_bar = std::make_unique<libdnf5::cli::progressbar::MultiProgressBar>();
        multi_progress_bar->set_total_bar_visible_limit(show_total_bar_limit);
    }
    auto progress_bar = std::make_unique<libdnf5::cli::progressbar::DownloadProgressBar>(
        total_to_download > 0 ? total_to_download : -1, description);
    auto * ppb = progress_bar.get();
    ppb->set_number_widget_visible(number_widget_visible);
    ppb->set_auto_finish(false);
    multi_progress_bar->add_bar(std::move(progress_bar));
    return ppb;
}

int DownloadCallbacks::progress(void * user_cb_data, double total_to_download, double downloaded) {
    auto * progress_bar = reinterpret_cast<libdnf5::cli::progressbar::DownloadProgressBar *>(user_cb_data);
    auto total = static_cast<int64_t>(total_to_download);
    if (total > 0) {
        progress_bar->set_total_ticks(total);
    }
    if (progress_bar->get_state() == libdnf5::cli::progressbar::ProgressBarState::READY) {
        progress_bar->start();
    }
    progress_bar->set_ticks(static_cast<int64_t>(downloaded));
    if (is_time_to_print()) {
        print();
    }
    return ReturnCode::OK;
}

int DownloadCallbacks::end(void * user_cb_data, TransferStatus status, const char * msg) {
    auto * progress_bar = reinterpret_cast<libdnf5::cli::progressbar::DownloadProgressBar *>(user_cb_data);
    switch (status) {
        case TransferStatus::SUCCESSFUL:
            // Correction of the total data size for the download.
            // Sometimes Librepo returns a larger data size for download than the actual file size.
            progress_bar->set_total_ticks(progress_bar->get_ticks());

            progress_bar->set_state(libdnf5::cli::progressbar::ProgressBarState::SUCCESS);
            break;
        case TransferStatus::ALREADYEXISTS:
            // skipping the download -> downloading 0 bytes
            progress_bar->set_ticks(0);
            progress_bar->set_total_ticks(0);
            progress_bar->add_message(libdnf5::cli::progressbar::MessageType::SUCCESS, msg);
            progress_bar->start();
            progress_bar->set_state(libdnf5::cli::progressbar::ProgressBarState::SUCCESS);
            break;
        case TransferStatus::ERROR:
            progress_bar->add_message(libdnf5::cli::progressbar::MessageType::ERROR, msg);
            progress_bar->set_state(libdnf5::cli::progressbar::ProgressBarState::ERROR);
            break;
    }
    print();
    return ReturnCode::OK;
}

int DownloadCallbacks::mirror_failure(void * user_cb_data, const char * msg, const char * url, const char * metadata) {
    auto * progress_bar = reinterpret_cast<libdnf5::cli::progressbar::DownloadProgressBar *>(user_cb_data);
    std::string message = std::string(msg) + " - " + url;
    if (metadata) {
        message = message + " - " + metadata;
    }
    progress_bar->add_message(libdnf5::cli::progressbar::MessageType::ERROR, message);
    print();
    return ReturnCode::OK;
}

void DownloadCallbacks::reset_progress_bar() {
    multi_progress_bar.reset();
    if (printed) {
        printed = false;
    }
}

bool DownloadCallbacks::is_time_to_print() {
    auto now = std::chrono::steady_clock::now();
    auto delta = now - prev_print_time;
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(delta).count();
    if (ms > 100) {
        // 100ms equals to 10 FPS and that seems to be smooth enough
        prev_print_time = now;
        return true;
    }
    return false;
}

void DownloadCallbacks::print() {
    multi_progress_bar->print();
    printed = true;
}

}  // namespace dnf5