From 1e20d676c1f4463bd114fdabf41a685d57e54054 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 14 Dec 2021 15:59:44 -0600 Subject: [PATCH] refactor: make tr_torrentInfo() private (#2285) * refactor: make tr_torrentInfo() private --- gtk/DetailsDialog.cc | 32 +++++++------- gtk/Session.cc | 6 +-- gtk/TorrentCellRenderer.cc | 4 +- libtransmission/rpcimpl.cc | 11 +++-- libtransmission/torrent-magnet.cc | 5 +++ libtransmission/torrent.cc | 33 ++++++++++++++ libtransmission/torrent.h | 4 +- libtransmission/transmission.h | 72 ++++++++++++++++++++----------- macosx/Controller.mm | 3 +- macosx/Torrent.mm | 36 +++++++--------- 10 files changed, 130 insertions(+), 76 deletions(-) diff --git a/gtk/DetailsDialog.cc b/gtk/DetailsDialog.cc index e8b4cb7a0..8f2bcc2ef 100644 --- a/gtk/DetailsDialog.cc +++ b/gtk/DetailsDialog.cc @@ -614,14 +614,14 @@ void DetailsDialog::Impl::refreshInfo(std::vector const& torrents) Glib::ustring stateString; uint64_t sizeWhenDone = 0; std::vector stats; - std::vector infos; + std::vector infos; stats.reserve(torrents.size()); infos.reserve(torrents.size()); for (auto* const torrent : torrents) { stats.push_back(tr_torrentStatCached(torrent)); - infos.push_back(tr_torrentInfo(torrent)); + infos.push_back(tr_torrentView(torrent)); } /* privacy_lb */ @@ -631,11 +631,11 @@ void DetailsDialog::Impl::refreshInfo(std::vector const& torrents) } else { - bool const baseline = infos.front()->isPrivate; + bool const baseline = infos.front().is_private; bool const is_uniform = std::all_of( infos.begin(), infos.end(), - [baseline](auto const* info) { return info->isPrivate == baseline; }); + [baseline](auto const& info) { return info.is_private == baseline; }); if (is_uniform) { @@ -656,17 +656,17 @@ void DetailsDialog::Impl::refreshInfo(std::vector const& torrents) } else { - auto const creator = Glib::ustring(infos.front()->creator != nullptr ? infos.front()->creator : ""); - time_t const date = infos.front()->dateCreated; + auto const creator = Glib::ustring(infos.front().creator != nullptr ? infos.front().creator : ""); + auto const date = infos.front().date_created; auto const datestr = get_short_date_string(date); bool const mixed_creator = std::any_of( infos.begin(), infos.end(), - [&creator](auto const* info) { return creator != (info->creator != nullptr ? info->creator : ""); }); + [&creator](auto const& info) { return creator != (info.creator != nullptr ? info.creator : ""); }); bool const mixed_date = std::any_of( infos.begin(), infos.end(), - [date](auto const* info) { return date != info->dateCreated; }); + [date](auto const& info) { return date != info.date_created; }); bool const empty_creator = creator.empty(); bool const empty_date = date == 0; @@ -705,11 +705,11 @@ void DetailsDialog::Impl::refreshInfo(std::vector const& torrents) } else { - auto const baseline = Glib::ustring(infos.front()->comment != nullptr ? infos.front()->comment : ""); + auto const baseline = Glib::ustring(infos.front().comment != nullptr ? infos.front().comment : ""); bool const is_uniform = std::all_of( infos.begin(), infos.end(), - [&baseline](auto const* info) { return baseline == (info->comment != nullptr ? info->comment : ""); }); + [&baseline](auto const& info) { return baseline == (info.comment != nullptr ? info.comment : ""); }); str = is_uniform ? baseline : mixed; } @@ -818,16 +818,16 @@ void DetailsDialog::Impl::refreshInfo(std::vector const& torrents) int pieces = 0; int32_t pieceSize = 0; - for (auto const* const info : infos) + for (auto const& info : infos) { - size += info->totalSize; - pieces += info->pieceCount; + size += info.total_size; + pieces += info.n_pieces; if (pieceSize == 0) { - pieceSize = info->pieceSize; + pieceSize = info.piece_size; } - else if (pieceSize != (int)info->pieceSize) + else if (pieceSize != (int)info.piece_size) { pieceSize = -1; } @@ -963,7 +963,7 @@ void DetailsDialog::Impl::refreshInfo(std::vector const& torrents) } else if (infos.size() == 1) { - str = infos.front()->hashString; + str = infos.front().hash_string; } else { diff --git a/gtk/Session.cc b/gtk/Session.cc index fb26a3465..0af20d08e 100644 --- a/gtk/Session.cc +++ b/gtk/Session.cc @@ -490,8 +490,8 @@ int compare_by_age(Gtk::TreeModel::iterator const& a, Gtk::TreeModel::iterator c int compare_by_size(Gtk::TreeModel::iterator const& a, Gtk::TreeModel::iterator const& b) { - auto const size_a = tr_torrentInfo(static_cast(a->get_value(torrent_cols.torrent)))->totalSize; - auto const size_b = tr_torrentInfo(static_cast(b->get_value(torrent_cols.torrent)))->totalSize; + auto const size_a = tr_torrentTotalSize(static_cast(a->get_value(torrent_cols.torrent))); + auto const size_b = tr_torrentTotalSize(static_cast(b->get_value(torrent_cols.torrent))); int ret = compare_uint64(size_a, size_b); if (ret == 0) @@ -883,7 +883,7 @@ namespace Glib::ustring get_collated_name(tr_torrent const* tor) { - return gtr_sprintf("%s\t%s", Glib::ustring(tr_torrentName(tor)).lowercase(), tr_torrentInfo(tor)->hashString); + return gtr_sprintf("%s\t%s", Glib::ustring(tr_torrentName(tor)).lowercase(), tr_torrentView(tor).hash_string); } struct metadata_callback_data diff --git a/gtk/TorrentCellRenderer.cc b/gtk/TorrentCellRenderer.cc index 4277ffddb..a309535bd 100644 --- a/gtk/TorrentCellRenderer.cc +++ b/gtk/TorrentCellRenderer.cc @@ -462,7 +462,7 @@ void TorrentCellRenderer::Impl::get_size_full(Gtk::Widget& widget, int& width, i auto* const tor = static_cast(torrent.get_value()); auto const* const st = tr_torrentStatCached(tor); - auto const total_size = tr_torrentInfo(tor)->totalSize; + auto const total_size = tr_torrentTotalSize(tor); auto const icon = get_icon(tor, FullIconSize, widget); auto const name = Glib::ustring(tr_torrentName(tor)); @@ -681,7 +681,7 @@ void TorrentCellRenderer::Impl::render_full( auto* const tor = static_cast(torrent.get_value()); auto const* const st = tr_torrentStatCached(tor); - auto const total_size = tr_torrentInfo(tor)->totalSize; + auto const total_size = tr_torrentTotalSize(tor); bool const active = st->activity != TR_STATUS_STOPPED && st->activity != TR_STATUS_DOWNLOAD_WAIT && st->activity != TR_STATUS_SEED_WAIT; auto const percentDone = get_percent_done(tor, st, &seed); diff --git a/libtransmission/rpcimpl.cc b/libtransmission/rpcimpl.cc index 91f157d57..ab7dad1fb 100644 --- a/libtransmission/rpcimpl.cc +++ b/libtransmission/rpcimpl.cc @@ -415,14 +415,13 @@ static void addWebseeds(tr_info const* info, tr_variant* webseeds) static void addTrackers(tr_torrent const* tor, tr_variant* trackers) { - for (size_t i = 0, n = tor->trackerCount(); i < n; ++i) + for (auto const& tracker : *tor->info.announce_list) { - auto const info = tor->tracker(i); tr_variant* d = tr_variantListAddDict(trackers, 4); - tr_variantDictAddQuark(d, TR_KEY_announce, info.announce_interned); - tr_variantDictAddInt(d, TR_KEY_id, info.id); - tr_variantDictAddQuark(d, TR_KEY_scrape, info.scrape_interned); - tr_variantDictAddInt(d, TR_KEY_tier, info.tier); + tr_variantDictAddQuark(d, TR_KEY_announce, tracker.announce_interned); + tr_variantDictAddInt(d, TR_KEY_id, tracker.id); + tr_variantDictAddQuark(d, TR_KEY_scrape, tracker.scrape_interned); + tr_variantDictAddInt(d, TR_KEY_tier, tracker.tier); } } diff --git a/libtransmission/torrent-magnet.cc b/libtransmission/torrent-magnet.cc index 8e2e523e7..0106d1483 100644 --- a/libtransmission/torrent-magnet.cc +++ b/libtransmission/torrent-magnet.cc @@ -413,3 +413,8 @@ char* tr_torrentInfoGetMagnetLink(tr_info const* inf) return evbuffer_free_to_str(s, nullptr); } + +char* tr_torrentGetMagnetLink(tr_torrent const* tor) +{ + return tr_torrentInfoGetMagnetLink(tr_torrentInfo(tor)); +} diff --git a/libtransmission/torrent.cc b/libtransmission/torrent.cc index e868c3c07..71b233ec1 100644 --- a/libtransmission/torrent.cc +++ b/libtransmission/torrent.cc @@ -77,6 +77,13 @@ char const* tr_torrentName(tr_torrent const* tor) return tor != nullptr ? tor->info.name : ""; } +uint64_t tr_torrentTotalSize(tr_torrent const* tor) +{ + TR_ASSERT(tr_isTorrent(tor)); + + return tor->info.totalSize; +} + int tr_torrentId(tr_torrent const* tor) { return tor != nullptr ? tor->uniqueId : -1; @@ -1257,6 +1264,27 @@ size_t tr_torrentTrackerCount(tr_torrent const* tor) return tr_announcerTrackerCount(tor); } +tr_torrent_view tr_torrentView(tr_torrent const* tor) +{ + TR_ASSERT(tr_isTorrent(tor)); + + auto ret = tr_torrent_view{}; + ret.name = tor->info.name; + ret.hash_string = tor->info.hashString; + ret.torrent_filename = tor->info.torrent; + ret.comment = tor->info.comment; + ret.creator = tor->info.creator; + ret.source = tor->info.source; + ret.total_size = tor->info.totalSize; + ret.date_created = tor->info.dateCreated; + ret.piece_size = tor->info.pieceSize; + ret.n_pieces = tor->info.pieceCount; + ret.is_private = tor->info.isPrivate; + ret.is_folder = tor->info.isFolder; + + return ret; +} + /*** **** ***/ @@ -3266,3 +3294,8 @@ void tr_torrentSetFilePriorities( { tor->setFilePriorities(files, fileCount, priority); } + +bool tr_torrentHasMetadata(tr_torrent const* tor) +{ + return tor->info.fileCount > 0; +} diff --git a/libtransmission/torrent.h b/libtransmission/torrent.h index 003381139..2e0eb0df0 100644 --- a/libtransmission/torrent.h +++ b/libtransmission/torrent.h @@ -330,7 +330,7 @@ public: /// TRACKERS - size_t trackerCount() const + auto trackerCount() const { return std::size(*info.announce_list); } @@ -694,3 +694,5 @@ constexpr tr_direction tr_torrentGetQueueDirection(tr_torrent const* tor) { return tr_torrentIsSeed(tor) ? TR_UP : TR_DOWN; } + +tr_info const* tr_torrentInfo(tr_torrent const* torrent); diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index b16d6b074..609815da1 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -46,8 +46,8 @@ struct tr_block_span_t }; struct tr_ctor; -struct tr_file; struct tr_error; +struct tr_file; struct tr_info; struct tr_session; struct tr_torrent; @@ -998,7 +998,7 @@ using tr_torrent_rename_done_func = void (*)( // * @param callback_data the pointer to pass in the callback's user_data arg * * As a special case, renaming the root file in a torrent will also - * update tr_info.name. + * update tr_torrentName(). * * EXAMPLES * @@ -1016,9 +1016,10 @@ using tr_torrent_rename_done_func = void (*)( // * * RETURN * - * Changing tr_info's contents requires a session lock, so this function - * returns asynchronously to avoid blocking. If you don't want to be notified - * when the function has finished, you can pass nullptr as the callback arg. + * Changing the torrent's internal fields requires a session thread lock, + * so this function returns asynchronously to avoid blocking. If you don't + * want to be notified when the function has finished, you can pass nullptr + * as the callback arg. * * On success, the callback's error argument will be 0. * @@ -1062,9 +1063,8 @@ uint64_t tr_torrentGetBytesLeftToAllocate(tr_torrent const* torrent); /** * @brief Returns this torrent's unique ID. * - * IDs are good as simple lookup keys, but are not persistent - * between sessions. If you need that, use tr_info.hash or - * tr_info.hashString. + * IDs are fast lookup keys, but are not persistent between sessions. + * If you need that, use tr_torrentView().hash_string. */ int tr_torrentId(tr_torrent const* torrent); @@ -1080,6 +1080,8 @@ tr_torrent* tr_torrentFindFromMagnetLink(tr_session* session, char const* link); */ char const* tr_torrentName(tr_torrent const*); +uint64_t tr_torrentTotalSize(tr_torrent const*); + /** * @brief find the location of a torrent's file by looking with and without * the ".part" suffix, looking in downloadDir and incompleteDir, etc. @@ -1186,8 +1188,6 @@ void tr_torrentSetFilePriorities( /** @brief Set a batch of files to be downloaded or not. */ void tr_torrentSetFileDLs(tr_torrent* torrent, tr_file_index_t const* files, tr_file_index_t fileCount, bool do_download); -tr_info const* tr_torrentInfo(tr_torrent const* torrent); - /* Raw function to change the torrent's downloadDir field. This should only be used by libtransmission or to bootstrap a newly-instantiated tr_torrent object. */ @@ -1210,10 +1210,7 @@ char* tr_torrentInfoGetMagnetLink(tr_info const* inf); * Returns a newly-allocated string with a magnet link of the torrent. * Use tr_free() to free the string when done. */ -static inline char* tr_torrentGetMagnetLink(tr_torrent const* tor) -{ - return tr_torrentInfoGetMagnetLink(tr_torrentInfo(tor)); -} +char* tr_torrentGetMagnetLink(tr_torrent const* tor); /** *** @@ -1473,6 +1470,33 @@ struct tr_webseed_view tr_torrentWebseed(tr_torrent const* torrent, size_t nth); size_t tr_torrentWebseedCount(tr_torrent const* torrent); +/* + * This view structure is intended for short-term use. Its pointers are owned + * by the torrent and may be invalidated if the torrent is edited or removed. + */ +struct tr_torrent_view +{ + char const* name; + char const* hash_string; + char const* torrent_filename; + + char const* comment; // optional; may be nullptr + char const* creator; // optional; may be nullptr + char const* source; // optional; may be nullptr + + uint64_t total_size; // total size of the torrent, in bytes + + time_t date_created; + + uint32_t piece_size; + tr_piece_index_t n_pieces; + + bool is_private; + bool is_folder; +}; + +struct tr_torrent_view tr_torrentView(tr_torrent const* tor); + /*********************************************************************** * tr_torrentAvailability *********************************************************************** @@ -1571,11 +1595,7 @@ struct tr_info bool isFolder; }; -static inline bool tr_torrentHasMetadata(tr_torrent const* tor) -{ - tr_info const* const inf = tr_torrentInfo(tor); - return (inf != nullptr) && (inf->fileCount > 0); -} +bool tr_torrentHasMetadata(tr_torrent const* tor); /** * What the torrent is doing right now. @@ -1705,13 +1725,13 @@ struct tr_stat int webseedsSendingToUs; /** Byte count of all the piece data we'll have downloaded when we're done, - whether or not we have it yet. This may be less than tr_info.totalSize + whether or not we have it yet. This may be less than tr_torrentTotalSize() if only some of the torrent's files are wanted. - [0...tr_info.totalSize] */ + [0...tr_torrentTotalSize()] */ uint64_t sizeWhenDone; /** Byte count of how much data is left to be downloaded until we've got - all the pieces that we want. [0...tr_info.sizeWhenDone] */ + all the pieces that we want. [0...tr_stat.sizeWhenDone] */ uint64_t leftUntilDone; /** Byte count of all the piece data we want and don't have yet, @@ -1778,14 +1798,14 @@ struct tr_stat /** Cumulative seconds the torrent's ever spent seeding */ int secondsSeeding; - /** A torrent is considered finished if it has met its seed ratio. - As a result, only paused torrents can be finished. */ - bool finished; - /** This torrent's queue position. All torrents have a queue position, even if it's not queued. */ int queuePosition; + /** A torrent is considered finished if it has met its seed ratio. + As a result, only paused torrents can be finished. */ + bool finished; + /** True if the torrent is running, but has been idle for long enough to be considered stalled. @see tr_sessionGetQueueStalledMinutes() */ bool isStalled; diff --git a/macosx/Controller.mm b/macosx/Controller.mm index 912d82213..6fbc49c1f 100644 --- a/macosx/Controller.mm +++ b/macosx/Controller.mm @@ -1213,8 +1213,7 @@ static void removeKeRangerRansomware() tr_torrent* duplicateTorrent; if ((duplicateTorrent = tr_torrentFindFromMagnetLink(fLib, address.UTF8String))) { - tr_info const* info = tr_torrentInfo(duplicateTorrent); - NSString* name = (info != NULL && info->name != NULL) ? @(info->name) : nil; + NSString* name = @(tr_torrentName(duplicateTorrent)); [self duplicateOpenMagnetAlert:address transferName:name]; return; } diff --git a/macosx/Torrent.mm b/macosx/Torrent.mm index 3bfdbecba..20c28920b 100644 --- a/macosx/Torrent.mm +++ b/macosx/Torrent.mm @@ -152,15 +152,12 @@ bool trashDataFile(char const* filename, tr_error** error) @implementation Torrent { tr_torrent* fHandle; - tr_info const* fInfo; tr_stat const* fStat; NSUserDefaults* fDefaults; NSImage* fIcon; - NSString* fHashString; - NSArray* fFileList; NSArray* fFlatFileList; @@ -424,7 +421,7 @@ bool trashDataFile(char const* filename, tr_error** error) { if (fResumeOnWake) { - tr_logAddNamedInfo(fInfo->name, "restarting because of wakeUp"); + tr_logAddNamedInfo(tr_torrentName(fHandle), "restarting because of wakeUp"); tr_torrentStart(fHandle); } } @@ -719,17 +716,17 @@ bool trashDataFile(char const* filename, tr_error** error) - (NSString*)name { - return fInfo->name != NULL ? @(fInfo->name) : fHashString; + return @(tr_torrentName(fHandle)); } - (BOOL)isFolder { - return fInfo->isFolder; + return tr_torrentView(fHandle).is_folder; } - (uint64_t)size { - return fInfo->totalSize; + return tr_torrentTotalSize(fHandle); } - (uint64_t)sizeLeft @@ -824,43 +821,46 @@ bool trashDataFile(char const* filename, tr_error** error) - (NSString*)comment { - return fInfo->comment ? @(fInfo->comment) : @""; + auto const* comment = tr_torrentView(fHandle).comment; + return comment ? @(comment) : @""; } - (NSString*)creator { - return fInfo->creator ? @(fInfo->creator) : @""; + auto const* creator = tr_torrentView(fHandle).creator; + return creator ? @(creator) : @""; } - (NSDate*)dateCreated { - NSInteger date = fInfo->dateCreated; + auto const date = tr_torrentView(fHandle).date_created; return date > 0 ? [NSDate dateWithTimeIntervalSince1970:date] : nil; } - (NSInteger)pieceSize { - return fInfo->pieceSize; + return tr_torrentView(fHandle).piece_size; } - (NSInteger)pieceCount { - return fInfo->pieceCount; + return tr_torrentView(fHandle).n_pieces; } - (NSString*)hashString { - return fHashString; + return @(tr_torrentView(fHandle).hash_string); } - (BOOL)privateTorrent { - return fInfo->isPrivate; + return tr_torrentView(fHandle).is_private; } - (NSString*)torrentLocation { - return fInfo->torrent ? @(fInfo->torrent) : @""; + auto const* filename = tr_torrentView(fHandle).torrent_filename; + return filename ? @(filename) : @""; } - (NSString*)dataLocation @@ -932,7 +932,7 @@ bool trashDataFile(char const* filename, tr_error** error) NSDictionary* contextInfo = @{ @"Torrent" : self, @"CompletionHandler" : [completionHandler copy] }; - tr_torrentRenamePath(fHandle, fInfo->name, newName.UTF8String, renameCallback, (__bridge_retained void*)(contextInfo)); + tr_torrentRenamePath(fHandle, tr_torrentName(fHandle), newName.UTF8String, renameCallback, (__bridge_retained void*)(contextInfo)); } - (void)renameFileNode:(FileListNode*)node @@ -1888,16 +1888,12 @@ bool trashDataFile(char const* filename, tr_error** error) } } - fInfo = tr_torrentInfo(fHandle); - tr_torrentSetQueueStartCallback(fHandle, startQueueCallback, (__bridge void*)(self)); tr_torrentSetCompletenessCallback(fHandle, completenessChangeCallback, (__bridge void*)(self)); tr_torrentSetRatioLimitHitCallback(fHandle, ratioLimitHitCallback, (__bridge void*)(self)); tr_torrentSetIdleLimitHitCallback(fHandle, idleLimitHitCallback, (__bridge void*)(self)); tr_torrentSetMetadataCallback(fHandle, metadataCallback, (__bridge void*)(self)); - fHashString = @(fInfo->hashString); - fResumeOnWake = NO; //don't do after this point - it messes with auto-group functionality