refactor: use std container for session torrents (#1832)
* refactor: use std container for session's torrents
This commit is contained in:
parent
6c77fa92ce
commit
b92c609ed9
|
@ -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<tr_tier*>{};
|
||||
auto scrape_me = std::vector<tr_tier*>{};
|
||||
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;
|
||||
|
||||
|
|
|
@ -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<tr_peerMgr*>(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<tr_peerMgr*>(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<tr_peerMgr*>(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<tr_peerMgr*>(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;
|
||||
|
|
|
@ -6,14 +6,17 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
|
||||
#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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __HAIKU__
|
||||
#include <limits.h> /* PATH_MAX */
|
||||
#endif
|
||||
|
|
|
@ -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<tr_torrent*>
|
||||
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);
|
||||
|
|
|
@ -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<tr_session*>(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<tr_session*>(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_torrent*> 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<tr_torrent*>{ 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<tr_torrent*>{};
|
||||
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<tr_torrent const*>(va);
|
||||
auto const* const b = static_cast<tr_torrent const*>(vb);
|
||||
return a->uniqueId - b->uniqueId;
|
||||
}
|
||||
|
||||
static int compareTorrentsByHashString(void const* va, void const* vb)
|
||||
{
|
||||
auto const* const a = static_cast<tr_torrent const*>(va);
|
||||
auto const* const b = static_cast<tr_torrent const*>(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<tr_torrent const*>(va);
|
||||
auto const* const b = static_cast<tr_torrent const*>(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);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,13 @@
|
|||
|
||||
#define TR_NAME "Transmission"
|
||||
|
||||
#include <cstring> // memcmp()
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <event2/util.h> // 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<tr_torrent*> torrents;
|
||||
std::map<int, tr_torrent*> torrentsById;
|
||||
std::map<uint8_t const*, tr_torrent*, CompareHash> torrentsByHash;
|
||||
std::map<char const*, tr_torrent*, CompareHashString> 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_torrent*> 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
|
||||
|
|
|
@ -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<tr_torrent const*>(va);
|
||||
auto const b = *static_cast<int const*>(vb);
|
||||
return a->uniqueId - b;
|
||||
}
|
||||
|
||||
tr_torrent* tr_torrentFindFromId(tr_session* session, int id)
|
||||
{
|
||||
return static_cast<tr_torrent*>(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<tr_torrent const*>(va);
|
||||
auto const* const b = static_cast<char const*>(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_torrent*>(
|
||||
tr_ptrArrayFindSorted(&session->torrentsSortedByHashString, str, compareKeyToTorrentHashString));
|
||||
}
|
||||
|
||||
static int compareKeyToTorrentHash(void const* va, void const* vb)
|
||||
{
|
||||
auto const* const a = static_cast<tr_torrent const*>(va);
|
||||
auto const* const b = static_cast<uint8_t const*>(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_torrent*>(
|
||||
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))
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue