diff --git a/platform/download_manager.hpp b/platform/download_manager.hpp index 13294aabc7..89dd3c79cc 100644 --- a/platform/download_manager.hpp +++ b/platform/download_manager.hpp @@ -14,6 +14,7 @@ struct HttpProgressT string m_url; int64_t m_current; int64_t m_total; + int64_t m_bytesPerSec; }; typedef function HttpProgressCallbackT; diff --git a/platform/qt_download.cpp b/platform/qt_download.cpp index 1aedb68782..05b05b5034 100644 --- a/platform/qt_download.cpp +++ b/platform/qt_download.cpp @@ -302,12 +302,23 @@ void QtDownload::OnHttpReadyRead() void QtDownload::OnUpdateDataReadProgress(qint64 bytesRead, qint64 totalBytes) { + m_urlGenerator.UpdateSpeed(bytesRead); if (m_params.m_progress) { HttpProgressT p; p.m_current = bytesRead; p.m_total = totalBytes; p.m_url = m_params.m_url; + p.m_bytesPerSec = m_urlGenerator.CurrentSpeed(); m_params.m_progress(p); } + // if download speed is slow, use next server + string const fasterUrl = m_urlGenerator.GetFasterUrl(); + if (!fasterUrl.empty()) + { + m_reply->abort(); + m_reply->deleteLater(); + m_currentUrl.setUrl(fasterUrl.c_str()); + StartRequest(); + } } diff --git a/platform/url_generator.cpp b/platform/url_generator.cpp index 5bd30acc57..de2e990646 100644 --- a/platform/url_generator.cpp +++ b/platform/url_generator.cpp @@ -38,12 +38,14 @@ static char const * g_defaultSecondGroup[] = { UrlGenerator::UrlGenerator() : m_randomGenerator(static_cast(time(NULL))), m_firstGroup(&g_defaultFirstGroup[0], &g_defaultFirstGroup[0] + ARRAY_SIZE(g_defaultFirstGroup)), - m_secondGroup(&g_defaultSecondGroup[0], &g_defaultSecondGroup[0] + ARRAY_SIZE(g_defaultSecondGroup)) + m_secondGroup(&g_defaultSecondGroup[0], &g_defaultSecondGroup[0] + ARRAY_SIZE(g_defaultSecondGroup)), + m_lastSecond(0.) { } UrlGenerator::UrlGenerator(vector const & firstGroup, vector const & secondGroup) - : m_randomGenerator(static_cast(time(NULL))), m_firstGroup(firstGroup), m_secondGroup(secondGroup) + : m_randomGenerator(static_cast(time(NULL))), m_firstGroup(firstGroup), m_secondGroup(secondGroup), + m_lastSecond(0.) { } @@ -84,3 +86,31 @@ string UrlGenerator::PopNextUrl() } return s; } + +void UrlGenerator::UpdateSpeed(int64_t totalBytesRead) +{ + double const seconds = m_timer.ElapsedSeconds(); + if (static_cast(seconds) - static_cast(m_lastSecond) > 0) + { + m_lastSecond = seconds; + m_speeds.push_back(make_pair(seconds, totalBytesRead)); + if (m_speeds.size() > 6) + m_speeds.pop_front(); + } +} + +int64_t UrlGenerator::CurrentSpeed() const +{ + switch (m_speeds.size()) + { + case 0: + case 1: return -1; + default: return static_cast((m_speeds.back().second - m_speeds.front().second) + / (m_speeds.back().first - m_speeds.front().first)); + } +} + +string UrlGenerator::GetFasterUrl() +{ + return string(); +} diff --git a/platform/url_generator.hpp b/platform/url_generator.hpp index 198a1a2bd7..65f61d68a7 100644 --- a/platform/url_generator.hpp +++ b/platform/url_generator.hpp @@ -1,9 +1,12 @@ #pragma once #include "../base/pseudo_random.hpp" +#include "../base/timer.hpp" #include "../std/vector.hpp" +#include "../std/list.hpp" #include "../std/string.hpp" +#include "../std/utility.hpp" class UrlGenerator { @@ -11,9 +14,22 @@ class UrlGenerator vector m_firstGroup; vector m_secondGroup; + /// For moving average speed calculations + my::Timer m_timer; + /// Stores time in seconds from start and downloaded amount at that moment + typedef pair MarkT; + list m_speeds; + double m_lastSecond; + public: UrlGenerator(); explicit UrlGenerator(vector const & firstGroup, vector const & secondGroup); + /// @return Always return empty string if all urls were already popped string PopNextUrl(); + + /// @return -1 means speed is unknown + void UpdateSpeed(int64_t totalBytesRead); + int64_t CurrentSpeed() const; + string GetFasterUrl(); }; diff --git a/qt/update_dialog.cpp b/qt/update_dialog.cpp index a1a048f005..6ae1c3944d 100644 --- a/qt/update_dialog.cpp +++ b/qt/update_dialog.cpp @@ -307,7 +307,19 @@ namespace qt { QTreeWidgetItem * item = GetTreeItemByIndex(*m_tree, index); if (item) - item->setText(KColumnIndexSize, QString("%1%").arg(progress.m_current * 100 / progress.m_total)); + { + QString speed; + if (progress.m_bytesPerSec > 1000 * 1000) + speed = QString(" %1 MB/s").arg(QString::number(static_cast(progress.m_bytesPerSec) / (1000.0 * 1000.0), + 'f', 1)); + else if (progress.m_bytesPerSec > 1000) + speed = QString(" %1 kB/s").arg(progress.m_bytesPerSec / 1000); + else if (progress.m_bytesPerSec >= 0) + speed = QString(" %1 B/sec").arg(progress.m_bytesPerSec); + + item->setText(KColumnIndexSize, QString("%1%%2").arg(progress.m_current * 100 / progress.m_total) + .arg(speed)); + } } void UpdateDialog::ShowDialog()