diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index 38154e98a..5d2f9cf0e 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 000000000..1dd65eea7 --- /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 c498b46f0..4deb2b3ed 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 @@ -58,6 +57,7 @@ #include #include +#include #include #include #include @@ -106,6 +106,7 @@ #include "torrentimpl.h" #include "tracker.h" #include "trackerentry.h" +#include "trackerentrystatus.h" using namespace std::chrono_literals; using namespace BitTorrent; @@ -1603,8 +1604,8 @@ 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(); @@ -1612,7 +1613,7 @@ void SessionImpl::endStartup(ResumeSessionContext *context) m_wakeupCheckTimestamp = now; }); - m_wakeupCheckTimestamp = QDateTime::currentDateTime(); + m_wakeupCheckTimestamp = std::chrono::steady_clock::now(); m_wakeupCheckTimer->start(30s); m_isRestored = true; @@ -5512,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_qNow = QDateTime::currentDateTime(); - const std::vector alerts = getPendingAlerts(); Q_ASSERT(m_loadedTorrents.isEmpty()); @@ -6395,9 +6391,3 @@ void SessionImpl::handleRemovedTorrent(const TorrentID &torrentID, const QString m_removingTorrents.erase(removingTorrentDataIter); } - -QDateTime SessionImpl::fromLTTimePoint32(const lt::time_point32 &timePoint) const -{ - const auto secsSinceNow = lt::duration_cast(timePoint - m_ltNow + lt::milliseconds(500)).count(); - return m_qNow.addSecs(secsSinceNow); -} diff --git a/src/base/bittorrent/sessionimpl.h b/src/base/bittorrent/sessionimpl.h index 83f36e668..8136a4749 100644 --- a/src/base/bittorrent/sessionimpl.h +++ b/src/base/bittorrent/sessionimpl.h @@ -29,6 +29,7 @@ #pragma once +#include #include #include @@ -37,7 +38,6 @@ #include #include -#include #include #include #include @@ -55,7 +55,6 @@ #include "session.h" #include "sessionstatus.h" #include "torrentinfo.h" -#include "trackerentrystatus.h" class QString; class QTimer; @@ -479,8 +478,6 @@ namespace BitTorrent void addMappedPorts(const QSet &ports); void removeMappedPorts(const QSet &ports); - QDateTime fromLTTimePoint32(const lt::time_point32 &timePoint) const; - template void invoke(Func &&func) { @@ -828,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; - QDateTime m_qNow; - 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 5c8ae4dc8..5a2b6aac9 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 FromLTTimePoint32Func &fromLTTimePoint32) + , 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 = fromLTTimePoint32(ltAnnounceInfo.next_announce); - trackerEndpointStatus.minAnnounceTime = fromLTTimePoint32(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 = QDateTime(); - trackerEntryStatus.minAnnounceTime = QDateTime(); + 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.isValid() || (trackerEntryStatus.nextAnnounceTime > endpointStatus.nextAnnounceTime)) + if ((trackerEntryStatus.nextAnnounceTime == AnnounceTimePoint()) || (trackerEntryStatus.nextAnnounceTime > endpointStatus.nextAnnounceTime)) { trackerEntryStatus.nextAnnounceTime = endpointStatus.nextAnnounceTime; trackerEntryStatus.minAnnounceTime = endpointStatus.minAnnounceTime; @@ -1774,11 +1772,7 @@ TrackerEntryStatus TorrentImpl::updateTrackerEntryStatus(const lt::announce_entr const QSet btProtocols {1}; #endif - const auto fromLTTimePoint32 = [this](const lt::time_point32 &timePoint) - { - return m_session->fromLTTimePoint32(timePoint); - }; - ::updateTrackerEntryStatus(*it, announceEntry, btProtocols, updateInfo, fromLTTimePoint32); + ::updateTrackerEntryStatus(*it, announceEntry, btProtocols, updateInfo); return *it; } diff --git a/src/base/bittorrent/trackerentrystatus.h b/src/base/bittorrent/trackerentrystatus.h index 1f271d41a..fa5998a58 100644 --- a/src/base/bittorrent/trackerentrystatus.h +++ b/src/base/bittorrent/trackerentrystatus.h @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015-2023 Vladimir Golovnev + * Copyright (C) 2015-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 @@ -28,10 +28,11 @@ #pragma once -#include #include #include +#include "announcetimepoint.h" + class QStringView; namespace BitTorrent @@ -59,8 +60,8 @@ namespace BitTorrent int numLeeches = -1; int numDownloaded = -1; - QDateTime nextAnnounceTime {}; - QDateTime minAnnounceTime {}; + AnnounceTimePoint nextAnnounceTime {}; + AnnounceTimePoint minAnnounceTime {}; }; struct TrackerEntryStatus @@ -76,8 +77,8 @@ namespace BitTorrent int numLeeches = -1; int numDownloaded = -1; - QDateTime nextAnnounceTime {}; - QDateTime minAnnounceTime {}; + AnnounceTimePoint nextAnnounceTime {}; + AnnounceTimePoint minAnnounceTime {}; QHash, TrackerEndpointStatus> endpoints {}; diff --git a/src/gui/trackerlist/trackerlistmodel.cpp b/src/gui/trackerlist/trackerlistmodel.cpp index 0d0b8fdf7..78465488c 100644 --- a/src/gui/trackerlist/trackerlistmodel.cpp +++ b/src/gui/trackerlist/trackerlistmodel.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2023 Vladimir Golovnev + * Copyright (C) 2023-2024 Vladimir Golovnev * Copyright (C) 2006 Christophe Dumez * * This program is free software; you can redistribute it and/or @@ -29,6 +29,7 @@ #include "trackerlistmodel.h" +#include #include #include @@ -40,11 +41,13 @@ #include #include +#include #include #include #include #include +#include "base/bittorrent/announcetimepoint.h" #include "base/bittorrent/peerinfo.h" #include "base/bittorrent/session.h" #include "base/bittorrent/torrent.h" @@ -141,12 +144,12 @@ struct TrackerListModel::Item final int numLeeches = -1; int numDownloaded = -1; - QDateTime nextAnnounceTime {}; - QDateTime minAnnounceTime {}; + BitTorrent::AnnounceTimePoint nextAnnounceTime; + BitTorrent::AnnounceTimePoint minAnnounceTime; qint64 secsToNextAnnounce = 0; qint64 secsToMinAnnounce = 0; - QDateTime announceTimestamp; + BitTorrent::AnnounceTimePoint announceTimestamp; std::weak_ptr parentItem {}; @@ -211,7 +214,7 @@ void TrackerListModel::Item::fillFrom(const BitTorrent::TrackerEntryStatus &trac minAnnounceTime = trackerEntryStatus.minAnnounceTime; secsToNextAnnounce = 0; secsToMinAnnounce = 0; - announceTimestamp = QDateTime(); + announceTimestamp = {}; } void TrackerListModel::Item::fillFrom(const BitTorrent::TrackerEndpointStatus &endpointStatus) @@ -230,7 +233,7 @@ void TrackerListModel::Item::fillFrom(const BitTorrent::TrackerEndpointStatus &e minAnnounceTime = endpointStatus.minAnnounceTime; secsToNextAnnounce = 0; secsToMinAnnounce = 0; - announceTimestamp = QDateTime(); + announceTimestamp = {}; } TrackerListModel::TrackerListModel(BitTorrent::Session *btSession, QObject *parent) @@ -369,7 +372,7 @@ void TrackerListModel::populate() for (const BitTorrent::TrackerEntryStatus &status : trackers) addTrackerItem(status); - m_announceTimestamp = QDateTime::currentDateTime(); + m_announceTimestamp = BitTorrent::AnnounceTimePoint::clock::now(); m_announceRefreshTimer->start(ANNOUNCE_TIME_REFRESH_INTERVAL); } @@ -448,7 +451,7 @@ void TrackerListModel::refreshAnnounceTimes() if (!m_torrent) return; - m_announceTimestamp = QDateTime::currentDateTime(); + 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) { @@ -545,8 +548,12 @@ QVariant TrackerListModel::data(const QModelIndex &index, const int role) const if (itemPtr->announceTimestamp != m_announceTimestamp) { - itemPtr->secsToNextAnnounce = std::max(0, m_announceTimestamp.secsTo(itemPtr->nextAnnounceTime)); - itemPtr->secsToMinAnnounce = std::max(0, m_announceTimestamp.secsTo(itemPtr->minAnnounceTime)); + 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 9a633bf8e..523f894b5 100644 --- a/src/gui/trackerlist/trackerlistmodel.h +++ b/src/gui/trackerlist/trackerlistmodel.h @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2023 Vladimir Golovnev + * Copyright (C) 2023-2024 Vladimir Golovnev * Copyright (C) 2006 Christophe Dumez * * This program is free software; you can redistribute it and/or @@ -33,8 +33,8 @@ #include #include -#include +#include "base/bittorrent/announcetimepoint.h" #include "base/bittorrent/trackerentrystatus.h" class QTimer; @@ -115,6 +115,6 @@ private: class Items; std::unique_ptr m_items; - QDateTime m_announceTimestamp; + BitTorrent::AnnounceTimePoint m_announceTimestamp; QTimer *m_announceRefreshTimer = nullptr; };