1
/** \file acquire_download_progress.cc */
3
// Copyright (C) 2010 Daniel Burrows
5
// This program is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU General Public License as
7
// published by the Free Software Foundation; either version 2 of the
8
// License, or (at your option) any later version.
10
// This program is distributed in the hope that it will be useful, but
11
// WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
// General Public License for more details.
15
// You should have received a copy of the GNU General Public License
16
// along with this program; see the file COPYING. If not, write to
17
// the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
// Boston, MA 02111-1307, USA.
21
#include "acquire_download_progress.h"
23
#include <generic/apt/download_signal_log.h>
24
#include <generic/views/download_progress.h>
27
#include <apt-pkg/acquire-item.h>
28
#include <apt-pkg/acquire-worker.h>
30
#include <boost/make_shared.hpp>
32
#include <sigc++/bind.h>
34
using boost::make_shared;
35
using boost::shared_ptr;
44
boost::optional<T> if_not_zero(const T &t)
47
return boost::optional<T>();
49
return boost::optional<T>(t);
53
class acquire_download_progress::impl : public acquire_download_progress,
54
public sigc::trackable
56
friend shared_ptr<impl>
59
void media_change(const std::string &media,
60
const std::string &drive,
61
download_signal_log &manager,
62
const sigc::slot1<void, bool> &k);
64
void ims_hit(pkgAcquire::ItemDesc &item, download_signal_log &manager);
65
void fetch(pkgAcquire::ItemDesc &item, download_signal_log &manager);
66
void done(pkgAcquire::ItemDesc &item, download_signal_log &manager);
67
void fail(pkgAcquire::ItemDesc &item, download_signal_log &manager);
68
void start(download_signal_log &manager);
69
void stop(download_signal_log &manager, const sigc::slot0<void> &k);
70
void complete(download_signal_log &manager);
72
void pulse(pkgAcquire *owner, download_signal_log &manager,
73
const sigc::slot1<void, bool> &k);
76
// Keeps track of the next ID to assign to a download item.
79
shared_ptr<views::download_progress> view;
81
shared_ptr<views::download_progress::status>
82
get_current_status(pkgAcquire *owner, download_signal_log &manager);
85
impl(download_signal_log *log,
86
const shared_ptr<views::download_progress> &_view);
89
acquire_download_progress::impl::impl(download_signal_log *log,
90
const shared_ptr<views::download_progress> &_view)
94
log->MediaChange_sig.connect(sigc::mem_fun(*this, &impl::media_change));
95
log->IMSHit_sig.connect(sigc::mem_fun(*this, &impl::ims_hit));
96
log->Fetch_sig.connect(sigc::mem_fun(*this, &impl::fetch));
97
log->Done_sig.connect(sigc::mem_fun(*this, &impl::done));
98
log->Fail_sig.connect(sigc::mem_fun(*this, &impl::fail));
99
log->Pulse_sig.connect(sigc::mem_fun(*this, &impl::pulse));
100
log->Start_sig.connect(sigc::mem_fun(*this, &impl::start));
101
log->Stop_sig.connect(sigc::mem_fun(*this, &impl::stop));
102
log->Complete_sig.connect(sigc::mem_fun(*this, &impl::complete));
107
// Ensure that the download progress gets an update after a
108
// successful media change, so that we have the same behavior as
109
// the old download progress object.
110
void do_media_change_result(bool result,
111
download_signal_log &manager,
112
const sigc::slot1<void, bool> &k)
115
manager.set_update(true);
121
void acquire_download_progress::impl::media_change(const std::string &media,
122
const std::string &drive,
123
download_signal_log &manager,
124
const sigc::slot1<void, bool> &k)
126
view->media_change(media,
128
sigc::bind(sigc::ptr_fun(&do_media_change_result),
133
shared_ptr<views::download_progress::status>
134
acquire_download_progress::impl::get_current_status(pkgAcquire *owner,
135
download_signal_log &manager)
137
typedef views::download_progress::file_progress file_progress;
138
typedef views::download_progress::status status;
139
typedef status::worker_status worker_status;
141
std::vector<worker_status> active_downloads;
144
for(pkgAcquire::Worker *it = owner->WorkersBegin(); it != 0;
145
it = owner->WorkerStep(it))
147
if(it->CurrentItem == NULL)
149
if(!it->Status.empty())
150
active_downloads.push_back(it->Status);
155
current_file(it->CurrentSize,
157
it->CurrentItem->Owner->Complete,
158
it->CurrentItem->ShortDesc,
159
if_not_zero(it->CurrentItem->Owner->ID),
160
it->CurrentItem->Owner->Mode == NULL
162
: it->CurrentItem->Owner->Mode);
164
active_downloads.push_back(current_file);
168
const double download_rate = manager.get_currentCPS();
170
const double current_bytes = manager.get_current_bytes();
171
const double current_items = manager.get_current_items();
172
const double total_bytes = manager.get_total_bytes();
173
const double total_items = manager.get_total_items();
175
const double fraction_complete =
176
((double) (current_bytes + current_items)) / (total_bytes + total_items);
178
const unsigned long time_remaining =
181
: (total_bytes - current_bytes) / download_rate;
183
return boost::make_shared<status>(manager.get_currentCPS(),
189
void acquire_download_progress::impl::ims_hit(pkgAcquire::ItemDesc &item,
190
download_signal_log &manager)
192
view->file_already_downloaded(item.Description,
193
if_not_zero(item.Owner->ID),
194
if_not_zero(item.Owner->FileSize));
196
manager.set_update(true);
199
void acquire_download_progress::impl::fetch(pkgAcquire::ItemDesc &item,
200
download_signal_log &manager)
202
if(item.Owner->Complete)
208
view->file_started(item.Description,
209
if_not_zero(item.Owner->ID),
210
if_not_zero(item.Owner->FileSize));
212
manager.set_update(true);
215
void acquire_download_progress::impl::done(pkgAcquire::ItemDesc &item, download_signal_log &manager)
217
view->file_finished(item.Description,
218
if_not_zero(item.Owner->ID));
220
manager.set_update(true);
223
void acquire_download_progress::impl::fail(pkgAcquire::ItemDesc &item,
224
download_signal_log &manager)
226
// Ignore certain kinds of transient failures (bad code)
227
if (item.Owner->Status == pkgAcquire::Item::StatIdle)
230
view->error(item.Owner->Status == pkgAcquire::Item::StatDone,
231
item.Owner->ErrorText,
233
if_not_zero(item.Owner->ID));
235
manager.set_update(true);
238
void acquire_download_progress::impl::start(download_signal_log &manager)
243
void acquire_download_progress::impl::stop(download_signal_log &manager, const sigc::slot0<void> &k)
245
view->done(manager.get_fetched_bytes(),
246
manager.get_elapsed_time(),
247
manager.get_currentCPS());
252
void acquire_download_progress::impl::complete(download_signal_log &manager)
254
view->complete(manager.get_fetched_bytes(),
255
manager.get_elapsed_time(),
256
manager.get_currentCPS());
259
void acquire_download_progress::impl::pulse(pkgAcquire *owner,
260
download_signal_log &manager,
261
const sigc::slot1<void, bool> &k)
263
const shared_ptr<views::download_progress::status> status =
264
get_current_status(owner, manager);
266
manager.set_update(false);
268
k(view->update_progress(*status));
271
acquire_download_progress::acquire_download_progress()
275
acquire_download_progress::~acquire_download_progress()
279
shared_ptr<acquire_download_progress>
280
create_acquire_download_progress(download_signal_log *log,
281
const shared_ptr<views::download_progress> &view)
283
return make_shared<acquire_download_progress::impl>(log, view);