From 34a88c83f04d4dfa6b138031dc79828abb4057f6 Mon Sep 17 00:00:00 2001 From: Nick Tiskov Date: Fri, 1 Mar 2013 13:31:45 +0400 Subject: [PATCH 1/3] Calculate eta for seed only torrents using ratio limits --- src/qtlibtorrent/torrentmodel.cpp | 2 +- src/qtlibtorrent/torrentspeedmonitor.cpp | 65 +++++++++++++++++------- 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/src/qtlibtorrent/torrentmodel.cpp b/src/qtlibtorrent/torrentmodel.cpp index 2dde082b0..435c62af7 100644 --- a/src/qtlibtorrent/torrentmodel.cpp +++ b/src/qtlibtorrent/torrentmodel.cpp @@ -172,7 +172,7 @@ QVariant TorrentModelItem::data(int column, int role) const return m_torrent.upload_payload_rate(); case TR_ETA: { // XXX: Is this correct? - if (m_torrent.is_seed() || m_torrent.is_paused() || m_torrent.is_queued()) return MAX_ETA; + if (m_torrent.is_paused() || m_torrent.is_queued()) return MAX_ETA; return QBtSession::instance()->getETA(m_torrent.hash()); } case TR_RATIO: diff --git a/src/qtlibtorrent/torrentspeedmonitor.cpp b/src/qtlibtorrent/torrentspeedmonitor.cpp index 56bbfde3e..3dc83b2c1 100644 --- a/src/qtlibtorrent/torrentspeedmonitor.cpp +++ b/src/qtlibtorrent/torrentspeedmonitor.cpp @@ -42,15 +42,15 @@ class SpeedSample { public: SpeedSample() {} - void addSample(int s); - qreal average() const; + void addSample(qint32 speedDL, qint32 speedUL); + QPair average() const; void clear(); private: static const int max_samples = 30; private: - QList m_speedSamples; + QList > m_speedSamples; }; TorrentSpeedMonitor::TorrentSpeedMonitor(QBtSession* session) : @@ -76,21 +76,31 @@ void TorrentSpeedMonitor::run() } while(!m_abort); } -void SpeedSample::addSample(int s) +void SpeedSample::addSample(qint32 speedDL, qint32 speedUL) { - m_speedSamples << s; + m_speedSamples << qMakePair(speedDL, speedUL); if (m_speedSamples.size() > max_samples) m_speedSamples.removeFirst(); } -qreal SpeedSample::average() const +QPair SpeedSample::average() const { - if (m_speedSamples.empty()) return 0; - qlonglong sum = 0; - foreach (int s, m_speedSamples) { - sum += s; + if (m_speedSamples.empty()) + return qMakePair(0., 0.); + + qlonglong sumDL = 0, sumUL =0; + + QPair p; + foreach (p, m_speedSamples) { + sumDL += p.first; + sumUL += p.second; } - return sum/static_cast(m_speedSamples.size()); + + qreal numSamples = m_speedSamples.size(); + return qMakePair( + (sumDL/numSamples), + (sumUL/numSamples)); + } void SpeedSample::clear() @@ -113,10 +123,31 @@ qlonglong TorrentSpeedMonitor::getETA(const QString &hash) const { QMutexLocker locker(&m_mutex); QTorrentHandle h = m_session->getTorrentHandle(hash); - if (h.is_paused() || !m_samples.contains(hash)) return -1; - const qreal speed_average = m_samples.value(hash).average(); - if (speed_average == 0) return -1; - return (h.total_wanted() - h.total_done()) / speed_average; + if (h.is_paused() || !m_samples.contains(hash)) + return -1; + + const QPair speed_average = m_samples.value(hash).average(); + + if(h.is_seed()) { + if (speed_average.second == 0) + return -1; + + bool _unused; + qreal max_ratio = m_session->getMaxRatioPerTorrent(hash, &_unused); + if (max_ratio < 0) + return -1; + + libtorrent::size_type realDL = h.all_time_download(); + if (realDL <= 0) + realDL = h.total_wanted(); + + return (realDL * max_ratio - h.all_time_upload()) / speed_average.second; + } else { + if (speed_average.first == 0) + return -1; + + return (h.total_wanted() - h.total_done()) / speed_average.first; + } } void TorrentSpeedMonitor::getSamples() @@ -130,10 +161,10 @@ void TorrentSpeedMonitor::getSamples() #if LIBTORRENT_VERSION_MINOR > 15 torrent_status st = it->status(0x0); if (!st.paused) - m_samples[misc::toQString(it->info_hash())].addSample(st.download_payload_rate); + m_samples[misc::toQString(it->info_hash())].addSample(st.download_payload_rate, st.upload_payload_rate); #else if (!it->is_paused()) - m_samples[misc::toQString(it->info_hash())].addSample(it->status().download_payload_rate); + m_samples[misc::toQString(it->info_hash())].addSample(it->status().download_payload_rate, it->status().upload_payload_rate); #endif } catch(invalid_handle&) {} } From 0c0c7459f1f11dac44f1f003fe9323c2655e9a04 Mon Sep 17 00:00:00 2001 From: Nick Tiskov Date: Fri, 1 Mar 2013 14:41:46 +0400 Subject: [PATCH 2/3] Cosmetic fix for eta sorting in torrent list: 'infinity' must always come last --- src/qtlibtorrent/torrentspeedmonitor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qtlibtorrent/torrentspeedmonitor.cpp b/src/qtlibtorrent/torrentspeedmonitor.cpp index 3dc83b2c1..a37b229c4 100644 --- a/src/qtlibtorrent/torrentspeedmonitor.cpp +++ b/src/qtlibtorrent/torrentspeedmonitor.cpp @@ -124,18 +124,18 @@ qlonglong TorrentSpeedMonitor::getETA(const QString &hash) const QMutexLocker locker(&m_mutex); QTorrentHandle h = m_session->getTorrentHandle(hash); if (h.is_paused() || !m_samples.contains(hash)) - return -1; + return MAX_ETA; const QPair speed_average = m_samples.value(hash).average(); if(h.is_seed()) { if (speed_average.second == 0) - return -1; + return MAX_ETA; bool _unused; qreal max_ratio = m_session->getMaxRatioPerTorrent(hash, &_unused); if (max_ratio < 0) - return -1; + return MAX_ETA; libtorrent::size_type realDL = h.all_time_download(); if (realDL <= 0) @@ -144,7 +144,7 @@ qlonglong TorrentSpeedMonitor::getETA(const QString &hash) const return (realDL * max_ratio - h.all_time_upload()) / speed_average.second; } else { if (speed_average.first == 0) - return -1; + return MAX_ETA; return (h.total_wanted() - h.total_done()) / speed_average.first; } From ec08bfac0790d7f5a0031d0c69997756b5230ff6 Mon Sep 17 00:00:00 2001 From: Nick Tiskov Date: Sun, 10 Mar 2013 22:04:05 +0400 Subject: [PATCH 3/3] Improve code readability in speed monitor --- src/qtlibtorrent/torrentspeedmonitor.cpp | 64 +++++++++++++----------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/src/qtlibtorrent/torrentspeedmonitor.cpp b/src/qtlibtorrent/torrentspeedmonitor.cpp index a37b229c4..fae0189e9 100644 --- a/src/qtlibtorrent/torrentspeedmonitor.cpp +++ b/src/qtlibtorrent/torrentspeedmonitor.cpp @@ -38,19 +38,25 @@ using namespace libtorrent; +template struct Sample { + Sample(const T down = 0, const T up = 0) : download(down), upload(up) {} + T download; + T upload; +}; + class SpeedSample { public: SpeedSample() {} - void addSample(qint32 speedDL, qint32 speedUL); - QPair average() const; + void addSample(int speedDL, int speedUL); + Sample average() const; void clear(); private: static const int max_samples = 30; private: - QList > m_speedSamples; + QList > m_speedSamples; }; TorrentSpeedMonitor::TorrentSpeedMonitor(QBtSession* session) : @@ -76,31 +82,28 @@ void TorrentSpeedMonitor::run() } while(!m_abort); } -void SpeedSample::addSample(qint32 speedDL, qint32 speedUL) +void SpeedSample::addSample(int speedDL, int speedUL) { - m_speedSamples << qMakePair(speedDL, speedUL); + m_speedSamples << Sample(speedDL, speedUL); if (m_speedSamples.size() > max_samples) m_speedSamples.removeFirst(); } -QPair SpeedSample::average() const +Sample SpeedSample::average() const { if (m_speedSamples.empty()) - return qMakePair(0., 0.); + return Sample(); - qlonglong sumDL = 0, sumUL =0; + qlonglong sumDL = 0; + qlonglong sumUL = 0; - QPair p; - foreach (p, m_speedSamples) { - sumDL += p.first; - sumUL += p.second; + foreach (const Sample& s, m_speedSamples) { + sumDL += s.download; + sumUL += s.upload; } - qreal numSamples = m_speedSamples.size(); - return qMakePair( - (sumDL/numSamples), - (sumUL/numSamples)); - + const qreal numSamples = m_speedSamples.size(); + return Sample(sumDL/numSamples, sumUL/numSamples); } void SpeedSample::clear() @@ -126,10 +129,10 @@ qlonglong TorrentSpeedMonitor::getETA(const QString &hash) const if (h.is_paused() || !m_samples.contains(hash)) return MAX_ETA; - const QPair speed_average = m_samples.value(hash).average(); + const Sample speed_average = m_samples[hash].average(); - if(h.is_seed()) { - if (speed_average.second == 0) + if (h.is_seed()) { + if (!speed_average.upload) return MAX_ETA; bool _unused; @@ -141,13 +144,13 @@ qlonglong TorrentSpeedMonitor::getETA(const QString &hash) const if (realDL <= 0) realDL = h.total_wanted(); - return (realDL * max_ratio - h.all_time_upload()) / speed_average.second; - } else { - if (speed_average.first == 0) - return MAX_ETA; - - return (h.total_wanted() - h.total_done()) / speed_average.first; + return (realDL * max_ratio - h.all_time_upload()) / speed_average.upload; } + + if (!speed_average.download) + return MAX_ETA; + + return (h.total_wanted() - h.total_done()) / speed_average.download; } void TorrentSpeedMonitor::getSamples() @@ -160,12 +163,13 @@ void TorrentSpeedMonitor::getSamples() try { #if LIBTORRENT_VERSION_MINOR > 15 torrent_status st = it->status(0x0); - if (!st.paused) - m_samples[misc::toQString(it->info_hash())].addSample(st.download_payload_rate, st.upload_payload_rate); + if (!st.paused) { #else - if (!it->is_paused()) - m_samples[misc::toQString(it->info_hash())].addSample(it->status().download_payload_rate, it->status().upload_payload_rate); + if (!it->is_paused()) { + torrent_status st = it->status(); #endif + m_samples[misc::toQString(it->info_hash())].addSample(st.download_payload_rate, st.upload_payload_rate); + } } catch(invalid_handle&) {} } }