diff --git a/libtransmission/announcer.cc b/libtransmission/announcer.cc index 21a7394d1..74dc5a8f6 100644 --- a/libtransmission/announcer.cc +++ b/libtransmission/announcer.cc @@ -1713,8 +1713,7 @@ static void scrapeAndAnnounceMore(tr_announcer* announcer) /* build a list of tiers that need to be announced */ auto announce_me = std::vector{}; auto scrape_me = std::vector{}; - tr_torrent* tor = nullptr; - while ((tor = tr_torrentNext(announcer->session, tor)) != nullptr) + for (auto* tor : announcer->session->torrents) { struct tr_torrent_tiers* tt = tor->tiers; diff --git a/libtransmission/peer-mgr.cc b/libtransmission/peer-mgr.cc index d875d0bb1..75e04f295 100644 --- a/libtransmission/peer-mgr.cc +++ b/libtransmission/peer-mgr.cc @@ -553,12 +553,9 @@ void tr_peerMgrFree(tr_peerMgr* manager) void tr_peerMgrOnBlocklistChanged(tr_peerMgr* mgr) { - tr_torrent* tor = nullptr; - tr_session* session = mgr->session; - /* we cache whether or not a peer is blocklisted... since the blocklist has changed, erase that cached value */ - while ((tor = tr_torrentNext(session, tor)) != nullptr) + for (auto* tor : mgr->session->torrents) { tr_swarm* s = tor->swarm; @@ -1490,7 +1487,6 @@ static void refillUpkeep(evutil_socket_t fd, short what, void* vmgr) time_t now; time_t too_old; - tr_torrent* tor; int cancel_buflen = 0; struct block_request* cancel = nullptr; auto* mgr = static_cast(vmgr); @@ -1500,9 +1496,7 @@ static void refillUpkeep(evutil_socket_t fd, short what, void* vmgr) too_old = now - REQUEST_TTL_SECS; /* alloc the temporary "cancel" buffer */ - tor = nullptr; - - while ((tor = tr_torrentNext(mgr->session, tor)) != nullptr) + for (auto const* tor : mgr->session->torrents) { cancel_buflen = std::max(cancel_buflen, tor->swarm->requestCount); } @@ -1513,9 +1507,7 @@ static void refillUpkeep(evutil_socket_t fd, short what, void* vmgr) } /* prune requests that are too old */ - tor = nullptr; - - while ((tor = tr_torrentNext(mgr->session, tor)) != nullptr) + for (auto* tor : mgr->session->torrents) { tr_swarm* s = tor->swarm; int const n = s->requestCount; @@ -3378,13 +3370,12 @@ static void rechokePulse(evutil_socket_t fd, short what, void* vmgr) TR_UNUSED(fd); TR_UNUSED(what); - tr_torrent* tor = nullptr; auto* mgr = static_cast(vmgr); uint64_t const now = tr_time_msec(); managerLock(mgr); - while ((tor = tr_torrentNext(mgr->session, tor)) != nullptr) + for (auto* tor : mgr->session->torrents) { if (tor->isRunning) { @@ -3720,17 +3711,15 @@ static void enforceTorrentPeerLimit(tr_swarm* s, uint64_t now) static void enforceSessionPeerLimit(tr_session* session, uint64_t now) { - int n = 0; - tr_torrent* tor = nullptr; - int const max = tr_sessionGetPeerLimit(session); - /* count the total number of peers */ - while ((tor = tr_torrentNext(session, tor)) != nullptr) + int n = 0; + for (auto const* tor : session->torrents) { n += tr_ptrArraySize(&tor->swarm->peers); } /* if there are too many, prune out the worst */ + int const max = tr_sessionGetPeerLimit(session); if (n > max) { tr_peer** peers = tr_new(tr_peer*, n); @@ -3738,9 +3727,7 @@ static void enforceSessionPeerLimit(tr_session* session, uint64_t now) /* populate the peer array */ n = 0; - tor = nullptr; - - while ((tor = tr_torrentNext(session, tor)) != nullptr) + for (auto* tor : session->torrents) { tr_swarm* s = tor->swarm; @@ -3774,7 +3761,6 @@ static void reconnectPulse(evutil_socket_t fd, short what, void* vmgr) TR_UNUSED(fd); TR_UNUSED(what); - tr_torrent* tor; auto* mgr = static_cast(vmgr); time_t const now_sec = tr_time(); uint64_t const now_msec = tr_time_msec(); @@ -3784,9 +3770,7 @@ static void reconnectPulse(evutil_socket_t fd, short what, void* vmgr) **/ /* if we're over the per-torrent peer limits, cull some peers */ - tor = nullptr; - - while ((tor = tr_torrentNext(mgr->session, tor)) != nullptr) + for (auto* tor : mgr->session->torrents) { if (tor->isRunning) { @@ -3798,9 +3782,7 @@ static void reconnectPulse(evutil_socket_t fd, short what, void* vmgr) enforceSessionPeerLimit(mgr->session, now_msec); /* remove crappy peers */ - tor = nullptr; - - while ((tor = tr_torrentNext(mgr->session, tor)) != nullptr) + for (auto* tor : mgr->session->torrents) { if (!tor->swarm->isRunning) { @@ -3825,9 +3807,7 @@ static void reconnectPulse(evutil_socket_t fd, short what, void* vmgr) static void pumpAllPeers(tr_peerMgr* mgr) { - tr_torrent* tor = nullptr; - - while ((tor = tr_torrentNext(mgr->session, tor)) != nullptr) + for (auto* tor : mgr->session->torrents) { tr_swarm* s = tor->swarm; @@ -3883,8 +3863,7 @@ static void bandwidthPulse(evutil_socket_t fd, short what, void* vmgr) tr_bandwidthAllocate(&session->bandwidth, TR_DOWN, BANDWIDTH_PERIOD_MSEC); /* torrent upkeep */ - tr_torrent* tor = nullptr; - while ((tor = tr_torrentNext(session, tor)) != nullptr) + for (auto* tor : session->torrents) { /* possibly stop torrents that have seeded enough */ tr_torrentCheckSeedLimit(tor); @@ -3986,8 +3965,7 @@ static void atomPulse(evutil_socket_t fd, short what, void* vmgr) auto* mgr = static_cast(vmgr); managerLock(mgr); - tr_torrent* tor = nullptr; - while ((tor = tr_torrentNext(mgr->session, tor)) != nullptr) + for (auto* tor : mgr->session->torrents) { int atomCount; tr_swarm* s = tor->swarm; @@ -4237,9 +4215,6 @@ static bool swarmIsAllSeeds(struct tr_swarm* swarm) /** @return an array of all the atoms we might want to connect to */ static struct peer_candidate* getPeerCandidates(tr_session* session, int* candidateCount, int max) { - int atomCount; - int peerCount; - tr_torrent* tor; struct peer_candidate* candidates; struct peer_candidate* walk; time_t const now = tr_time(); @@ -4248,11 +4223,9 @@ static struct peer_candidate* getPeerCandidates(tr_session* session, int* candid int const maxCandidates = tr_sessionGetPeerLimit(session) * 0.95; /* count how many peers and atoms we've got */ - tor = nullptr; - atomCount = 0; - peerCount = 0; - - while ((tor = tr_torrentNext(session, tor)) != nullptr) + int atomCount = 0; + int peerCount = 0; + for (auto const* tor : session->torrents) { atomCount += tr_ptrArraySize(&tor->swarm->pool); peerCount += tr_ptrArraySize(&tor->swarm->peers); @@ -4269,9 +4242,7 @@ static struct peer_candidate* getPeerCandidates(tr_session* session, int* candid walk = candidates = tr_new(struct peer_candidate, atomCount); /* populate the candidate array */ - tor = nullptr; - - while ((tor = tr_torrentNext(session, tor)) != nullptr) + for (auto* tor : session->torrents) { int nAtoms; struct peer_atom** atoms; diff --git a/libtransmission/platform.cc b/libtransmission/platform.cc index 857fe868e..8712949a3 100644 --- a/libtransmission/platform.cc +++ b/libtransmission/platform.cc @@ -6,14 +6,17 @@ * */ +#include +#include +#include + +#ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE 600 /* needed for recursive locks. */ +#endif #ifndef __USE_UNIX98 #define __USE_UNIX98 /* some older Linuxes need it spelt out for them */ #endif -#include -#include - #ifdef __HAIKU__ #include /* PATH_MAX */ #endif diff --git a/libtransmission/rpcimpl.cc b/libtransmission/rpcimpl.cc index e3dba341e..a7281f486 100644 --- a/libtransmission/rpcimpl.cc +++ b/libtransmission/rpcimpl.cc @@ -160,13 +160,12 @@ static tr_torrent** getTorrents(tr_session* session, tr_variant* args, int* setm { if (strcmp(str, "recently-active") == 0) { - tr_torrent* tor = nullptr; time_t const now = tr_time(); time_t const window = RECENTLY_ACTIVE_SECONDS; int const n = tr_sessionCountTorrents(session); torrents = tr_new0(tr_torrent*, n); - while ((tor = tr_torrentNext(session, tor)) != nullptr) + for (auto* tor : session->torrents) { if (tor->anyDate >= now - window) { @@ -187,7 +186,11 @@ static tr_torrent** getTorrents(tr_session* session, tr_variant* args, int* setm } else /* all of them */ { - torrents = tr_sessionGetTorrents(session, &torrentCount); + // TODO: getTorrents() should return a std::vector + auto tmp = tr_sessionGetTorrents(session); + torrentCount = std::size(tmp); + torrents = tr_new(tr_torrent*, torrentCount); + std::copy_n(std::begin(tmp), torrentCount, torrents); } *setmeCount = torrentCount; @@ -2382,21 +2385,14 @@ static char const* sessionStats( TR_ASSERT(idle_data == nullptr); - int running = 0; - int total = 0; auto currentStats = tr_session_stats{}; auto cumulativeStats = tr_session_stats{}; - tr_torrent* tor = nullptr; - while ((tor = tr_torrentNext(session, tor)) != nullptr) - { - ++total; - - if (tor->isRunning) - { - ++running; - } - } + int const total = std::size(session->torrents); + int const running = std::count_if( + std::begin(session->torrents), + std::end(session->torrents), + [](auto const* tor) { return tor->isRunning; }); tr_sessionGetStats(session, ¤tStats); tr_sessionGetCumulativeStats(session, &cumulativeStats); diff --git a/libtransmission/session.cc b/libtransmission/session.cc index 04bfbfb11..fa10cb5db 100644 --- a/libtransmission/session.cc +++ b/libtransmission/session.cc @@ -586,7 +586,6 @@ static void onSaveTimer(evutil_socket_t fd, short what, void* vsession) TR_UNUSED(fd); TR_UNUSED(what); - tr_torrent* tor = nullptr; auto* session = static_cast(vsession); if (tr_cacheFlushDone(session->cache) != 0) @@ -594,7 +593,7 @@ static void onSaveTimer(evutil_socket_t fd, short what, void* vsession) tr_logAddError("Error while flushing completed pieces from cache"); } - while ((tor = tr_torrentNext(session, tor)) != nullptr) + for (auto* tor : session->torrents) { tr_torrentSave(tor); } @@ -624,22 +623,18 @@ tr_session* tr_sessionInit(char const* configDir, bool messageQueuingEnabled, tr TR_ASSERT(tr_variantIsDict(clientSettings)); int64_t i; - tr_session* session; struct init_data data; tr_timeUpdate(time(nullptr)); /* initialize the bare skeleton of the session object */ - session = tr_new0(tr_session, 1); + auto* session = new tr_session{}; session->udp_socket = TR_BAD_SOCKET; session->udp6_socket = TR_BAD_SOCKET; session->lock = tr_lockNew(); session->cache = tr_cacheNew(1024 * 1024 * 2); session->magicNumber = SESSION_MAGIC_NUMBER; session->session_id = tr_session_id_new(); - session->torrentsSortedByHash = {}; - session->torrentsSortedByHashString = {}; - session->torrentsSortedById = {}; tr_bandwidthConstruct(&session->bandwidth, session, nullptr); tr_variantInitList(&session->removedTorrents, 0); @@ -686,7 +681,6 @@ static void onNowTimer(evutil_socket_t fd, short what, void* vsession) int const min = 100; int const max = 999999; struct timeval tv; - tr_torrent* tor = nullptr; time_t const now = time(nullptr); /** @@ -702,7 +696,10 @@ static void onNowTimer(evutil_socket_t fd, short what, void* vsession) turtleCheckClock(session, &session->turtle); } - while ((tor = tr_torrentNext(session, tor)) != nullptr) + // TODO: this seems a little silly. Why do we increment this + // every second instead of computing the value as needed by + // subtracting the current time from a start time? + for (auto* tor : session->torrents) { if (tor->isRunning) { @@ -1325,13 +1322,11 @@ static void peerPortChanged(void* vsession) auto* session = static_cast(vsession); TR_ASSERT(tr_isSession(session)); - tr_torrent* tor = nullptr; - close_incoming_peer_port(session); open_incoming_peer_port(session); tr_sharedPortChanged(session); - while ((tor = tr_torrentNext(session, tor)) != nullptr) + for (auto* tor : session->torrents) { tr_torrentChangeMyPort(tor); } @@ -1908,52 +1903,26 @@ double tr_sessionGetRawSpeed_KBps(tr_session const* session, tr_direction dir) int tr_sessionCountTorrents(tr_session const* session) { - return tr_isSession(session) ? session->torrentCount : 0; + return tr_isSession(session) ? std::size(session->torrents) : 0; } -tr_torrent** tr_sessionGetTorrents(tr_session* session, int* setme_n) +std::vector tr_sessionGetTorrents(tr_session* session) { TR_ASSERT(tr_isSession(session)); - TR_ASSERT(setme_n != nullptr); - - int n = tr_sessionCountTorrents(session); - *setme_n = n; - - tr_torrent** torrents = tr_new(tr_torrent*, n); - tr_torrent* tor = nullptr; - - for (int i = 0; i < n; ++i) - { - torrents[i] = tor = tr_torrentNext(session, tor); - } + auto const& src = session->torrents; + auto const n = std::size(src); + auto torrents = std::vector{ n }; + std::copy(std::begin(src), std::end(src), std::begin(torrents)); return torrents; } -static int compareTorrentByCur(void const* va, void const* vb) -{ - tr_torrent const* a = *(tr_torrent const* const*)va; - tr_torrent const* b = *(tr_torrent const* const*)vb; - uint64_t const aCur = a->downloadedCur + a->uploadedCur; - uint64_t const bCur = b->downloadedCur + b->uploadedCur; - - if (aCur != bCur) - { - return aCur > bCur ? -1 : 1; /* close the biggest torrents first */ - } - - return 0; -} - static void closeBlocklists(tr_session*); static void sessionCloseImplWaitForIdleUdp(evutil_socket_t fd, short what, void* vsession); static void sessionCloseImplStart(tr_session* session) { - int n; - tr_torrent** torrents; - session->isClosing = true; free_incoming_peer_port(session); @@ -1979,15 +1948,23 @@ static void sessionCloseImplStart(tr_session* session) /* Close the torrents. Get the most active ones first so that * if we can't get them all closed in a reasonable amount of time, * at least we get the most important ones first. */ - torrents = tr_sessionGetTorrents(session, &n); - qsort(torrents, n, sizeof(tr_torrent*), compareTorrentByCur); + auto torrents = tr_sessionGetTorrents(session); + std::sort( + std::begin(torrents), + std::end(torrents), + [](auto const* a, auto const* b) + { + auto const aCur = a->downloadedCur + a->uploadedCur; + auto const bCur = b->downloadedCur + b->uploadedCur; + return aCur > bCur; // larger xfers go first + }); - for (int i = 0; i < n; ++i) + for (auto* tor : torrents) { - tr_torrentFree(torrents[i]); + tr_torrentFree(tor); } - tr_free(torrents); + torrents.clear(); /* Close the announcer *after* closing the torrents so that all the &event=stopped messages will be @@ -2144,9 +2121,6 @@ void tr_sessionClose(tr_session* session) } tr_device_info_free(session->downloadDir); - tr_ptrArrayDestruct(&session->torrentsSortedByHash, nullptr); - tr_ptrArrayDestruct(&session->torrentsSortedByHashString, nullptr); - tr_ptrArrayDestruct(&session->torrentsSortedById, nullptr); tr_free(session->torrentDoneScript); tr_free(session->configDir); tr_free(session->resumeDir); @@ -2154,7 +2128,7 @@ void tr_sessionClose(tr_session* session) tr_free(session->incompleteDir); tr_free(session->blocklist_url); tr_free(session->peer_congestion_algorithm); - tr_free(session); + delete session; } struct sessionLoadTorrentsData @@ -3026,8 +3000,7 @@ void tr_sessionGetNextQueuedTorrents(tr_session* session, tr_direction direction // build an array of the candidates auto candidates = std::vector{}; candidates.reserve(tr_sessionCountTorrents(session)); - tr_torrent* tor = nullptr; - while ((tor = tr_torrentNext(session, tor)) != nullptr) + for (auto* tor : session->torrents) { if (tr_torrentIsQueued(tor) && (direction == tr_torrentGetQueueDirection(tor))) { @@ -3069,8 +3042,7 @@ int tr_sessionCountQueueFreeSlots(tr_session* session, tr_direction dir) bool const stalled_enabled = tr_sessionGetQueueStalledEnabled(session); int const stalled_if_idle_for_n_seconds = tr_sessionGetQueueStalledMinutes(session) * 60; time_t const now = tr_time(); - tr_torrent* tor = nullptr; - while ((tor = tr_torrentNext(session, tor)) != nullptr) + for (auto const* tor : session->torrents) { /* is it the right activity? */ if (activity != tr_torrentGetActivity(tor)) @@ -3098,67 +3070,18 @@ int tr_sessionCountQueueFreeSlots(tr_session* session, tr_direction dir) return max - active_count; } -static int compareTorrentsById(void const* va, void const* vb) -{ - auto const* const a = static_cast(va); - auto const* const b = static_cast(vb); - return a->uniqueId - b->uniqueId; -} - -static int compareTorrentsByHashString(void const* va, void const* vb) -{ - auto const* const a = static_cast(va); - auto const* const b = static_cast(vb); - return evutil_ascii_strcasecmp(a->info.hashString, b->info.hashString); -} - -static int compareTorrentsByHash(void const* va, void const* vb) -{ - auto const* const a = static_cast(va); - auto const* const b = static_cast(vb); - return memcmp(a->info.hash, b->info.hash, SHA_DIGEST_LENGTH); -} - void tr_sessionAddTorrent(tr_session* session, tr_torrent* tor) { - /* add tor to tr_session.torrentList */ - tor->next = session->torrentList; - session->torrentList = tor; - - /* add tor to tr_session.torrentsSortedByFoo */ - tr_ptrArrayInsertSorted(&session->torrentsSortedById, tor, compareTorrentsById); - tr_ptrArrayInsertSorted(&session->torrentsSortedByHashString, tor, compareTorrentsByHashString); - tr_ptrArrayInsertSorted(&session->torrentsSortedByHash, tor, compareTorrentsByHash); - - /* increment the torrent count */ - ++session->torrentCount; + session->torrents.insert(tor); + session->torrentsById.insert_or_assign(tor->uniqueId, tor); + session->torrentsByHash.insert_or_assign(tor->info.hash, tor); + session->torrentsByHashString.insert_or_assign(tor->info.hashString, tor); } void tr_sessionRemoveTorrent(tr_session* session, tr_torrent* tor) { - /* remove tor from tr_session.torrentList */ - if (tor == session->torrentList) - { - session->torrentList = tor->next; - } - else - { - for (tr_torrent* t = session->torrentList; t != nullptr; t = t->next) - { - if (t->next == tor) - { - t->next = tor->next; - break; - } - } - } - - /* remove tor from tr_session.torrentsSortedByFoo */ - tr_ptrArrayRemoveSortedPointer(&session->torrentsSortedById, tor, compareTorrentsById); - tr_ptrArrayRemoveSortedPointer(&session->torrentsSortedByHashString, tor, compareTorrentsByHashString); - tr_ptrArrayRemoveSortedPointer(&session->torrentsSortedByHash, tor, compareTorrentsByHash); - - /* decrement the torrent count */ - TR_ASSERT(session->torrentCount >= 1); - session->torrentCount--; + session->torrents.erase(tor); + session->torrentsById.erase(tor->uniqueId); + session->torrentsByHash.erase(tor->info.hash); + session->torrentsByHashString.erase(tor->info.hashString); } diff --git a/libtransmission/session.h b/libtransmission/session.h index 8db4c864e..7a77ce7c1 100644 --- a/libtransmission/session.h +++ b/libtransmission/session.h @@ -14,6 +14,13 @@ #define TR_NAME "Transmission" +#include // memcmp() +#include +#include +#include + +#include // evutil_ascii_strcasecmp() + #include "bandwidth.h" #include "bitfield.h" #include "net.h" @@ -22,8 +29,6 @@ #include "utils.h" #include "variant.h" -TR_BEGIN_DECLS - typedef enum { TR_NET_OK, @@ -95,6 +100,22 @@ struct tr_turtle_info tr_auto_switch_state_t autoTurtleState; }; +struct CompareHash +{ + bool operator()(uint8_t const* const a, uint8_t const* const b) const + { + return std::memcmp(a, b, SHA_DIGEST_LENGTH) < 0; + } +}; + +struct CompareHashString +{ + bool operator()(char const* const a, char const* const b) const + { + return evutil_ascii_strcasecmp(a, b) < 0; + } +}; + /** @brief handle to an active libtransmission session */ struct tr_session { @@ -176,11 +197,10 @@ struct tr_session int peerSocketTOS; char* peer_congestion_algorithm; - int torrentCount; - tr_torrent* torrentList; - tr_ptrArray torrentsSortedByHash; - tr_ptrArray torrentsSortedByHashString; - tr_ptrArray torrentsSortedById; + std::unordered_set torrents; + std::map torrentsById; + std::map torrentsByHash; + std::map torrentsByHashString; char* torrentDoneScript; @@ -256,7 +276,7 @@ struct tr_bindsockets* tr_sessionGetBindSockets(tr_session*); int tr_sessionCountTorrents(tr_session const* session); -tr_torrent** tr_sessionGetTorrents(tr_session* session, int* setme_n); +std::vector tr_sessionGetTorrents(tr_session* session); enum { @@ -328,5 +348,3 @@ int tr_sessionCountQueueFreeSlots(tr_session* session, tr_direction); void tr_sessionAddTorrent(tr_session* session, tr_torrent* tor); void tr_sessionRemoveTorrent(tr_session* session, tr_torrent* tor); - -TR_END_DECLS diff --git a/libtransmission/torrent.cc b/libtransmission/torrent.cc index d380abeb2..c0f1a9932 100644 --- a/libtransmission/torrent.cc +++ b/libtransmission/torrent.cc @@ -73,42 +73,25 @@ int tr_torrentId(tr_torrent const* tor) return tor != nullptr ? tor->uniqueId : -1; } -static int compareKeyToTorrentId(void const* va, void const* vb) -{ - auto const* const a = static_cast(va); - auto const b = *static_cast(vb); - return a->uniqueId - b; -} - tr_torrent* tr_torrentFindFromId(tr_session* session, int id) { - return static_cast(tr_ptrArrayFindSorted(&session->torrentsSortedById, &id, compareKeyToTorrentId)); + auto& src = session->torrentsById; + auto it = src.find(id); + return it == std::end(src) ? nullptr : it->second; } -static int compareKeyToTorrentHashString(void const* va, void const* vb) +tr_torrent* tr_torrentFindFromHashString(tr_session* session, char const* hashstr) { - auto const* const a = static_cast(va); - auto const* const b = static_cast(vb); - return evutil_ascii_strcasecmp(a->info.hashString, b); + auto& src = session->torrentsByHashString; + auto it = src.find(hashstr); + return it == std::end(src) ? nullptr : it->second; } -tr_torrent* tr_torrentFindFromHashString(tr_session* session, char const* str) +tr_torrent* tr_torrentFindFromHash(tr_session* session, uint8_t const* hash) { - return static_cast( - tr_ptrArrayFindSorted(&session->torrentsSortedByHashString, str, compareKeyToTorrentHashString)); -} - -static int compareKeyToTorrentHash(void const* va, void const* vb) -{ - auto const* const a = static_cast(va); - auto const* const b = static_cast(vb); - return memcmp(a->info.hash, b, SHA_DIGEST_LENGTH); -} - -tr_torrent* tr_torrentFindFromHash(tr_session* session, uint8_t const* torrentHash) -{ - return static_cast( - tr_ptrArrayFindSorted(&session->torrentsSortedByHash, torrentHash, compareKeyToTorrentHash)); + auto& src = session->torrentsByHash; + auto it = src.find(hash); + return it == std::end(src) ? nullptr : it->second; } tr_torrent* tr_torrentFindFromMagnetLink(tr_session* session, char const* magnet) @@ -127,9 +110,7 @@ tr_torrent* tr_torrentFindFromMagnetLink(tr_session* session, char const* magnet tr_torrent* tr_torrentFindFromObfuscatedHash(tr_session* session, uint8_t const* obfuscatedTorrentHash) { - tr_torrent* tor = nullptr; - - while ((tor = tr_torrentNext(session, tor)) != nullptr) + for (auto* tor : session->torrents) { if (memcmp(tor->obfuscatedHash, obfuscatedTorrentHash, SHA_DIGEST_LENGTH) == 0) { @@ -883,7 +864,7 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor) tor->session = session; tor->uniqueId = nextUniqueId++; tor->magicNumber = TORRENT_MAGIC_NUMBER; - tor->queuePosition = session->torrentCount; + tor->queuePosition = tr_sessionCountTorrents(session); tor->labels = {}; tr_sha1(tor->obfuscatedHash, "req2", 4, tor->info.hash, SHA_DIGEST_LENGTH, nullptr); @@ -1644,9 +1625,7 @@ static void freeTorrent(tr_torrent* tor) tr_sessionRemoveTorrent(session, tor); /* resequence the queue positions */ - tr_torrent* t = nullptr; - - while ((t = tr_torrentNext(session, t)) != nullptr) + for (auto* t : session->torrents) { if (t->queuePosition > tor->queuePosition) { @@ -3599,13 +3578,11 @@ static int compareTorrentByQueuePosition(void const* va, void const* vb) static bool queueIsSequenced(tr_session* session) { - int n; - bool is_sequenced; - tr_torrent** torrents; - - n = 0; - torrents = tr_sessionGetTorrents(session, &n); - qsort(torrents, n, sizeof(tr_torrent*), compareTorrentByQueuePosition); + auto torrents = tr_sessionGetTorrents(session); + std::sort( + std::begin(torrents), + std::end(torrents), + [](auto const* a, auto const* b) { return a->queuePosition < b->queuePosition; }); #if 0 @@ -3621,14 +3598,13 @@ static bool queueIsSequenced(tr_session* session) #endif /* test them */ - is_sequenced = true; + bool is_sequenced = true; - for (int i = 0; is_sequenced && i < n; ++i) + for (int i = 0, n = std::size(torrents); is_sequenced && i < n; ++i) { is_sequenced = torrents[i]->queuePosition == i; } - tr_free(torrents); return is_sequenced; } @@ -3642,7 +3618,6 @@ int tr_torrentGetQueuePosition(tr_torrent const* tor) void tr_torrentSetQueuePosition(tr_torrent* tor, int pos) { int back = -1; - tr_torrent* walk; int const old_pos = tor->queuePosition; time_t const now = tr_time(); @@ -3653,9 +3628,7 @@ void tr_torrentSetQueuePosition(tr_torrent* tor, int pos) tor->queuePosition = -1; - walk = nullptr; - - while ((walk = tr_torrentNext(tor->session, walk)) != nullptr) + for (auto* walk : tor->session->torrents) { if ((old_pos < pos) && (old_pos <= walk->queuePosition) && (walk->queuePosition <= pos)) { diff --git a/libtransmission/torrent.h b/libtransmission/torrent.h index 74fe8ae31..1aca01b48 100644 --- a/libtransmission/torrent.h +++ b/libtransmission/torrent.h @@ -253,8 +253,6 @@ struct tr_torrent time_t lastStatTime; tr_stat stats; - tr_torrent* next; - int uniqueId; struct tr_bandwidth bandwidth; @@ -271,11 +269,6 @@ struct tr_torrent tr_ptrArray labels; }; -static inline tr_torrent* tr_torrentNext(tr_session* session, tr_torrent* current) -{ - return current != nullptr ? current->next : session->torrentList; -} - /* what piece index is this block in? */ static inline tr_piece_index_t tr_torBlockPiece(tr_torrent const* tor, tr_block_index_t const block) { diff --git a/libtransmission/tr-dht.cc b/libtransmission/tr-dht.cc index 5ee0387b2..2ccdc2e3d 100644 --- a/libtransmission/tr-dht.cc +++ b/libtransmission/tr-dht.cc @@ -768,10 +768,9 @@ static int tr_dhtAnnounce(tr_torrent* tor, int af, bool announce) void tr_dhtUpkeep(tr_session* session) { - tr_torrent* tor = nullptr; time_t const now = tr_time(); - while ((tor = tr_torrentNext(session, tor)) != nullptr) + for (auto* tor : session->torrents) { if (!tor->isRunning || !tr_torrentAllowsDHT(tor)) { diff --git a/libtransmission/tr-lpd.cc b/libtransmission/tr-lpd.cc index 8a86a65f1..e68ea3b7d 100644 --- a/libtransmission/tr-lpd.cc +++ b/libtransmission/tr-lpd.cc @@ -618,7 +618,6 @@ static int tr_lpdConsiderAnnounce(tr_pex* peer, char const* const msg) */ static int tr_lpdAnnounceMore(time_t const now, int const interval) { - tr_torrent* tor = nullptr; int announcesSent = 0; if (!tr_isSession(session)) @@ -626,9 +625,9 @@ static int tr_lpdAnnounceMore(time_t const now, int const interval) return -1; } - while ((tor = tr_torrentNext(session, tor)) != nullptr && tr_sessionAllowsLPD(session)) + if (tr_sessionAllowsLPD(session)) { - if (tr_isTorrent(tor)) + for (auto* tor : session->torrents) { int announcePrio = 0;