refactor: use smaller integral types in some structs (#3005)

This commit is contained in:
Charles Kerr 2022-04-27 20:06:51 -05:00 committed by GitHub
parent fca85c2f4d
commit bf655a921d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 221 additions and 203 deletions

View File

@ -156,10 +156,10 @@ bool refreshFilesForeach(
auto const old_progress = iter->get_value(file_cols.prog); auto const old_progress = iter->get_value(file_cols.prog);
auto const old_size = iter->get_value(file_cols.size); auto const old_size = iter->get_value(file_cols.size);
auto new_enabled = old_enabled; auto new_enabled = int{};
auto new_have = old_have; auto new_have = old_have;
auto new_priority = old_priority; auto new_priority = int{};
auto new_progress = old_progress; auto new_progress = int{};
auto new_size = old_size; auto new_size = old_size;
if (is_file) if (is_file)

View File

@ -121,10 +121,10 @@ bool tr_peerIsSeed(tr_peer const* peer);
struct tr_swarm_stats struct tr_swarm_stats
{ {
int activePeerCount[2]; uint16_t active_peer_count[2];
int activeWebseedCount; uint16_t active_webseed_count;
int peerCount; uint16_t peer_count;
int peerFromCount[TR_PEER_FROM__MAX]; uint16_t peer_from_count[TR_PEER_FROM__MAX];
}; };
void tr_swarmGetStats(tr_swarm const* swarm, tr_swarm_stats* setme); void tr_swarmGetStats(tr_swarm const* swarm, tr_swarm_stats* setme);

View File

@ -54,7 +54,7 @@ static auto constexpr RechokePeriodMsec = int{ 10 * 1000 };
// an optimistically unchoked peer is immune from rechoking // an optimistically unchoked peer is immune from rechoking
// for this many calls to rechokeUploads(). // for this many calls to rechokeUploads().
static auto constexpr OptimisticUnchokeMultiplier = int{ 4 }; static auto constexpr OptimisticUnchokeMultiplier = uint8_t{ 4 };
// how frequently to reallocate bandwidth // how frequently to reallocate bandwidth
static auto constexpr BandwidthPeriodMsec = int{ 500 }; static auto constexpr BandwidthPeriodMsec = int{ 500 };
@ -109,15 +109,12 @@ static auto constexpr CancelHistorySec = int{ 60 };
*/ */
struct peer_atom struct peer_atom
{ {
uint8_t fromFirst; /* where the peer was first found */ tr_address addr;
uint8_t fromBest; /* the "best" value of where the peer has been found */
uint8_t flags; /* these match the added_f flags */
uint8_t flags2; /* flags that aren't defined in added_f */
int8_t blocklisted; /* -1 for unknown, true for blocklisted, false for not blocklisted */
tr_port port; tr_port port;
bool utp_failed; /* We recently failed to connect over uTP */
uint16_t numFails; uint16_t num_fails;
time_t time; /* when the peer's connection status last changed */ time_t time; /* when the peer's connection status last changed */
time_t piece_data_time; time_t piece_data_time;
@ -127,8 +124,16 @@ struct peer_atom
/* similar to a TTL field, but less rigid -- /* similar to a TTL field, but less rigid --
* if the swarm is small, the atom will be kept past this date. */ * if the swarm is small, the atom will be kept past this date. */
time_t shelf_date; time_t shelf_date;
tr_peer* peer; /* will be nullptr if not connected */ tr_peer* peer; /* will be nullptr if not connected */
tr_address addr;
uint8_t fromFirst; /* where the peer was first found */
uint8_t fromBest; /* the "best" value of where the peer has been found */
uint8_t flags; /* these match the added_f flags */
uint8_t flags2; /* flags that aren't defined in added_f */
int8_t blocklisted; /* -1 for unknown, true for blocklisted, false for not blocklisted */
bool utp_failed; /* We recently failed to connect over uTP */
}; };
#ifndef TR_ENABLE_ASSERTS #ifndef TR_ENABLE_ASSERTS
@ -208,37 +213,42 @@ private:
class tr_swarm class tr_swarm
{ {
public: public:
tr_swarm(tr_peerMgr* manager_in, tr_torrent* tor_in) tr_swarm(tr_peerMgr* manager_in, tr_torrent* tor_in) noexcept
: manager{ manager_in } : manager{ manager_in }
, tor{ tor_in } , tor{ tor_in }
{ {
} }
public: public:
Handshakes outgoing_handshakes;
uint16_t interested_count = 0;
uint16_t max_peers = 0;
tr_swarm_stats stats = {}; tr_swarm_stats stats = {};
Handshakes outgoing_handshakes; uint8_t optimistic_unchoke_time_scaler = 0;
tr_ptrArray pool = {}; /* struct peer_atom */
tr_ptrArray peers = {}; /* tr_peerMsgs */ bool pool_is_all_seeds = false;
std::vector<std::unique_ptr<tr_peer>> webseeds; bool pool_is_all_seeds_dirty = true; /* true if pool_is_all_seeds needs to be recomputed */
bool is_running = false;
bool needs_completeness_check = true;
bool is_endgame = false;
tr_peerMgr* const manager; tr_peerMgr* const manager;
std::vector<std::unique_ptr<tr_peer>> webseeds;
tr_ptrArray pool = {}; /* struct peer_atom */
tr_ptrArray peers = {}; /* tr_peerMsgs */
tr_torrent* const tor; tr_torrent* const tor;
tr_peerMsgs* optimistic = nullptr; /* the optimistic peer, or nullptr if none */ tr_peerMsgs* optimistic = nullptr; /* the optimistic peer, or nullptr if none */
int optimisticUnchokeTimeScaler = 0;
bool poolIsAllSeeds = false; time_t lastCancel = 0;
bool poolIsAllSeedsDirty = true; /* true if poolIsAllSeeds needs to be recomputed */
bool isRunning = false;
bool needsCompletenessCheck = true;
bool endgame = false;
ActiveRequests active_requests; ActiveRequests active_requests;
int interestedCount = 0;
int maxPeers = 0;
time_t lastCancel = 0;
}; };
struct tr_peerMgr struct tr_peerMgr
@ -361,7 +371,7 @@ static void swarmFree(tr_swarm* s)
TR_ASSERT(s != nullptr); TR_ASSERT(s != nullptr);
auto const lock = s->manager->unique_lock(); auto const lock = s->manager->unique_lock();
TR_ASSERT(!s->isRunning); TR_ASSERT(!s->is_running);
TR_ASSERT(std::empty(s->outgoing_handshakes)); TR_ASSERT(std::empty(s->outgoing_handshakes));
TR_ASSERT(tr_ptrArrayEmpty(&s->peers)); TR_ASSERT(tr_ptrArrayEmpty(&s->peers));
@ -386,7 +396,7 @@ static void rebuildWebseedArray(tr_swarm* s, tr_torrent* tor)
} }
s->webseeds.shrink_to_fit(); s->webseeds.shrink_to_fit();
s->stats.activeWebseedCount = 0; s->stats.active_webseed_count = 0;
} }
static tr_swarm* swarmNew(tr_peerMgr* manager, tr_torrent* tor) static tr_swarm* swarmNew(tr_peerMgr* manager, tr_torrent* tor)
@ -478,7 +488,7 @@ static void atomSetSeed(tr_swarm* s, struct peer_atom* atom)
{ {
tr_logAddTraceSwarm(s, fmt::format("marking peer {} as a seed", tr_atomAddrStr(atom))); tr_logAddTraceSwarm(s, fmt::format("marking peer {} as a seed", tr_atomAddrStr(atom)));
atom->flags |= ADDED_F_SEED_FLAG; atom->flags |= ADDED_F_SEED_FLAG;
s->poolIsAllSeedsDirty = true; s->pool_is_all_seeds_dirty = true;
} }
bool tr_peerMgrPeerIsSeed(tr_torrent const* tor, tr_address const* addr) bool tr_peerMgrPeerIsSeed(tr_torrent const* tor, tr_address const* addr)
@ -532,7 +542,7 @@ void tr_peerMgrSetUtpFailed(tr_torrent* tor, tr_address const* addr, bool failed
*** struct block_request *** struct block_request
**/ **/
static int countActiveWebseeds(tr_swarm* s) [[nodiscard]] static uint16_t countActiveWebseeds(tr_swarm* s) noexcept
{ {
if (!s->tor->isRunning || s->tor->isDone()) if (!s->tor->isRunning || s->tor->isDone())
{ {
@ -562,7 +572,7 @@ static void updateEndgame(tr_swarm* s)
{ {
/* we consider ourselves to be in endgame if the number of bytes /* we consider ourselves to be in endgame if the number of bytes
we've got requested is >= the number of bytes left to download */ we've got requested is >= the number of bytes left to download */
s->endgame = uint64_t(std::size(s->active_requests)) * tr_block_info::BlockSize >= s->tor->leftUntilDone(); s->is_endgame = uint64_t(std::size(s->active_requests)) * tr_block_info::BlockSize >= s->tor->leftUntilDone();
} }
std::vector<tr_block_span_t> tr_peerMgrGetNextRequests(tr_torrent* torrent, tr_peer const* peer, size_t numwant) std::vector<tr_block_span_t> tr_peerMgrGetNextRequests(tr_torrent* torrent, tr_peer const* peer, size_t numwant)
@ -591,7 +601,7 @@ std::vector<tr_block_span_t> tr_peerMgrGetNextRequests(tr_torrent* torrent, tr_p
[[nodiscard]] bool isEndgame() const override [[nodiscard]] bool isEndgame() const override
{ {
return swarm_->endgame; return swarm_->is_endgame;
} }
[[nodiscard]] size_t countActiveRequests(tr_block_index_t block) const override [[nodiscard]] size_t countActiveRequests(tr_block_index_t block) const override
@ -776,7 +786,7 @@ void tr_peerMgrPieceCompleted(tr_torrent* tor, tr_piece_index_t p)
} }
/* bookkeeping */ /* bookkeeping */
s->needsCompletenessCheck = true; s->needs_completeness_check = true;
} }
static void peerCallbackFunc(tr_peer* peer, tr_peer_event const* e, void* vs) static void peerCallbackFunc(tr_peer* peer, tr_peer_event const* e, void* vs)
@ -959,14 +969,14 @@ static struct peer_atom* ensureAtomExists(
a->flags |= flags; a->flags |= flags;
} }
s->poolIsAllSeedsDirty = true; s->pool_is_all_seeds_dirty = true;
return a; return a;
} }
static int getMaxPeerCount(tr_torrent const* tor) [[nodiscard]] static constexpr auto getMaxPeerCount(tr_torrent const* tor) noexcept
{ {
return tor->maxConnectedPeers; return tor->max_connected_peers;
} }
static int getPeerCount(tr_swarm const* s) static int getPeerCount(tr_swarm const* s)
@ -987,11 +997,11 @@ static void createBitTorrentPeer(tr_torrent* tor, tr_peerIo* io, struct peer_ato
atom->peer = peer; atom->peer = peer;
tr_ptrArrayInsertSorted(&swarm->peers, peer, peerCompare); tr_ptrArrayInsertSorted(&swarm->peers, peer, peerCompare);
++swarm->stats.peerCount; ++swarm->stats.peer_count;
++swarm->stats.peerFromCount[atom->fromFirst]; ++swarm->stats.peer_from_count[atom->fromFirst];
TR_ASSERT(swarm->stats.peerCount == tr_ptrArraySize(&swarm->peers)); TR_ASSERT(swarm->stats.peer_count == tr_ptrArraySize(&swarm->peers));
TR_ASSERT(swarm->stats.peerFromCount[atom->fromFirst] <= swarm->stats.peerCount); TR_ASSERT(swarm->stats.peer_from_count[atom->fromFirst] <= swarm->stats.peer_count);
// TODO is this needed? // TODO is this needed?
// isn't it already initialized in tr_peerMsgsImpl's ctor? // isn't it already initialized in tr_peerMsgsImpl's ctor?
@ -1025,7 +1035,7 @@ static bool on_handshake_done(tr_handshake_result const& result)
auto const lock = manager->unique_lock(); auto const lock = manager->unique_lock();
if (!ok || s == nullptr || !s->isRunning) if (!ok || s == nullptr || !s->is_running)
{ {
if (s != nullptr) if (s != nullptr)
{ {
@ -1033,13 +1043,16 @@ static bool on_handshake_done(tr_handshake_result const& result)
if (atom != nullptr) if (atom != nullptr)
{ {
++atom->numFails; ++atom->num_fails;
if (!result.readAnythingFromPeer) if (!result.readAnythingFromPeer)
{ {
tr_logAddTraceSwarm( tr_logAddTraceSwarm(
s, s,
fmt::format("marking peer {} as unreachable... numFails is {}", tr_atomAddrStr(atom), atom->numFails)); fmt::format(
"marking peer {} as unreachable... num_fails is {}",
tr_atomAddrStr(atom),
atom->num_fails));
atom->flags2 |= MyflagUnreachable; atom->flags2 |= MyflagUnreachable;
} }
} }
@ -1144,8 +1157,8 @@ void tr_peerMgrSetSwarmIsAllSeeds(tr_torrent* tor)
atomSetSeed(swarm, atoms[i]); atomSetSeed(swarm, atoms[i]);
} }
swarm->poolIsAllSeeds = true; swarm->pool_is_all_seeds = true;
swarm->poolIsAllSeedsDirty = false; swarm->pool_is_all_seeds_dirty = false;
} }
size_t tr_peerMgrAddPex(tr_torrent* tor, uint8_t from, tr_pex const* pex, size_t n_pex) size_t tr_peerMgrAddPex(tr_torrent* tor, uint8_t from, tr_pex const* pex, size_t n_pex)
@ -1277,9 +1290,9 @@ static int compareAtomsByUsefulness(void const* va, void const* vb)
return a->fromBest < b->fromBest ? -1 : 1; return a->fromBest < b->fromBest ? -1 : 1;
} }
if (a->numFails != b->numFails) if (a->num_fails != b->num_fails)
{ {
return a->numFails < b->numFails ? -1 : 1; return a->num_fails < b->num_fails ? -1 : 1;
} }
return 0; return 0;
@ -1441,8 +1454,8 @@ void tr_peerMgrStartTorrent(tr_torrent* tor)
ensureMgrTimersExist(s->manager); ensureMgrTimersExist(s->manager);
s->isRunning = true; s->is_running = true;
s->maxPeers = tor->maxConnectedPeers; s->max_peers = getMaxPeerCount(tor);
// rechoke soon // rechoke soon
tr_timerAddMsec(*s->manager->rechokeTimer, 100); tr_timerAddMsec(*s->manager->rechokeTimer, 100);
@ -1452,7 +1465,7 @@ static void removeAllPeers(tr_swarm* /*swarm*/);
static void stopSwarm(tr_swarm* swarm) static void stopSwarm(tr_swarm* swarm)
{ {
swarm->isRunning = false; swarm->is_running = false;
removeAllPeers(swarm); removeAllPeers(swarm);
@ -1588,7 +1601,7 @@ void tr_swarmGetStats(tr_swarm const* swarm, tr_swarm_stats* setme)
void tr_swarmIncrementActivePeers(tr_swarm* swarm, tr_direction direction, bool is_active) void tr_swarmIncrementActivePeers(tr_swarm* swarm, tr_direction direction, bool is_active)
{ {
int n = swarm->stats.activePeerCount[direction]; int n = swarm->stats.active_peer_count[direction];
if (is_active) if (is_active)
{ {
@ -1600,9 +1613,9 @@ void tr_swarmIncrementActivePeers(tr_swarm* swarm, tr_direction direction, bool
} }
TR_ASSERT(n >= 0); TR_ASSERT(n >= 0);
TR_ASSERT(n <= swarm->stats.peerCount); TR_ASSERT(n <= swarm->stats.peer_count);
swarm->stats.activePeerCount[direction] = n; swarm->stats.active_peer_count[direction] = n;
} }
bool tr_peerIsSeed(tr_peer const* peer) bool tr_peerIsSeed(tr_peer const* peer)
@ -1623,7 +1636,7 @@ uint64_t tr_peerMgrGetDesiredAvailable(tr_torrent const* tor)
} }
tr_swarm const* const s = tor->swarm; tr_swarm const* const s = tor->swarm;
if (s == nullptr || !s->isRunning) if (s == nullptr || !s->is_running)
{ {
return 0; return 0;
} }
@ -1871,10 +1884,11 @@ static constexpr int compare_rechoke_info(void const* va, void const* vb)
/* determines who we send "interested" messages to */ /* determines who we send "interested" messages to */
static void rechokeDownloads(tr_swarm* s) static void rechokeDownloads(tr_swarm* s)
{ {
int maxPeers = 0; static auto constexpr MinInterestingPeers = uint16_t{ 5 };
int rechoke_count = 0;
uint16_t max_peers = 0;
uint16_t rechoke_count = 0;
struct tr_rechoke_info* rechoke = nullptr; struct tr_rechoke_info* rechoke = nullptr;
auto constexpr MinInterestingPeers = 5;
int const peerCount = tr_ptrArraySize(&s->peers); int const peerCount = tr_ptrArraySize(&s->peers);
time_t const now = tr_time(); time_t const now = tr_time();
@ -1924,7 +1938,7 @@ static void rechokeDownloads(tr_swarm* s)
* higher values indicate more congestion. */ * higher values indicate more congestion. */
double const cancelRate = cancels / (double)(cancels + blocks); double const cancelRate = cancels / (double)(cancels + blocks);
double const mult = 1 - std::min(cancelRate, 0.5); double const mult = 1 - std::min(cancelRate, 0.5);
maxPeers = s->interestedCount * mult; max_peers = s->interested_count * mult;
tr_logAddTraceSwarm( tr_logAddTraceSwarm(
s, s,
fmt::format( fmt::format(
@ -1942,7 +1956,7 @@ static void rechokeDownloads(tr_swarm* s)
time_t const maxHistory = 2 * CancelHistorySec; time_t const maxHistory = 2 * CancelHistorySec;
double const mult = std::min(timeSinceCancel, maxHistory) / (double)maxHistory; double const mult = std::min(timeSinceCancel, maxHistory) / (double)maxHistory;
int const inc = maxIncrease * mult; int const inc = maxIncrease * mult;
maxPeers = s->maxPeers + inc; max_peers = s->max_peers + inc;
tr_logAddTraceSwarm( tr_logAddTraceSwarm(
s, s,
fmt::format( fmt::format(
@ -1953,9 +1967,9 @@ static void rechokeDownloads(tr_swarm* s)
} }
/* don't let the previous section's number tweaking go too far... */ /* don't let the previous section's number tweaking go too far... */
maxPeers = std::clamp(maxPeers, MinInterestingPeers, int(s->tor->maxConnectedPeers)); max_peers = std::clamp(max_peers, MinInterestingPeers, s->tor->max_connected_peers);
s->maxPeers = maxPeers; s->max_peers = max_peers;
if (peerCount > 0) if (peerCount > 0)
{ {
@ -2028,11 +2042,11 @@ static void rechokeDownloads(tr_swarm* s)
/* now that we know which & how many peers to be interested in... update the peer interest */ /* now that we know which & how many peers to be interested in... update the peer interest */
s->interestedCount = std::min(maxPeers, rechoke_count); s->interested_count = std::min(max_peers, rechoke_count);
for (int i = 0; i < rechoke_count; ++i) for (int i = 0; i < rechoke_count; ++i)
{ {
rechoke[i].peer->set_interested(i < s->interestedCount); rechoke[i].peer->set_interested(i < s->interested_count);
} }
/* cleanup */ /* cleanup */
@ -2134,9 +2148,9 @@ static void rechokeUploads(tr_swarm* s, uint64_t const now)
/* an optimistic unchoke peer's "optimistic" /* an optimistic unchoke peer's "optimistic"
* state lasts for N calls to rechokeUploads(). */ * state lasts for N calls to rechokeUploads(). */
if (s->optimisticUnchokeTimeScaler > 0) if (s->optimistic_unchoke_time_scaler > 0)
{ {
s->optimisticUnchokeTimeScaler--; --s->optimistic_unchoke_time_scaler;
} }
else else
{ {
@ -2230,7 +2244,7 @@ static void rechokeUploads(tr_swarm* s, uint64_t const now)
auto* c = randPool[tr_rand_int_weak(n)]; auto* c = randPool[tr_rand_int_weak(n)];
c->isChoked = false; c->isChoked = false;
s->optimistic = c->msgs; s->optimistic = c->msgs;
s->optimisticUnchokeTimeScaler = OptimisticUnchokeMultiplier; s->optimistic_unchoke_time_scaler = OptimisticUnchokeMultiplier;
} }
} }
@ -2255,7 +2269,7 @@ static void rechokePulse(evutil_socket_t /*fd*/, short /*what*/, void* vmgr)
{ {
tr_swarm* s = tor->swarm; tr_swarm* s = tor->swarm;
if (s->stats.peerCount > 0) if (s->stats.peer_count > 0)
{ {
rechokeUploads(s, now); rechokeUploads(s, now);
rechokeDownloads(s); rechokeDownloads(s);
@ -2334,7 +2348,7 @@ static int getReconnectIntervalSecs(struct peer_atom const* atom, time_t const n
* and failed to connect to the peer */ * and failed to connect to the peer */
else else
{ {
int step = atom->numFails; auto step = atom->num_fails;
/* penalize peers that were unreachable the last time we tried */ /* penalize peers that were unreachable the last time we tried */
if (unreachable) if (unreachable)
@ -2389,11 +2403,11 @@ static void removePeer(tr_peer* peer)
atom->time = tr_time(); atom->time = tr_time();
tr_ptrArrayRemoveSortedPointer(&s->peers, peer, peerCompare); tr_ptrArrayRemoveSortedPointer(&s->peers, peer, peerCompare);
--s->stats.peerCount; --s->stats.peer_count;
--s->stats.peerFromCount[atom->fromFirst]; --s->stats.peer_from_count[atom->fromFirst];
TR_ASSERT(s->stats.peerCount == tr_ptrArraySize(&s->peers)); TR_ASSERT(s->stats.peer_count == tr_ptrArraySize(&s->peers));
TR_ASSERT(s->stats.peerFromCount[atom->fromFirst] >= 0); TR_ASSERT(s->stats.peer_from_count[atom->fromFirst] >= 0);
delete peer; delete peer;
} }
@ -2404,17 +2418,17 @@ static void closePeer(tr_peer* peer)
auto const* const s = peer->swarm; auto const* const s = peer->swarm;
/* if we transferred piece data, then they might be good peers, /* if we transferred piece data, then they might be good peers,
so reset their `numFails' weight to zero. otherwise we connected so reset their `num_fails' weight to zero. otherwise we connected
to them fruitlessly, so mark it as another fail */ to them fruitlessly, so mark it as another fail */
if (auto* const atom = peer->atom; atom->piece_data_time != 0) if (auto* const atom = peer->atom; atom->piece_data_time != 0)
{ {
tr_logAddTraceSwarm(s, fmt::format("resetting atom {} numFails to 0", tr_atomAddrStr(atom))); tr_logAddTraceSwarm(s, fmt::format("resetting atom {} num_fails to 0", tr_atomAddrStr(atom)));
atom->numFails = 0; atom->num_fails = 0;
} }
else else
{ {
++atom->numFails; ++atom->num_fails;
tr_logAddTraceSwarm(s, fmt::format("incremented atom {} numFails to {}", tr_atomAddrStr(atom), atom->numFails)); tr_logAddTraceSwarm(s, fmt::format("incremented atom {} num_fails to {}", tr_atomAddrStr(atom), atom->num_fails));
} }
tr_logAddTraceSwarm(s, fmt::format("removing bad peer {}", tr_atomAddrStr(peer->atom))); tr_logAddTraceSwarm(s, fmt::format("removing bad peer {}", tr_atomAddrStr(peer->atom)));
@ -2430,7 +2444,7 @@ static void removeAllPeers(tr_swarm* swarm)
removePeer(peer); removePeer(peer);
} }
TR_ASSERT(swarm->stats.peerCount == 0); TR_ASSERT(swarm->stats.peer_count == 0);
} }
static auto getPeersToClose(tr_swarm* s, time_t const now_sec) static auto getPeersToClose(tr_swarm* s, time_t const now_sec)
@ -2546,7 +2560,7 @@ static void reconnectPulse(evutil_socket_t /*fd*/, short /*what*/, void* vmgr)
// remove crappy peers // remove crappy peers
for (auto* const tor : mgr->session->torrents()) for (auto* const tor : mgr->session->torrents())
{ {
if (!tor->swarm->isRunning) if (!tor->swarm->is_running)
{ {
removeAllPeers(tor->swarm); removeAllPeers(tor->swarm);
} }
@ -2632,9 +2646,9 @@ static void bandwidthPulse(evutil_socket_t /*fd*/, short /*what*/, void* vmgr)
tr_torrentCheckSeedLimit(tor); tr_torrentCheckSeedLimit(tor);
/* run the completeness check for any torrents that need it */ /* run the completeness check for any torrents that need it */
if (tor->swarm->needsCompletenessCheck) if (tor->swarm->needs_completeness_check)
{ {
tor->swarm->needsCompletenessCheck = false; tor->swarm->needs_completeness_check = false;
tor->recheckCompleteness(); tor->recheckCompleteness();
} }
@ -2646,7 +2660,7 @@ static void bandwidthPulse(evutil_socket_t /*fd*/, short /*what*/, void* vmgr)
} }
/* update the torrent's stats */ /* update the torrent's stats */
tor->swarm->stats.activeWebseedCount = countActiveWebseeds(tor->swarm); tor->swarm->stats.active_webseed_count = countActiveWebseeds(tor->swarm);
} }
/* pump the queues */ /* pump the queues */
@ -2714,9 +2728,12 @@ static int compareAtomPtrsByShelfDate(void const* va, void const* vb)
return 0; return 0;
} }
static int getMaxAtomCount(tr_torrent const* tor) static auto getMaxAtomCount(tr_torrent const* tor)
{ {
return std::min(50, tor->maxConnectedPeers * 3); static auto constexpr Limit = uint16_t{ 50 };
static auto constexpr Multiplier = uint16_t{ 3 };
return std::min(Limit, static_cast<uint16_t>(tor->max_connected_peers * Multiplier));
} }
static void atomPulse(evutil_socket_t /*fd*/, short /*what*/, void* vmgr) static void atomPulse(evutil_socket_t /*fd*/, short /*what*/, void* vmgr)
@ -2933,13 +2950,13 @@ static bool calculateAllSeeds(tr_swarm* swarm)
static bool swarmIsAllSeeds(tr_swarm* swarm) static bool swarmIsAllSeeds(tr_swarm* swarm)
{ {
if (swarm->poolIsAllSeedsDirty) if (swarm->pool_is_all_seeds_dirty)
{ {
swarm->poolIsAllSeeds = calculateAllSeeds(swarm); swarm->pool_is_all_seeds = calculateAllSeeds(swarm);
swarm->poolIsAllSeedsDirty = false; swarm->pool_is_all_seeds_dirty = false;
} }
return swarm->poolIsAllSeeds; return swarm->pool_is_all_seeds;
} }
/** @return an array of all the atoms we might want to connect to */ /** @return an array of all the atoms we might want to connect to */
@ -2971,7 +2988,7 @@ static std::vector<peer_candidate> getPeerCandidates(tr_session* session, size_t
/* populate the candidate array */ /* populate the candidate array */
for (auto* tor : session->torrents()) for (auto* tor : session->torrents())
{ {
if (!tor->swarm->isRunning) if (!tor->swarm->is_running)
{ {
continue; continue;
} }
@ -3056,7 +3073,7 @@ static void initiateConnection(tr_peerMgr* mgr, tr_swarm* s, struct peer_atom* a
{ {
tr_logAddTraceSwarm(s, fmt::format("peerIo not created; marking peer {} as unreachable", tr_atomAddrStr(atom))); tr_logAddTraceSwarm(s, fmt::format("peerIo not created; marking peer {} as unreachable", tr_atomAddrStr(atom)));
atom->flags2 |= MyflagUnreachable; atom->flags2 |= MyflagUnreachable;
atom->numFails++; ++atom->num_fails;
} }
else else
{ {

View File

@ -742,7 +742,7 @@ static auto loadFromFile(tr_torrent* tor, tr_resume::fields_t fieldsToLoad, bool
if ((fieldsToLoad & tr_resume::MaxPeers) != 0 && tr_variantDictFindInt(&top, TR_KEY_max_peers, &i)) if ((fieldsToLoad & tr_resume::MaxPeers) != 0 && tr_variantDictFindInt(&top, TR_KEY_max_peers, &i))
{ {
tor->maxConnectedPeers = i; tor->max_connected_peers = static_cast<uint16_t>(i);
fields_loaded |= tr_resume::MaxPeers; fields_loaded |= tr_resume::MaxPeers;
} }
@ -873,7 +873,7 @@ static auto setFromCtor(tr_torrent* tor, tr_resume::fields_t fields, tr_ctor con
} }
} }
if (((fields & tr_resume::MaxPeers) != 0) && tr_ctorGetPeerLimit(ctor, mode, &tor->maxConnectedPeers)) if (((fields & tr_resume::MaxPeers) != 0) && tr_ctorGetPeerLimit(ctor, mode, &tor->max_connected_peers))
{ {
ret |= tr_resume::MaxPeers; ret |= tr_resume::MaxPeers;
} }
@ -943,7 +943,7 @@ void save(tr_torrent* tor)
tr_variantDictAddInt(&top, TR_KEY_downloaded, tor->downloadedPrev + tor->downloadedCur); 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_uploaded, tor->uploadedPrev + tor->uploadedCur);
tr_variantDictAddInt(&top, TR_KEY_max_peers, tor->maxConnectedPeers); tr_variantDictAddInt(&top, TR_KEY_max_peers, tor->max_connected_peers);
tr_variantDictAddInt(&top, TR_KEY_bandwidth_priority, tr_torrentGetPriority(tor)); tr_variantDictAddInt(&top, TR_KEY_bandwidth_priority, tr_torrentGetPriority(tor));
tr_variantDictAddBool(&top, TR_KEY_paused, !tor->isRunning && !tor->isQueued()); tr_variantDictAddBool(&top, TR_KEY_paused, !tor->isRunning && !tor->isQueued());
savePeers(&top, tor); savePeers(&top, tor);

View File

@ -654,7 +654,7 @@ static void initField(tr_torrent const* const tor, tr_stat const* const st, tr_v
case TR_KEY_peersFrom: case TR_KEY_peersFrom:
{ {
tr_variantInitDict(initme, 7); tr_variantInitDict(initme, 7);
int const* f = st->peersFrom; auto const* f = st->peersFrom;
tr_variantDictAddInt(initme, TR_KEY_fromCache, f[TR_PEER_FROM_RESUME]); tr_variantDictAddInt(initme, TR_KEY_fromCache, f[TR_PEER_FROM_RESUME]);
tr_variantDictAddInt(initme, TR_KEY_fromDht, f[TR_PEER_FROM_DHT]); tr_variantDictAddInt(initme, TR_KEY_fromDht, f[TR_PEER_FROM_DHT]);
tr_variantDictAddInt(initme, TR_KEY_fromIncoming, f[TR_PEER_FROM_INCOMING]); tr_variantDictAddInt(initme, TR_KEY_fromIncoming, f[TR_PEER_FROM_INCOMING]);

View File

@ -1045,14 +1045,14 @@ tr_stat const* tr_torrentStat(tr_torrent* tor)
s->errorString = tor->error_string.c_str(); s->errorString = tor->error_string.c_str();
s->manualAnnounceTime = tr_announcerNextManualAnnounce(tor); s->manualAnnounceTime = tr_announcerNextManualAnnounce(tor);
s->peersConnected = swarm_stats.peerCount; s->peersConnected = swarm_stats.peer_count;
s->peersSendingToUs = swarm_stats.activePeerCount[TR_DOWN]; s->peersSendingToUs = swarm_stats.active_peer_count[TR_DOWN];
s->peersGettingFromUs = swarm_stats.activePeerCount[TR_UP]; s->peersGettingFromUs = swarm_stats.active_peer_count[TR_UP];
s->webseedsSendingToUs = swarm_stats.activeWebseedCount; s->webseedsSendingToUs = swarm_stats.active_webseed_count;
for (int i = 0; i < TR_PEER_FROM__MAX; i++) for (int i = 0; i < TR_PEER_FROM__MAX; i++)
{ {
s->peersFrom[i] = swarm_stats.peerFromCount[i]; s->peersFrom[i] = swarm_stats.peer_from_count[i];
} }
s->rawUploadSpeed_KBps = tr_toSpeedKBps(tor->bandwidth_.getRawSpeedBytesPerSecond(now, TR_UP)); s->rawUploadSpeed_KBps = tr_toSpeedKBps(tor->bandwidth_.getRawSpeedBytesPerSecond(now, TR_UP));
@ -1980,13 +1980,13 @@ void tr_torrentSetPriority(tr_torrent* tor, tr_priority_t priority)
**** ****
***/ ***/
void tr_torrentSetPeerLimit(tr_torrent* tor, uint16_t maxConnectedPeers) void tr_torrentSetPeerLimit(tr_torrent* tor, uint16_t max_connected_peers)
{ {
TR_ASSERT(tr_isTorrent(tor)); TR_ASSERT(tr_isTorrent(tor));
if (tor->maxConnectedPeers != maxConnectedPeers) if (tor->max_connected_peers != max_connected_peers)
{ {
tor->maxConnectedPeers = maxConnectedPeers; tor->max_connected_peers = max_connected_peers;
tor->setDirty(); tor->setDirty();
} }
@ -1996,7 +1996,7 @@ uint16_t tr_torrentGetPeerLimit(tr_torrent const* tor)
{ {
TR_ASSERT(tr_isTorrent(tor)); TR_ASSERT(tr_isTorrent(tor));
return tor->maxConnectedPeers; return tor->max_connected_peers;
} }
/*** /***

View File

@ -73,7 +73,7 @@ void tr_torrentCheckSeedLimit(tr_torrent* tor);
/** save a torrent's .resume file if it's changed since the last time it was saved */ /** save a torrent's .resume file if it's changed since the last time it was saved */
void tr_torrentSave(tr_torrent* tor); void tr_torrentSave(tr_torrent* tor);
enum tr_verify_state enum tr_verify_state : uint8_t
{ {
TR_VERIFY_NONE, TR_VERIFY_NONE,
TR_VERIFY_WAIT, TR_VERIFY_WAIT,
@ -699,7 +699,7 @@ public:
void markEdited(); void markEdited();
void markChanged(); void markChanged();
uint16_t maxConnectedPeers = TR_DEFAULT_PEER_LIMIT_TORRENT; uint16_t max_connected_peers = TR_DEFAULT_PEER_LIMIT_TORRENT;
time_t lastStatTime = 0; time_t lastStatTime = 0;
tr_stat stats = {}; tr_stat stats = {};

View File

@ -1497,21 +1497,69 @@ enum tr_stat_errtype
/** @brief Used by tr_torrentStat() to tell clients about a torrent's state and statistics */ /** @brief Used by tr_torrentStat() to tell clients about a torrent's state and statistics */
struct tr_stat struct tr_stat
{ {
/** The torrent's unique Id.
@see tr_torrentId() */
int id;
/** What is this torrent doing right now? */
tr_torrent_activity activity;
/** Defines what kind of text is in errorString.
@see errorString */
tr_stat_errtype error;
/** A warning or error message regarding the torrent. /** A warning or error message regarding the torrent.
@see error */ @see error */
char const* errorString; char const* errorString;
/** 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_torrentTotalSize()
if only some of the torrent's files are wanted.
[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_stat.sizeWhenDone] */
uint64_t leftUntilDone;
/** Byte count of all the piece data we want and don't have yet,
but that a connected peer does have. [0...leftUntilDone] */
uint64_t desiredAvailable;
/** Byte count of all the corrupt data you've ever downloaded for
this torrent. If you're on a poisoned torrent, this number can
grow very large. */
uint64_t corruptEver;
/** Byte count of all data you've ever uploaded for this torrent. */
uint64_t uploadedEver;
/** Byte count of all the non-corrupt data you've ever downloaded
for this torrent. If you deleted the files and downloaded a second
time, this will be 2*totalSize.. */
uint64_t downloadedEver;
/** Byte count of all the checksum-verified data we have for this torrent.
*/
uint64_t haveValid;
/** Byte count of all the partial piece data we have for this torrent.
As pieces become complete, this value may decrease as portions of it
are moved to `corrupt' or `haveValid'. */
uint64_t haveUnchecked;
/** time when one or more of the torrent's trackers will
allow you to manually ask for more peers,
or 0 if you can't */
time_t manualAnnounceTime;
/** When the torrent was first added. */
time_t addedDate;
/** When the torrent finished downloading. */
time_t doneDate;
/** When the torrent was last started. */
time_t startDate;
/** The last time we uploaded or downloaded piece data on this torrent. */
time_t activityDate;
/** The last time during this session that a rarely-changing field
changed -- e.g. any tr_torrent_metainfo field (trackers, filenames, name)
or download directory. RPC clients can monitor this to know when
to reload fields that rarely change. */
time_t editDate;
/** When tr_stat.activity is TR_STATUS_CHECK or TR_STATUS_CHECK_WAIT, /** When tr_stat.activity is TR_STATUS_CHECK or TR_STATUS_CHECK_WAIT,
this is the percentage of how much of the files has been this is the percentage of how much of the files has been
verified. When it gets to 1, the verify process is done. verified. When it gets to 1, the verify process is done.
@ -1556,93 +1604,14 @@ struct tr_stat
This ONLY counts piece data. */ This ONLY counts piece data. */
float pieceDownloadSpeed_KBps; float pieceDownloadSpeed_KBps;
#define TR_ETA_NOT_AVAIL (-1)
#define TR_ETA_UNKNOWN (-2)
/** If downloading, estimated number of seconds left until the torrent is done.
If seeding, estimated number of seconds left until seed ratio is reached. */
int eta;
/** If seeding, number of seconds left until the idle time limit is reached. */
int etaIdle;
/** Number of peers that we're connected to */
int peersConnected;
/** How many peers we found out about from the tracker, or from pex,
or from incoming connections, or from our resume file. */
int peersFrom[TR_PEER_FROM__MAX];
/** Number of peers that are sending data to us. */
int peersSendingToUs;
/** Number of peers that we're sending data to */
int peersGettingFromUs;
/** Number of webseeds that are sending data to us. */
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_torrentTotalSize()
if only some of the torrent's files are wanted.
[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_stat.sizeWhenDone] */
uint64_t leftUntilDone;
/** Byte count of all the piece data we want and don't have yet,
but that a connected peer does have. [0...leftUntilDone] */
uint64_t desiredAvailable;
/** Byte count of all the corrupt data you've ever downloaded for
this torrent. If you're on a poisoned torrent, this number can
grow very large. */
uint64_t corruptEver;
/** Byte count of all data you've ever uploaded for this torrent. */
uint64_t uploadedEver;
/** Byte count of all the non-corrupt data you've ever downloaded
for this torrent. If you deleted the files and downloaded a second
time, this will be 2*totalSize.. */
uint64_t downloadedEver;
/** Byte count of all the checksum-verified data we have for this torrent.
*/
uint64_t haveValid;
/** Byte count of all the partial piece data we have for this torrent.
As pieces become complete, this value may decrease as portions of it
are moved to `corrupt' or `haveValid'. */
uint64_t haveUnchecked;
/** time when one or more of the torrent's trackers will
allow you to manually ask for more peers,
or 0 if you can't */
time_t manualAnnounceTime;
/** Total uploaded bytes / sizeWhenDone. /** Total uploaded bytes / sizeWhenDone.
NB: In Transmission 3.00 and earlier, this was total upload / download, NB: In Transmission 3.00 and earlier, this was total upload / download,
which caused edge cases when total download was less than sizeWhenDone. */ which caused edge cases when total download was less than sizeWhenDone. */
float ratio; float ratio;
/** When the torrent was first added. */ /** The torrent's unique Id.
time_t addedDate; @see tr_torrentId() */
int id;
/** When the torrent finished downloading. */
time_t doneDate;
/** When the torrent was last started. */
time_t startDate;
/** The last time we uploaded or downloaded piece data on this torrent. */
time_t activityDate;
/** The last time during this session that a rarely-changing field
changed -- e.g. any tr_torrent_metainfo field (trackers, filenames, name)
or download directory. RPC clients can monitor this to know when
to reload fields that rarely change. */
time_t editDate;
/** Number of seconds since the last activity (or since started). /** Number of seconds since the last activity (or since started).
-1 if activity is not seeding or downloading. */ -1 if activity is not seeding or downloading. */
@ -1658,6 +1627,38 @@ struct tr_stat
All torrents have a queue position, even if it's not queued. */ All torrents have a queue position, even if it's not queued. */
int queuePosition; int queuePosition;
#define TR_ETA_NOT_AVAIL (-1)
#define TR_ETA_UNKNOWN (-2)
/** If downloading, estimated number of seconds left until the torrent is done.
If seeding, estimated number of seconds left until seed ratio is reached. */
int eta;
/** If seeding, number of seconds left until the idle time limit is reached. */
int etaIdle;
/** What is this torrent doing right now? */
tr_torrent_activity activity;
/** Defines what kind of text is in errorString.
@see errorString */
tr_stat_errtype error;
/** Number of peers that we're connected to */
uint16_t peersConnected;
/** How many peers we found out about from the tracker, or from pex,
or from incoming connections, or from our resume file. */
uint16_t peersFrom[TR_PEER_FROM__MAX];
/** Number of peers that are sending data to us. */
uint16_t peersSendingToUs;
/** Number of peers that we're sending data to */
uint16_t peersGettingFromUs;
/** Number of webseeds that are sending data to us. */
uint16_t webseedsSendingToUs;
/** A torrent is considered finished if it has met its seed ratio. /** A torrent is considered finished if it has met its seed ratio.
As a result, only paused torrents can be finished. */ As a result, only paused torrents can be finished. */
bool finished; bool finished;