From 616057a433eb206c7d6425d923ef2298b3146417 Mon Sep 17 00:00:00 2001 From: Vladimir Golovnev Date: Thu, 29 Sep 2022 06:49:34 +0300 Subject: [PATCH] Improve session statistics handling PR #17779. --- src/base/CMakeLists.txt | 2 - src/base/base.pri | 2 - src/base/bittorrent/session.h | 2 - src/base/bittorrent/sessionimpl.cpp | 62 +++++++++++---- src/base/bittorrent/sessionimpl.h | 14 +++- src/base/bittorrent/sessionstatus.h | 2 + src/base/bittorrent/statistics.cpp | 114 ---------------------------- src/base/bittorrent/statistics.h | 66 ---------------- src/gui/statsdialog.cpp | 4 +- src/webui/api/synccontroller.cpp | 4 +- 10 files changed, 64 insertions(+), 208 deletions(-) delete mode 100644 src/base/bittorrent/statistics.cpp delete mode 100644 src/base/bittorrent/statistics.h diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index 1e49f2f1b..115c61d67 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -33,7 +33,6 @@ add_library(qbt_base STATIC bittorrent/sessionimpl.h bittorrent/sessionstatus.h bittorrent/speedmonitor.h - bittorrent/statistics.h bittorrent/torrent.h bittorrent/torrentcontentlayout.h bittorrent/torrentcreatorthread.h @@ -128,7 +127,6 @@ add_library(qbt_base STATIC bittorrent/resumedatastorage.cpp bittorrent/sessionimpl.cpp bittorrent/speedmonitor.cpp - bittorrent/statistics.cpp bittorrent/torrent.cpp bittorrent/torrentcreatorthread.cpp bittorrent/torrentimpl.cpp diff --git a/src/base/base.pri b/src/base/base.pri index 70bb86855..83853344b 100644 --- a/src/base/base.pri +++ b/src/base/base.pri @@ -32,7 +32,6 @@ HEADERS += \ $$PWD/bittorrent/sessionimpl.h \ $$PWD/bittorrent/sessionstatus.h \ $$PWD/bittorrent/speedmonitor.h \ - $$PWD/bittorrent/statistics.h \ $$PWD/bittorrent/torrent.h \ $$PWD/bittorrent/torrentcontentlayout.h \ $$PWD/bittorrent/torrentcreatorthread.h \ @@ -128,7 +127,6 @@ SOURCES += \ $$PWD/bittorrent/resumedatastorage.cpp \ $$PWD/bittorrent/sessionimpl.cpp \ $$PWD/bittorrent/speedmonitor.cpp \ - $$PWD/bittorrent/statistics.cpp \ $$PWD/bittorrent/torrent.cpp \ $$PWD/bittorrent/torrentcreatorthread.cpp \ $$PWD/bittorrent/torrentimpl.cpp \ diff --git a/src/base/bittorrent/session.h b/src/base/bittorrent/session.h index a7e61f449..2f62a7646 100644 --- a/src/base/bittorrent/session.h +++ b/src/base/bittorrent/session.h @@ -404,8 +404,6 @@ namespace BitTorrent virtual bool hasRunningSeed() const = 0; virtual const SessionStatus &status() const = 0; virtual const CacheStatus &cacheStatus() const = 0; - virtual qint64 getAlltimeDL() const = 0; - virtual qint64 getAlltimeUL() const = 0; virtual bool isListening() const = 0; virtual MaxRatioAction maxRatioAction() const = 0; diff --git a/src/base/bittorrent/sessionimpl.cpp b/src/base/bittorrent/sessionimpl.cpp index 609dc7cad..c96b54625 100644 --- a/src/base/bittorrent/sessionimpl.cpp +++ b/src/base/bittorrent/sessionimpl.cpp @@ -106,7 +106,6 @@ #include "nativesessionextension.h" #include "portforwarderimpl.h" #include "resumedatastorage.h" -#include "statistics.h" #include "torrentimpl.h" #include "tracker.h" @@ -115,6 +114,7 @@ using namespace BitTorrent; const Path CATEGORIES_FILE_NAME {u"categories.json"_qs}; const int MAX_PROCESSING_RESUMEDATA_COUNT = 50; +const int STATISTICS_SAVE_INTERVAL = std::chrono::milliseconds(15min).count(); namespace { @@ -493,7 +493,6 @@ SessionImpl::SessionImpl(QObject *parent) , m_resumeDataStorageType(BITTORRENT_SESSION_KEY(u"ResumeDataStorageType"_qs), ResumeDataStorageType::Legacy) , m_seedingLimitTimer {new QTimer {this}} , m_resumeDataTimer {new QTimer {this}} - , m_statistics {new Statistics {this}} , m_ioThread {new QThread {this}} , m_recentErroredTorrentsTimer {new QTimer {this}} #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) @@ -557,6 +556,7 @@ SessionImpl::SessionImpl(QObject *parent) new PortForwarderImpl(m_nativeSession); initMetrics(); + loadStatistics(); prepareStartup(); } @@ -1004,6 +1004,8 @@ void SessionImpl::setGlobalMaxSeedingMinutes(int minutes) // Main destructor SessionImpl::~SessionImpl() { + saveStatistics(); + // Do some BT related saving saveResumeData(); @@ -1372,6 +1374,8 @@ void SessionImpl::endStartup(ResumeSessionContext *context) else enqueueRefresh(); + m_statisticsLastUpdateTimer.start(); + // Regular saving of fastresume data connect(m_resumeDataTimer, &QTimer::timeout, this, &SessionImpl::generateResumeData); const int saveInterval = saveResumeDataInterval(); @@ -4893,16 +4897,6 @@ const CacheStatus &SessionImpl::cacheStatus() const return m_cacheStatus; } -qint64 SessionImpl::getAlltimeDL() const -{ - return m_statistics->getAlltimeDL(); -} - -qint64 SessionImpl::getAlltimeUL() const -{ - return m_statistics->getAlltimeUL(); -} - void SessionImpl::enqueueRefresh() { Q_ASSERT(!m_refreshEnqueued); @@ -5456,8 +5450,6 @@ void SessionImpl::handleSessionStatsAlert(const lt::session_stats_alert *p) m_status.trackerDownloadRate = calcRate(m_status.trackerDownload, trackerDownload); m_status.trackerUploadRate = calcRate(m_status.trackerUpload, trackerUpload); - m_status.totalDownload = totalDownload; - m_status.totalUpload = totalUpload; m_status.totalPayloadDownload = totalPayloadDownload; m_status.totalPayloadUpload = totalPayloadUpload; m_status.ipOverheadDownload = ipOverheadDownload; @@ -5473,6 +5465,24 @@ void SessionImpl::handleSessionStatsAlert(const lt::session_stats_alert *p) m_status.diskWriteQueue = stats[m_metricIndices.peer.numPeersDownDisk]; m_status.peersCount = stats[m_metricIndices.peer.numPeersConnected]; + if (totalDownload > m_status.totalDownload) + { + m_status.totalDownload = totalDownload; + m_isStatisticsDirty = true; + } + + if (totalUpload > m_status.totalUpload) + { + m_status.totalUpload = totalUpload; + m_isStatisticsDirty = true; + } + + m_status.allTimeDownload = m_previouslyDownloaded + m_status.totalDownload; + m_status.allTimeUpload = m_previouslyUploaded + m_status.totalUpload; + + if (m_statisticsLastUpdateTimer.hasExpired(STATISTICS_SAVE_INTERVAL)) + saveStatistics(); + m_cacheStatus.totalUsedBuffers = stats[m_metricIndices.disk.diskBlocksInUse]; m_cacheStatus.jobQueueLength = stats[m_metricIndices.disk.queuedDiskJobs]; @@ -5648,3 +5658,27 @@ void SessionImpl::processTrackerStatuses() m_updatedTrackerEntries.clear(); } } + +void SessionImpl::saveStatistics() const +{ + if (!m_isStatisticsDirty) + return; + + const QVariantHash stats { + {u"AlltimeDL"_qs, m_status.allTimeDownload}, + {u"AlltimeUL"_qs, m_status.allTimeUpload}}; + std::unique_ptr settings = Profile::instance()->applicationSettings(u"qBittorrent-data"_qs); + settings->setValue(u"Stats/AllStats"_qs, stats); + + m_statisticsLastUpdateTimer.start(); + m_isStatisticsDirty = false; +} + +void SessionImpl::loadStatistics() +{ + const std::unique_ptr settings = Profile::instance()->applicationSettings(u"qBittorrent-data"_qs); + const QVariantHash value = settings->value(u"Stats/AllStats"_qs).toHash(); + + m_previouslyDownloaded = value[u"AlltimeDL"_qs].toLongLong(); + m_previouslyUploaded = value[u"AlltimeUL"_qs].toLongLong(); +} diff --git a/src/base/bittorrent/sessionimpl.h b/src/base/bittorrent/sessionimpl.h index 41f43e4c6..1dabf4e3f 100644 --- a/src/base/bittorrent/sessionimpl.h +++ b/src/base/bittorrent/sessionimpl.h @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -72,7 +73,6 @@ class QUrl; class BandwidthScheduler; class FileSearcher; class FilterParserThread; -class Statistics; namespace Net { @@ -384,8 +384,6 @@ namespace BitTorrent bool hasRunningSeed() const override; const SessionStatus &status() const override; const CacheStatus &cacheStatus() const override; - qint64 getAlltimeDL() const override; - qint64 getAlltimeUL() const override; bool isListening() const override; MaxRatioAction maxRatioAction() const override; @@ -550,6 +548,9 @@ namespace BitTorrent void storeCategories() const; void upgradeCategories(); + void saveStatistics() const; + void loadStatistics(); + // BitTorrent lt::session *m_nativeSession = nullptr; @@ -675,10 +676,15 @@ namespace BitTorrent QVector m_additionalTrackerList; QVector m_excludedFileNamesRegExpList; + // Statistics + mutable QElapsedTimer m_statisticsLastUpdateTimer; + mutable bool m_isStatisticsDirty = false; + qint64 m_previouslyUploaded = 0; + qint64 m_previouslyDownloaded = 0; + bool m_refreshEnqueued = false; QTimer *m_seedingLimitTimer = nullptr; QTimer *m_resumeDataTimer = nullptr; - Statistics *m_statistics = nullptr; // IP filtering QPointer m_filterParser; QPointer m_bwScheduler; diff --git a/src/base/bittorrent/sessionstatus.h b/src/base/bittorrent/sessionstatus.h index 58aee588b..9997a24d7 100644 --- a/src/base/bittorrent/sessionstatus.h +++ b/src/base/bittorrent/sessionstatus.h @@ -56,6 +56,8 @@ namespace BitTorrent qint64 trackerUploadRate = 0; qint64 trackerDownloadRate = 0; + qint64 allTimeDownload = 0; + qint64 allTimeUpload = 0; qint64 totalDownload = 0; qint64 totalUpload = 0; qint64 totalPayloadDownload = 0; diff --git a/src/base/bittorrent/statistics.cpp b/src/base/bittorrent/statistics.cpp deleted file mode 100644 index 6712fe08d..000000000 --- a/src/base/bittorrent/statistics.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * In addition, as a special exception, the copyright holders give permission to - * link this program with the OpenSSL project's "OpenSSL" library (or with - * modified versions of it that use the same license as the "OpenSSL" library), - * and distribute the linked executables. You must obey the GNU General Public - * License in all respects for all of the code used other than "OpenSSL". If you - * modify file(s), you may extend this exception to your version of the file(s), - * but you are not obligated to do so. If you do not wish to do so, delete this - * exception statement from your version. - */ - -#include "statistics.h" - -#include - -#include - -#include "base/global.h" -#include "base/bittorrent/sessionimpl.h" -#include "base/bittorrent/sessionstatus.h" -#include "base/profile.h" - -using namespace std::chrono_literals; -using namespace BitTorrent; - -const int SAVE_INTERVAL = std::chrono::milliseconds(15min).count(); - -Statistics::Statistics(BitTorrent::SessionImpl *session) - : QObject(session) - , m_session(session) -{ - load(); - m_lastUpdateTimer.start(); - - auto *timer = new QTimer(this); - connect(timer, &QTimer::timeout, this, &Statistics::gather); - timer->start(60s); -} - -Statistics::~Statistics() -{ - save(); -} - -qint64 Statistics::getAlltimeDL() const -{ - return m_alltimeDL + m_sessionDL; -} - -qint64 Statistics::getAlltimeUL() const -{ - return m_alltimeUL + m_sessionUL; -} - -void Statistics::gather() -{ - const SessionStatus &ss = m_session->status(); - if (ss.totalDownload > m_sessionDL) - { - m_sessionDL = ss.totalDownload; - m_dirty = true; - } - if (ss.totalUpload > m_sessionUL) - { - m_sessionUL = ss.totalUpload; - m_dirty = true; - } - - if (m_lastUpdateTimer.hasExpired(SAVE_INTERVAL)) - save(); -} - -void Statistics::save() const -{ - if (!m_dirty) - return; - - const QVariantHash stats = - { - {u"AlltimeDL"_qs, (m_alltimeDL + m_sessionDL)}, - {u"AlltimeUL"_qs, (m_alltimeUL + m_sessionUL)} - }; - std::unique_ptr settings = Profile::instance()->applicationSettings(u"qBittorrent-data"_qs); - settings->setValue(u"Stats/AllStats"_qs, stats); - - m_lastUpdateTimer.start(); - m_dirty = false; -} - -void Statistics::load() -{ - const std::unique_ptr s = Profile::instance()->applicationSettings(u"qBittorrent-data"_qs); - const QVariantHash v = s->value(u"Stats/AllStats"_qs).toHash(); - - m_alltimeDL = v[u"AlltimeDL"_qs].toLongLong(); - m_alltimeUL = v[u"AlltimeUL"_qs].toLongLong(); -} diff --git a/src/base/bittorrent/statistics.h b/src/base/bittorrent/statistics.h deleted file mode 100644 index 0107a10b1..000000000 --- a/src/base/bittorrent/statistics.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * In addition, as a special exception, the copyright holders give permission to - * link this program with the OpenSSL project's "OpenSSL" library (or with - * modified versions of it that use the same license as the "OpenSSL" library), - * and distribute the linked executables. You must obey the GNU General Public - * License in all respects for all of the code used other than "OpenSSL". If you - * modify file(s), you may extend this exception to your version of the file(s), - * but you are not obligated to do so. If you do not wish to do so, delete this - * exception statement from your version. - */ - -#pragma once - -#include -#include - -namespace BitTorrent -{ - class SessionImpl; -} - -class Statistics : public QObject -{ - Q_OBJECT - Q_DISABLE_COPY_MOVE(Statistics) - -public: - explicit Statistics(BitTorrent::SessionImpl *session); - ~Statistics(); - - qint64 getAlltimeDL() const; - qint64 getAlltimeUL() const; - -private slots: - void gather(); - -private: - void save() const; - void load(); - - BitTorrent::SessionImpl *m_session = nullptr; - mutable QElapsedTimer m_lastUpdateTimer; - mutable bool m_dirty = false; - - qint64 m_alltimeUL = 0; - qint64 m_alltimeDL = 0; - qint64 m_sessionUL = 0; - qint64 m_sessionDL = 0; -}; diff --git a/src/gui/statsdialog.cpp b/src/gui/statsdialog.cpp index d0fcc9aab..5be0a4b8b 100644 --- a/src/gui/statsdialog.cpp +++ b/src/gui/statsdialog.cpp @@ -76,8 +76,8 @@ void StatsDialog::update() const BitTorrent::CacheStatus &cs = BitTorrent::Session::instance()->cacheStatus(); // All-time DL/UL - const qint64 atd = BitTorrent::Session::instance()->getAlltimeDL(); - const qint64 atu = BitTorrent::Session::instance()->getAlltimeUL(); + const qint64 atd = ss.allTimeDownload; + const qint64 atu = ss.allTimeUpload; m_ui->labelAlltimeDL->setText(Utils::Misc::friendlyUnit(atd)); m_ui->labelAlltimeUL->setText(Utils::Misc::friendlyUnit(atu)); // Total waste (this session) diff --git a/src/webui/api/synccontroller.cpp b/src/webui/api/synccontroller.cpp index 92c3bdc0b..173280c6e 100644 --- a/src/webui/api/synccontroller.cpp +++ b/src/webui/api/synccontroller.cpp @@ -129,8 +129,8 @@ namespace map[KEY_TRANSFER_DLRATELIMIT] = session->downloadSpeedLimit(); map[KEY_TRANSFER_UPRATELIMIT] = session->uploadSpeedLimit(); - const qint64 atd = session->getAlltimeDL(); - const qint64 atu = session->getAlltimeUL(); + const qint64 atd = sessionStatus.allTimeDownload; + const qint64 atu = sessionStatus.allTimeUpload; map[KEY_TRANSFER_ALLTIME_DL] = atd; map[KEY_TRANSFER_ALLTIME_UL] = atu; map[KEY_TRANSFER_TOTAL_WASTE_SESSION] = sessionStatus.totalWasted;