From f8c544397a3237900fa5bfff76402c7ee7f28e7a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 15 Nov 2023 18:53:43 -0600 Subject: [PATCH] refactor: add private helper class CumulativeCount (#6260) * refactor: CumulativeCounts helper class * refactor: add private CumulativeCounts helper class for tr_torrent --- libtransmission/peer-mgr.cc | 4 +-- libtransmission/resume.cc | 14 +++++----- libtransmission/session.cc | 4 +-- libtransmission/torrent.cc | 32 ++++++++++------------ libtransmission/torrent.h | 54 ++++++++++++++++++++++++++++++++----- 5 files changed, 72 insertions(+), 36 deletions(-) diff --git a/libtransmission/peer-mgr.cc b/libtransmission/peer-mgr.cc index fdf9bc9d4..d88234474 100644 --- a/libtransmission/peer-mgr.cc +++ b/libtransmission/peer-mgr.cc @@ -481,7 +481,7 @@ public: auto const now = tr_time(); auto* const tor = s->tor; - tor->uploadedCur += event.length; + tor->bytes_uploaded_ += event.length; tr_announcerAddBytes(tor, TR_ANN_UP, event.length); tor->set_date_active(now); tor->set_dirty(); @@ -795,7 +795,7 @@ private: static void on_client_got_piece_data(tr_torrent* const tor, uint32_t const sent_length, time_t const now) { - tor->downloadedCur += sent_length; + tor->bytes_downloaded_ += sent_length; tor->set_date_active(now); tor->set_dirty(); tor->session->add_downloaded(sent_length); diff --git a/libtransmission/resume.cc b/libtransmission/resume.cc index 7acb51c2a..c0c015301 100644 --- a/libtransmission/resume.cc +++ b/libtransmission/resume.cc @@ -654,7 +654,7 @@ tr_resume::fields_t loadFromFile(tr_torrent* tor, tr_resume::fields_t fields_to_ if ((fields_to_load & tr_resume::Corrupt) != 0 && tr_variantDictFindInt(&top, TR_KEY_corrupt, &i)) { - tor->corruptPrev = i; + tor->bytes_corrupt_.set_prev(i); fields_loaded |= tr_resume::Corrupt; } @@ -686,13 +686,13 @@ tr_resume::fields_t loadFromFile(tr_torrent* tor, tr_resume::fields_t fields_to_ if ((fields_to_load & tr_resume::Downloaded) != 0 && tr_variantDictFindInt(&top, TR_KEY_downloaded, &i)) { - tor->downloadedPrev = i; + tor->bytes_downloaded_.set_prev(i); fields_loaded |= tr_resume::Downloaded; } if ((fields_to_load & tr_resume::Uploaded) != 0 && tr_variantDictFindInt(&top, TR_KEY_uploaded, &i)) { - tor->uploadedPrev = i; + tor->bytes_uploaded_.set_prev(i); fields_loaded |= tr_resume::Uploaded; } @@ -871,7 +871,7 @@ fields_t load(tr_torrent* tor, fields_t fields_to_load, tr_ctor const* ctor) return ret; } -void save(tr_torrent* tor) +void save(tr_torrent* const tor) { if (!tr_isTorrent(tor)) { @@ -885,7 +885,7 @@ void save(tr_torrent* tor) tr_variantDictAddInt(&top, TR_KEY_downloading_time_seconds, tor->seconds_downloading(now)); tr_variantDictAddInt(&top, TR_KEY_activity_date, tor->activityDate); tr_variantDictAddInt(&top, TR_KEY_added_date, tor->addedDate); - tr_variantDictAddInt(&top, TR_KEY_corrupt, tor->corruptPrev + tor->corruptCur); + tr_variantDictAddInt(&top, TR_KEY_corrupt, tor->bytes_corrupt_.ever()); tr_variantDictAddInt(&top, TR_KEY_done_date, tor->doneDate); tr_variantDictAddStrView(&top, TR_KEY_destination, tor->download_dir().sv()); @@ -894,8 +894,8 @@ void save(tr_torrent* tor) tr_variantDictAddStrView(&top, TR_KEY_incomplete_dir, tor->incomplete_dir().sv()); } - tr_variantDictAddInt(&top, TR_KEY_downloaded, tor->downloadedPrev + tor->downloadedCur); - tr_variantDictAddInt(&top, TR_KEY_uploaded, tor->uploadedPrev + tor->uploadedCur); + tr_variantDictAddInt(&top, TR_KEY_downloaded, tor->bytes_downloaded_.ever()); + tr_variantDictAddInt(&top, TR_KEY_uploaded, tor->bytes_uploaded_.ever()); tr_variantDictAddInt(&top, TR_KEY_max_peers, tor->peer_limit()); tr_variantDictAddInt(&top, TR_KEY_bandwidth_priority, tor->get_priority()); tr_variantDictAddBool(&top, TR_KEY_paused, !tor->start_when_stable); diff --git a/libtransmission/session.cc b/libtransmission/session.cc index 28993eb78..b693b50f3 100644 --- a/libtransmission/session.cc +++ b/libtransmission/session.cc @@ -1346,8 +1346,8 @@ void tr_session::closeImplPart1(std::promise* closed_promise, std::chrono: std::end(torrents), [](auto const* a, auto const* b) { - auto const a_cur = a->downloadedCur + a->uploadedCur; - auto const b_cur = b->downloadedCur + b->uploadedCur; + auto const a_cur = a->bytes_downloaded_.ever(); + auto const b_cur = b->bytes_downloaded_.ever(); return a_cur > b_cur; // larger xfers go first }); for (auto* tor : torrents) diff --git a/libtransmission/torrent.cc b/libtransmission/torrent.cc index b7591b9be..f160e659b 100644 --- a/libtransmission/torrent.cc +++ b/libtransmission/torrent.cc @@ -173,7 +173,7 @@ bool tr_torrentGetSeedRatioBytes(tr_torrent const* tor, uint64_t* setme_left, ui if (auto const seed_ratio = tor->effective_seed_ratio(); seed_ratio) { - auto const uploaded = tor->uploadedCur + tor->uploadedPrev; + auto const uploaded = tor->bytes_uploaded_.ever(); auto const baseline = tor->size_when_done(); auto const goal = baseline * *seed_ratio; @@ -374,7 +374,7 @@ void torrentCallScript(tr_torrent const* tor, std::string const& script) auto const id_str = std::to_string(tr_torrentId(tor)); auto const labels_str = build_labels_string(tor->labels()); auto const trackers_str = buildTrackersString(tor); - auto const bytes_downloaded_str = std::to_string(tor->downloadedCur + tor->downloadedPrev); + auto const bytes_downloaded_str = std::to_string(tor->bytes_downloaded_.ever()); auto const localtime_str = fmt::format("{:%a %b %d %T %Y%n}", fmt::localtime(tr_time())); auto const env = std::map{ @@ -615,12 +615,9 @@ void torrentResetTransferStats(tr_torrent* tor) { auto const lock = tor->unique_lock(); - tor->downloadedPrev += tor->downloadedCur; - tor->downloadedCur = 0; - tor->uploadedPrev += tor->uploadedCur; - tor->uploadedCur = 0; - tor->corruptPrev += tor->corruptCur; - tor->corruptCur = 0; + tor->bytes_uploaded_.start_new_session(); + tor->bytes_downloaded_.start_new_session(); + tor->bytes_corrupt_.start_new_session(); tor->set_dirty(); } @@ -980,8 +977,8 @@ void tr_torrent::init(tr_ctor const* const ctor) session->addTorrent(this); - TR_ASSERT(downloadedCur == 0); - TR_ASSERT(uploadedCur == 0); + TR_ASSERT(bytes_downloaded_.during_this_session() == 0U); + TR_ASSERT(bytes_uploaded_.during_this_session() == 0); mark_changed(); @@ -1371,9 +1368,9 @@ tr_stat tr_torrent::stats() const stats.secondsSeeding = this->seconds_seeding(now_sec); stats.secondsDownloading = this->seconds_downloading(now_sec); - stats.corruptEver = this->corruptCur + this->corruptPrev; - stats.downloadedEver = this->downloadedCur + this->downloadedPrev; - stats.uploadedEver = this->uploadedCur + this->uploadedPrev; + stats.corruptEver = this->bytes_corrupt_.ever(); + stats.downloadedEver = this->bytes_downloaded_.ever(); + stats.uploadedEver = this->bytes_uploaded_.ever(); stats.haveValid = this->completion.has_valid(); stats.haveUnchecked = this->has_total() - stats.haveValid; stats.desiredAvailable = tr_peerMgrGetDesiredAvailable(this); @@ -1773,7 +1770,7 @@ void tr_torrent::recheck_completeness() if (new_completeness != completeness) { - bool const recent_change = downloadedCur != 0; + bool const recent_change = bytes_downloaded_.during_this_session() != 0U; bool const was_running = is_running(); if (recent_change) @@ -2203,8 +2200,8 @@ void onPieceFailed(tr_torrent* tor, tr_piece_index_t piece) tr_logAddDebugTor(tor, fmt::format("Piece {}, which was just downloaded, failed its checksum test", piece)); auto const n = tor->piece_size(piece); - tor->corruptCur += n; - tor->downloadedCur -= std::min(tor->downloadedCur, uint64_t{ n }); + tor->bytes_corrupt_ += n; + tor->bytes_downloaded_.reduce(n); tor->got_bad_piece_.emit(tor, piece); tor->set_has_piece(piece, false); } @@ -2221,8 +2218,7 @@ void tr_torrentGotBlock(tr_torrent* tor, tr_block_index_t block) if (tor->has_block(block)) { tr_logAddDebugTor(tor, "we have this block already..."); - auto const n = tor->block_size(block); - tor->downloadedCur -= std::min(tor->downloadedCur, uint64_t{ n }); + tor->bytes_downloaded_.reduce(tor->block_size(block)); return; } diff --git a/libtransmission/torrent.h b/libtransmission/torrent.h index 69ea83e50..ce6e2afe2 100644 --- a/libtransmission/torrent.h +++ b/libtransmission/torrent.h @@ -78,8 +78,49 @@ struct tr_torrent final : public tr_completion::torrent_view { using Speed = libtransmission::Values::Speed; + class CumulativeCount + { + public: + [[nodiscard]] constexpr auto start_new_session() noexcept + { + prev_ += cur_; + cur_ = {}; + } + + [[nodiscard]] constexpr auto during_this_session() const noexcept + { + return cur_; + } + + [[nodiscard]] constexpr auto ever() const noexcept + { + return cur_ + prev_; + } + + constexpr auto& operator+=(uint64_t count) noexcept + { + cur_ += count; + return *this; + } + + constexpr void reduce(uint64_t count) // subtract w/underflow guard + { + cur_ = cur_ >= count ? cur_ - count : 0U; + } + + constexpr void set_prev(uint64_t count) noexcept + { + prev_ = count; + } + + private: + uint64_t prev_ = {}; + uint64_t cur_ = {}; + }; + public: using labels_t = std::vector; + using VerifyDoneCallback = std::function; class VerifyMediator : public tr_verify_worker::Mediator @@ -105,6 +146,8 @@ public: std::optional time_started_; }; + // --- + explicit tr_torrent(tr_torrent_metainfo&& tm) : metainfo_{ std::move(tm) } , completion{ this, &this->metainfo_.block_info() } @@ -957,6 +1000,10 @@ public: // Will equal either download_dir or incomplete_dir tr_interned_string current_dir_; + CumulativeCount bytes_corrupt_; + CumulativeCount bytes_downloaded_; + CumulativeCount bytes_uploaded_; + /* Used when the torrent has been created with a magnet link * and we're in the process of downloading the metainfo from * other peers */ @@ -979,13 +1026,6 @@ public: time_t seconds_downloading_before_current_start_ = 0; time_t seconds_seeding_before_current_start_ = 0; - uint64_t downloadedCur = 0; - uint64_t downloadedPrev = 0; - uint64_t uploadedCur = 0; - uint64_t uploadedPrev = 0; - uint64_t corruptCur = 0; - uint64_t corruptPrev = 0; - size_t queuePosition = 0; tr_completeness completeness = TR_LEECH;