diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index 38154e98a7aa..5d2f9cf0e3be 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(qbt_base STATIC asyncfilestorage.h bittorrent/abstractfilestorage.h bittorrent/addtorrentparams.h + bittorrent/announcetimepoint.h bittorrent/bandwidthscheduler.h bittorrent/bencoderesumedatastorage.h bittorrent/cachestatus.h diff --git a/src/base/bittorrent/announcetimepoint.h b/src/base/bittorrent/announcetimepoint.h new file mode 100644 index 000000000000..1dd65eea72e4 --- /dev/null +++ b/src/base/bittorrent/announcetimepoint.h @@ -0,0 +1,36 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2024 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 + +namespace BitTorrent +{ + using AnnounceTimePoint = std::chrono::high_resolution_clock::time_point; +} diff --git a/src/base/bittorrent/sessionimpl.cpp b/src/base/bittorrent/sessionimpl.cpp index cd93b7103f00..4deb2b3ed145 100644 --- a/src/base/bittorrent/sessionimpl.cpp +++ b/src/base/bittorrent/sessionimpl.cpp @@ -30,7 +30,6 @@ #include "sessionimpl.h" #include -#include #include #include #include @@ -1605,16 +1604,16 @@ void SessionImpl::endStartup(ResumeSessionContext *context) m_wakeupCheckTimer = new QTimer(this); connect(m_wakeupCheckTimer, &QTimer::timeout, this, [this] { - const auto now = QDateTime::currentDateTime(); - if (m_wakeupCheckTimestamp.secsTo(now) > 100) + const auto now = std::chrono::steady_clock::now(); + if ((now - m_wakeupCheckTimestamp) > 100s) { LogMsg(tr("System wake-up event detected. Re-announcing to all the trackers...")); reannounceToAllTrackers(); } - m_wakeupCheckTimestamp = QDateTime::currentDateTime(); + m_wakeupCheckTimestamp = now; }); - m_wakeupCheckTimestamp = QDateTime::currentDateTime(); + m_wakeupCheckTimestamp = std::chrono::steady_clock::now(); m_wakeupCheckTimer->start(30s); m_isRestored = true; @@ -5514,11 +5513,6 @@ void SessionImpl::setTorrentContentLayout(const TorrentContentLayout value) // Read alerts sent by libtorrent session void SessionImpl::readAlerts() { - // cache current datetime of Qt and libtorrent clocks in order - // to optimize conversion of time points from lt to Qt clocks - m_ltNow = lt::clock_type::now(); - m_currentSecsSinceEpoch = QDateTime::currentSecsSinceEpoch(); - const std::vector alerts = getPendingAlerts(); Q_ASSERT(m_loadedTorrents.isEmpty()); @@ -6397,9 +6391,3 @@ void SessionImpl::handleRemovedTorrent(const TorrentID &torrentID, const QString m_removingTorrents.erase(removingTorrentDataIter); } - -qint64 SessionImpl::toSecsSinceEpoch(const lt::time_point32 &timePoint) const -{ - const auto secsSinceNow = lt::duration_cast(timePoint - m_ltNow + lt::milliseconds(500)).count(); - return m_currentSecsSinceEpoch + secsSinceNow; -} diff --git a/src/base/bittorrent/sessionimpl.h b/src/base/bittorrent/sessionimpl.h index 0d603e827399..8136a4749ec3 100644 --- a/src/base/bittorrent/sessionimpl.h +++ b/src/base/bittorrent/sessionimpl.h @@ -29,6 +29,7 @@ #pragma once +#include #include #include @@ -477,8 +478,6 @@ namespace BitTorrent void addMappedPorts(const QSet &ports); void removeMappedPorts(const QSet &ports); - qint64 toSecsSinceEpoch(const lt::time_point32 &timePoint) const; - template void invoke(Func &&func) { @@ -826,13 +825,10 @@ namespace BitTorrent QHash> m_mappedPorts; QTimer *m_wakeupCheckTimer = nullptr; - QDateTime m_wakeupCheckTimestamp; + std::chrono::steady_clock::time_point m_wakeupCheckTimestamp; QList m_pendingFinishedTorrents; - qint64 m_currentSecsSinceEpoch = 0; - lt::clock_type::time_point m_ltNow; - friend void Session::initInstance(); friend void Session::freeInstance(); friend Session *Session::instance(); diff --git a/src/base/bittorrent/torrentimpl.cpp b/src/base/bittorrent/torrentimpl.cpp index a061356ab179..5eb417c93c6e 100644 --- a/src/base/bittorrent/torrentimpl.cpp +++ b/src/base/bittorrent/torrentimpl.cpp @@ -106,10 +106,8 @@ namespace return endpointName; } - template void updateTrackerEntryStatus(TrackerEntryStatus &trackerEntryStatus, const lt::announce_entry &nativeEntry - , const QSet &btProtocols, const QHash> &updateInfo - , const ToSecsSinceEpochFunc &toSecsSinceEpoch) + , const QSet &btProtocols, const QHash> &updateInfo) { Q_ASSERT(trackerEntryStatus.url == QString::fromStdString(nativeEntry.url)); @@ -146,8 +144,8 @@ namespace trackerEndpointStatus.numSeeds = ltAnnounceInfo.scrape_complete; trackerEndpointStatus.numLeeches = ltAnnounceInfo.scrape_incomplete; trackerEndpointStatus.numDownloaded = ltAnnounceInfo.scrape_downloaded; - trackerEndpointStatus.nextAnnounceTime = toSecsSinceEpoch(ltAnnounceInfo.next_announce); - trackerEndpointStatus.minAnnounceTime = toSecsSinceEpoch(ltAnnounceInfo.min_announce); + trackerEndpointStatus.nextAnnounceTime = ltAnnounceInfo.next_announce; + trackerEndpointStatus.minAnnounceTime = ltAnnounceInfo.min_announce; if (ltAnnounceInfo.updating) { @@ -238,8 +236,8 @@ namespace trackerEntryStatus.numSeeds = -1; trackerEntryStatus.numLeeches = -1; trackerEntryStatus.numDownloaded = -1; - trackerEntryStatus.nextAnnounceTime = 0; - trackerEntryStatus.minAnnounceTime = 0; + trackerEntryStatus.nextAnnounceTime = {}; + trackerEntryStatus.minAnnounceTime = {}; trackerEntryStatus.message.clear(); for (const TrackerEndpointStatus &endpointStatus : asConst(trackerEntryStatus.endpoints)) @@ -251,7 +249,7 @@ namespace if (endpointStatus.state == trackerEntryStatus.state) { - if ((trackerEntryStatus.nextAnnounceTime <= 0) || (trackerEntryStatus.nextAnnounceTime > endpointStatus.nextAnnounceTime)) + if ((trackerEntryStatus.nextAnnounceTime == AnnounceTimePoint()) || (trackerEntryStatus.nextAnnounceTime > endpointStatus.nextAnnounceTime)) { trackerEntryStatus.nextAnnounceTime = endpointStatus.nextAnnounceTime; trackerEntryStatus.minAnnounceTime = endpointStatus.minAnnounceTime; @@ -1777,11 +1775,7 @@ TrackerEntryStatus TorrentImpl::updateTrackerEntryStatus(const lt::announce_entr const QSet btProtocols {1}; #endif - const auto toSecsSinceEpoch = [this](const lt::time_point32 &timePoint) - { - return m_session->toSecsSinceEpoch(timePoint); - }; - ::updateTrackerEntryStatus(*it, announceEntry, btProtocols, updateInfo, toSecsSinceEpoch); + ::updateTrackerEntryStatus(*it, announceEntry, btProtocols, updateInfo); return *it; } diff --git a/src/base/bittorrent/trackerentrystatus.h b/src/base/bittorrent/trackerentrystatus.h index 792ce303a39f..fa5998a58737 100644 --- a/src/base/bittorrent/trackerentrystatus.h +++ b/src/base/bittorrent/trackerentrystatus.h @@ -31,6 +31,8 @@ #include #include +#include "announcetimepoint.h" + class QStringView; namespace BitTorrent @@ -58,8 +60,8 @@ namespace BitTorrent int numLeeches = -1; int numDownloaded = -1; - qint64 nextAnnounceTime = 0; - qint64 minAnnounceTime = 0; + AnnounceTimePoint nextAnnounceTime {}; + AnnounceTimePoint minAnnounceTime {}; }; struct TrackerEntryStatus @@ -75,8 +77,8 @@ namespace BitTorrent int numLeeches = -1; int numDownloaded = -1; - qint64 nextAnnounceTime = 0; - qint64 minAnnounceTime = 0; + AnnounceTimePoint nextAnnounceTime {}; + AnnounceTimePoint minAnnounceTime {}; QHash, TrackerEndpointStatus> endpoints {}; diff --git a/src/gui/trackerlist/trackerlistmodel.cpp b/src/gui/trackerlist/trackerlistmodel.cpp index 5d1608cddb5d..78465488c312 100644 --- a/src/gui/trackerlist/trackerlistmodel.cpp +++ b/src/gui/trackerlist/trackerlistmodel.cpp @@ -29,6 +29,7 @@ #include "trackerlistmodel.h" +#include #include #include @@ -46,6 +47,7 @@ #include #include +#include "base/bittorrent/announcetimepoint.h" #include "base/bittorrent/peerinfo.h" #include "base/bittorrent/session.h" #include "base/bittorrent/torrent.h" @@ -142,12 +144,12 @@ struct TrackerListModel::Item final int numLeeches = -1; int numDownloaded = -1; - qint64 nextAnnounceTime = 0; - qint64 minAnnounceTime = 0; + BitTorrent::AnnounceTimePoint nextAnnounceTime; + BitTorrent::AnnounceTimePoint minAnnounceTime; qint64 secsToNextAnnounce = 0; qint64 secsToMinAnnounce = 0; - qint64 announceTimestamp = 0; + BitTorrent::AnnounceTimePoint announceTimestamp; std::weak_ptr parentItem {}; @@ -212,7 +214,7 @@ void TrackerListModel::Item::fillFrom(const BitTorrent::TrackerEntryStatus &trac minAnnounceTime = trackerEntryStatus.minAnnounceTime; secsToNextAnnounce = 0; secsToMinAnnounce = 0; - announceTimestamp = 0; + announceTimestamp = {}; } void TrackerListModel::Item::fillFrom(const BitTorrent::TrackerEndpointStatus &endpointStatus) @@ -231,7 +233,7 @@ void TrackerListModel::Item::fillFrom(const BitTorrent::TrackerEndpointStatus &e minAnnounceTime = endpointStatus.minAnnounceTime; secsToNextAnnounce = 0; secsToMinAnnounce = 0; - announceTimestamp = 0; + announceTimestamp = {}; } TrackerListModel::TrackerListModel(BitTorrent::Session *btSession, QObject *parent) @@ -370,7 +372,7 @@ void TrackerListModel::populate() for (const BitTorrent::TrackerEntryStatus &status : trackers) addTrackerItem(status); - m_announceTimestamp = QDateTime::currentSecsSinceEpoch(); + m_announceTimestamp = BitTorrent::AnnounceTimePoint::clock::now(); m_announceRefreshTimer->start(ANNOUNCE_TIME_REFRESH_INTERVAL); } @@ -449,7 +451,7 @@ void TrackerListModel::refreshAnnounceTimes() if (!m_torrent) return; - m_announceTimestamp = QDateTime::currentSecsSinceEpoch(); + m_announceTimestamp = BitTorrent::AnnounceTimePoint::clock::now(); emit dataChanged(index(0, COL_NEXT_ANNOUNCE), index((rowCount() - 1), COL_MIN_ANNOUNCE)); for (int i = 0; i < rowCount(); ++i) { @@ -546,8 +548,12 @@ QVariant TrackerListModel::data(const QModelIndex &index, const int role) const if (itemPtr->announceTimestamp != m_announceTimestamp) { - itemPtr->secsToNextAnnounce = std::max(0, (itemPtr->nextAnnounceTime - m_announceTimestamp)); - itemPtr->secsToMinAnnounce = std::max(0, (itemPtr->minAnnounceTime - m_announceTimestamp)); + const auto timeToNextAnnounce = std::chrono::duration_cast(itemPtr->nextAnnounceTime - m_announceTimestamp); + itemPtr->secsToNextAnnounce = std::max(0, timeToNextAnnounce.count()); + + const auto timeToMinAnnounce = std::chrono::duration_cast(itemPtr->minAnnounceTime - m_announceTimestamp); + itemPtr->secsToMinAnnounce = std::max(0, timeToMinAnnounce.count()); + itemPtr->announceTimestamp = m_announceTimestamp; } diff --git a/src/gui/trackerlist/trackerlistmodel.h b/src/gui/trackerlist/trackerlistmodel.h index ce9669b8923b..523f894b5c7c 100644 --- a/src/gui/trackerlist/trackerlistmodel.h +++ b/src/gui/trackerlist/trackerlistmodel.h @@ -34,6 +34,7 @@ #include #include +#include "base/bittorrent/announcetimepoint.h" #include "base/bittorrent/trackerentrystatus.h" class QTimer; @@ -114,6 +115,6 @@ class TrackerListModel final : public QAbstractItemModel class Items; std::unique_ptr m_items; - qint64 m_announceTimestamp = 0; + BitTorrent::AnnounceTimePoint m_announceTimestamp; QTimer *m_announceRefreshTimer = nullptr; };