refactor: remove peer-mgr replication info (#2021)
* refactor: remove peer-mgr replication info Co-authored-by: Mike Gelfand <mikedld@users.noreply.github.com>
This commit is contained in:
parent
81147a8fbb
commit
a1c5a215bf
|
@ -204,13 +204,6 @@ public:
|
|||
int pieceCount = 0;
|
||||
enum piece_sort_state pieceSortState = PIECES_UNSORTED;
|
||||
|
||||
/* An array of pieceCount items stating how many peers have each piece.
|
||||
This is used to help us for downloading pieces "rarest first."
|
||||
This may be nullptr if we don't have metainfo yet, or if we're not
|
||||
downloading and don't care about rarity */
|
||||
uint16_t* pieceReplication = nullptr;
|
||||
size_t pieceReplicationSize = 0;
|
||||
|
||||
int interestedCount = 0;
|
||||
int maxPeers = 0;
|
||||
time_t lastCancel = 0;
|
||||
|
@ -374,13 +367,13 @@ static int peerCompare(void const* va, void const* vb)
|
|||
|
||||
static struct peer_atom* getExistingAtom(tr_swarm const* cswarm, tr_address const* addr)
|
||||
{
|
||||
tr_swarm* swarm = (tr_swarm*)cswarm;
|
||||
auto* swarm = const_cast<tr_swarm*>(cswarm);
|
||||
return static_cast<struct peer_atom*>(tr_ptrArrayFindSorted(&swarm->pool, addr, comparePeerAtomToAddress));
|
||||
}
|
||||
|
||||
static bool peerIsInUse(tr_swarm const* cs, struct peer_atom const* atom)
|
||||
{
|
||||
tr_swarm* s = (tr_swarm*)cs;
|
||||
auto* s = const_cast<tr_swarm*>(cs);
|
||||
|
||||
TR_ASSERT(swarmIsLocked(s));
|
||||
|
||||
|
@ -388,46 +381,6 @@ static bool peerIsInUse(tr_swarm const* cs, struct peer_atom const* atom)
|
|||
getExistingHandshake(&s->manager->incomingHandshakes, &atom->addr) != nullptr;
|
||||
}
|
||||
|
||||
static constexpr bool replicationExists(tr_swarm const* s)
|
||||
{
|
||||
return s->pieceReplication != nullptr;
|
||||
}
|
||||
|
||||
static void replicationFree(tr_swarm* s)
|
||||
{
|
||||
tr_free(s->pieceReplication);
|
||||
s->pieceReplication = nullptr;
|
||||
s->pieceReplicationSize = 0;
|
||||
}
|
||||
|
||||
static void replicationNew(tr_swarm* s)
|
||||
{
|
||||
TR_ASSERT(!replicationExists(s));
|
||||
|
||||
tr_piece_index_t const piece_count = s->tor->info.pieceCount;
|
||||
int const n = tr_ptrArraySize(&s->peers);
|
||||
|
||||
s->pieceReplicationSize = piece_count;
|
||||
s->pieceReplication = tr_new0(uint16_t, piece_count);
|
||||
|
||||
for (tr_piece_index_t piece_i = 0; piece_i < piece_count; ++piece_i)
|
||||
{
|
||||
uint16_t r = 0;
|
||||
|
||||
for (int peer_i = 0; peer_i < n; ++peer_i)
|
||||
{
|
||||
auto const* const peer = static_cast<tr_peer const*>(tr_ptrArrayNth(&s->peers, peer_i));
|
||||
|
||||
if (peer->have.test(piece_i))
|
||||
{
|
||||
++r;
|
||||
}
|
||||
}
|
||||
|
||||
s->pieceReplication[piece_i] = r;
|
||||
}
|
||||
}
|
||||
|
||||
static void swarmFree(void* vs)
|
||||
{
|
||||
auto* s = static_cast<tr_swarm*>(vs);
|
||||
|
@ -444,8 +397,6 @@ static void swarmFree(void* vs)
|
|||
tr_ptrArrayDestruct(&s->peers, nullptr);
|
||||
s->stats = {};
|
||||
|
||||
replicationFree(s);
|
||||
|
||||
tr_free(s->requests);
|
||||
tr_free(s->pieces);
|
||||
|
||||
|
@ -823,17 +774,9 @@ static constexpr void invalidatePieceSorting(tr_swarm* s)
|
|||
|
||||
static tr_torrent const* weightTorrent;
|
||||
|
||||
static uint16_t const* weightReplication;
|
||||
|
||||
static void setComparePieceByWeightTorrent(tr_swarm* s)
|
||||
{
|
||||
if (!replicationExists(s))
|
||||
{
|
||||
replicationNew(s);
|
||||
}
|
||||
|
||||
weightTorrent = s->tor;
|
||||
weightReplication = s->pieceReplication;
|
||||
}
|
||||
|
||||
/* we try to create a "weight" s.t. high-priority pieces come before others,
|
||||
|
@ -843,7 +786,6 @@ static int comparePieceByWeight(void const* va, void const* vb)
|
|||
auto const* const a = static_cast<struct weighted_piece const*>(va);
|
||||
auto const* const b = static_cast<struct weighted_piece const*>(vb);
|
||||
tr_torrent const* const tor = weightTorrent;
|
||||
uint16_t const* const rep = weightReplication;
|
||||
|
||||
/* primary key: weight */
|
||||
int missing = tr_torrentMissingBlocksInPiece(tor, a->index);
|
||||
|
@ -852,58 +794,21 @@ static int comparePieceByWeight(void const* va, void const* vb)
|
|||
missing = tr_torrentMissingBlocksInPiece(tor, b->index);
|
||||
pending = b->requestCount;
|
||||
int ib = missing > pending ? missing - pending : tor->blockCountInPiece + pending;
|
||||
|
||||
if (ia < ib)
|
||||
if (ia != ib)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ia > ib)
|
||||
{
|
||||
return 1;
|
||||
return ia < ib ? -1 : 1;
|
||||
}
|
||||
|
||||
/* secondary key: higher priorities go first */
|
||||
ia = tor->info.pieces[a->index].priority;
|
||||
ib = tor->info.pieces[b->index].priority;
|
||||
|
||||
if (ia > ib)
|
||||
if (ia != ib)
|
||||
{
|
||||
return -1;
|
||||
return ia > ib ? -1 : 1;
|
||||
}
|
||||
|
||||
if (ia < ib)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* tertiary key: rarest first. */
|
||||
ia = rep[a->index];
|
||||
ib = rep[b->index];
|
||||
|
||||
if (ia < ib)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ia > ib)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* quaternary key: random */
|
||||
if (a->salt < b->salt)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (a->salt > b->salt)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* okay, they're equal */
|
||||
return 0;
|
||||
/* tertiary key: random */
|
||||
return a->salt - b->salt;
|
||||
}
|
||||
|
||||
static int comparePieceByIndex(void const* va, void const* vb)
|
||||
|
@ -951,7 +856,6 @@ static void pieceListSort(tr_swarm* s, enum piece_sort_state state)
|
|||
#if 1
|
||||
|
||||
#define assertWeightedPiecesAreSorted(t)
|
||||
#define assertReplicationCountIsExact(t)
|
||||
|
||||
#else
|
||||
|
||||
|
@ -968,36 +872,6 @@ static void assertWeightedPiecesAreSorted(Torrent* t)
|
|||
}
|
||||
}
|
||||
|
||||
static void assertReplicationCountIsExact(Torrent* t)
|
||||
{
|
||||
/* This assert might fail due to errors of implementations in other
|
||||
* clients. It happens when receiving duplicate bitfields/HaveAll/HaveNone
|
||||
* from a client. If a such a behavior is noticed,
|
||||
* a bug report should be filled to the faulty client. */
|
||||
|
||||
uint16_t const* rep = t->pieceReplication;
|
||||
size_t const piece_count = t->pieceReplicationSize;
|
||||
tr_peer const** peers = (tr_peer const**)tr_ptrArrayBase(&t->peers);
|
||||
int const peer_count = tr_ptrArraySize(&t->peers);
|
||||
|
||||
TR_ASSERT(piece_count == t->tor->info.pieceCount);
|
||||
|
||||
for (size_t piece_i = 0; piece_i < piece_count; ++piece_i)
|
||||
{
|
||||
uint16_t r = 0;
|
||||
|
||||
for (int peer_i = 0; peer_i < peer_count; ++peer_i)
|
||||
{
|
||||
if (tr_bitsetHas(&peers[peer_i]->have, piece_i))
|
||||
{
|
||||
++r;
|
||||
}
|
||||
}
|
||||
|
||||
TR_ASSERT(rep[piece_i] == r);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static constexpr weighted_piece* pieceListLookup(tr_swarm* s, tr_piece_index_t index)
|
||||
|
@ -1161,100 +1035,6 @@ static void pieceListRemoveRequest(tr_swarm* s, tr_block_index_t block)
|
|||
}
|
||||
}
|
||||
|
||||
/****
|
||||
*****
|
||||
***** Replication count (for rarest first policy)
|
||||
*****
|
||||
****/
|
||||
|
||||
/**
|
||||
* Increase the replication count of this piece and sort it if the
|
||||
* piece list is already sorted
|
||||
*/
|
||||
static void tr_incrReplicationOfPiece(tr_swarm* s, size_t const index)
|
||||
{
|
||||
TR_ASSERT(replicationExists(s));
|
||||
TR_ASSERT(s->pieceReplicationSize == s->tor->info.pieceCount);
|
||||
|
||||
/* One more replication of this piece is present in the swarm */
|
||||
++s->pieceReplication[index];
|
||||
|
||||
/* we only resort the piece if the list is already sorted */
|
||||
if (s->pieceSortState == PIECES_SORTED_BY_WEIGHT)
|
||||
{
|
||||
pieceListResortPiece(s, pieceListLookup(s, index));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the replication count of pieces present in the bitfield
|
||||
*/
|
||||
static void tr_incrReplicationFromBitfield(tr_swarm* s, tr_bitfield const* b)
|
||||
{
|
||||
TR_ASSERT(replicationExists(s));
|
||||
|
||||
uint16_t* rep = s->pieceReplication;
|
||||
|
||||
for (size_t i = 0, n = s->tor->info.pieceCount; i < n; ++i)
|
||||
{
|
||||
if (b->test(i))
|
||||
{
|
||||
++rep[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (s->pieceSortState == PIECES_SORTED_BY_WEIGHT)
|
||||
{
|
||||
invalidatePieceSorting(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the replication count of every piece
|
||||
*/
|
||||
static void tr_incrReplication(tr_swarm* s)
|
||||
{
|
||||
TR_ASSERT(replicationExists(s));
|
||||
TR_ASSERT(s->pieceReplicationSize == s->tor->info.pieceCount);
|
||||
|
||||
for (size_t i = 0; i < s->pieceReplicationSize; ++i)
|
||||
{
|
||||
++s->pieceReplication[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease the replication count of pieces present in the bitset.
|
||||
*/
|
||||
static void tr_decrReplicationFromBitfield(tr_swarm* s, tr_bitfield const* b)
|
||||
{
|
||||
TR_ASSERT(replicationExists(s));
|
||||
TR_ASSERT(s->pieceReplicationSize == s->tor->info.pieceCount);
|
||||
|
||||
if (b->hasAll())
|
||||
{
|
||||
for (size_t i = 0; i < s->pieceReplicationSize; ++i)
|
||||
{
|
||||
--s->pieceReplication[i];
|
||||
}
|
||||
}
|
||||
else if (!b->hasNone())
|
||||
{
|
||||
for (size_t i = 0; i < s->pieceReplicationSize; ++i)
|
||||
{
|
||||
if (b->test(i))
|
||||
{
|
||||
--s->pieceReplication[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (s->pieceSortState == PIECES_SORTED_BY_WEIGHT)
|
||||
{
|
||||
invalidatePieceSorting(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
***
|
||||
**/
|
||||
|
@ -1294,7 +1074,6 @@ void tr_peerMgrGetNextRequests(
|
|||
pieceListSort(s, PIECES_SORTED_BY_WEIGHT);
|
||||
}
|
||||
|
||||
assertReplicationCountIsExact(s);
|
||||
assertWeightedPiecesAreSorted(s);
|
||||
|
||||
updateEndgame(s);
|
||||
|
@ -1708,36 +1487,10 @@ static void peerCallbackFunc(tr_peer* peer, tr_peer_event const* e, void* vs)
|
|||
}
|
||||
|
||||
case TR_PEER_CLIENT_GOT_HAVE:
|
||||
if (replicationExists(s))
|
||||
{
|
||||
tr_incrReplicationOfPiece(s, e->pieceIndex);
|
||||
assertReplicationCountIsExact(s);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TR_PEER_CLIENT_GOT_HAVE_ALL:
|
||||
if (replicationExists(s))
|
||||
{
|
||||
tr_incrReplication(s);
|
||||
assertReplicationCountIsExact(s);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TR_PEER_CLIENT_GOT_HAVE_NONE:
|
||||
/* noop */
|
||||
break;
|
||||
|
||||
case TR_PEER_CLIENT_GOT_BITFIELD:
|
||||
TR_ASSERT(e->bitfield != nullptr);
|
||||
|
||||
if (replicationExists(s))
|
||||
{
|
||||
tr_incrReplicationFromBitfield(s, e->bitfield);
|
||||
assertReplicationCountIsExact(s);
|
||||
}
|
||||
|
||||
/* noop */
|
||||
break;
|
||||
|
||||
case TR_PEER_CLIENT_GOT_REJ:
|
||||
|
@ -2424,7 +2177,6 @@ static void stopSwarm(tr_swarm* swarm)
|
|||
{
|
||||
swarm->isRunning = false;
|
||||
|
||||
replicationFree(swarm);
|
||||
invalidatePieceSorting(swarm);
|
||||
|
||||
removeAllPeers(swarm);
|
||||
|
@ -2489,10 +2241,9 @@ void tr_peerUpdateProgress(tr_torrent* tor, tr_peer* peer)
|
|||
}
|
||||
}
|
||||
|
||||
/* clamp the progress range */
|
||||
peer->progress = std::clamp(peer->progress, 0.0F, 1.0F);
|
||||
|
||||
if (peer->atom != nullptr && peer->progress >= 1.0F)
|
||||
if (peer->atom != nullptr && peer->progress >= 1.0f)
|
||||
{
|
||||
atomSetSeed(tor->swarm, peer->atom);
|
||||
}
|
||||
|
@ -2606,29 +2357,27 @@ uint64_t tr_peerMgrGetDesiredAvailable(tr_torrent const* tor)
|
|||
{
|
||||
TR_ASSERT(tr_isTorrent(tor));
|
||||
|
||||
/* common shortcuts... */
|
||||
// common shortcuts...
|
||||
|
||||
if (!tor->isRunning || tor->isStopping || tr_torrentIsSeed(tor) || !tr_torrentHasMetadata(tor))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
tr_swarm const* s = tor->swarm;
|
||||
|
||||
tr_swarm const* const s = tor->swarm;
|
||||
if (s == nullptr || !s->isRunning)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t const peer_count = tr_ptrArraySize(&s->peers);
|
||||
|
||||
if (peer_count == 0)
|
||||
size_t const n_peers = tr_ptrArraySize(&s->peers);
|
||||
if (n_peers == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
tr_peer const** const peers = (tr_peer const**)tr_ptrArrayBase(&s->peers);
|
||||
for (size_t i = 0; i < peer_count; ++i)
|
||||
for (size_t i = 0; i < n_peers; ++i)
|
||||
{
|
||||
if (peers[i]->atom != nullptr && atomIsSeed(peers[i]->atom))
|
||||
{
|
||||
|
@ -2636,34 +2385,43 @@ uint64_t tr_peerMgrGetDesiredAvailable(tr_torrent const* tor)
|
|||
}
|
||||
}
|
||||
|
||||
if (s->pieceReplication == nullptr || s->pieceReplicationSize == 0)
|
||||
// do it the hard way
|
||||
|
||||
auto desired_available = uint64_t{};
|
||||
auto const n_pieces = tor->info.pieceCount;
|
||||
auto have = std::vector<bool>(n_pieces);
|
||||
|
||||
for (size_t i = 0; i < n_peers; ++i)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* do it the hard way */
|
||||
|
||||
uint64_t desiredAvailable = 0;
|
||||
|
||||
for (size_t i = 0, n = std::min(size_t{ tor->info.pieceCount }, s->pieceReplicationSize); i < n; ++i)
|
||||
{
|
||||
if (!tor->info.pieces[i].dnd && s->pieceReplication[i] > 0)
|
||||
auto* peer = peers[i];
|
||||
for (size_t j = 0; j < n_pieces; ++j)
|
||||
{
|
||||
desiredAvailable += tr_torrentMissingBytesInPiece(tor, i);
|
||||
if (peer->have.test(j))
|
||||
{
|
||||
have[j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TR_ASSERT(desiredAvailable <= tor->info.totalSize);
|
||||
return desiredAvailable;
|
||||
for (size_t i = 0; i < n_pieces; ++i)
|
||||
{
|
||||
if (!tor->info.pieces[i].dnd && have.at(i))
|
||||
{
|
||||
desired_available += tr_torrentMissingBytesInPiece(tor, i);
|
||||
}
|
||||
}
|
||||
|
||||
TR_ASSERT(desired_available <= tor->info.totalSize);
|
||||
return desired_available;
|
||||
}
|
||||
|
||||
double* tr_peerMgrWebSpeeds_KBps(tr_torrent const* tor)
|
||||
{
|
||||
TR_ASSERT(tr_isTorrent(tor));
|
||||
|
||||
uint64_t const now = tr_time_msec();
|
||||
auto const now = tr_time_msec();
|
||||
|
||||
tr_swarm* s = tor->swarm;
|
||||
tr_swarm* const s = tor->swarm;
|
||||
TR_ASSERT(s->manager != nullptr);
|
||||
|
||||
unsigned int n = tr_ptrArraySize(&s->webseeds);
|
||||
|
@ -3419,11 +3177,6 @@ static void removePeer(tr_swarm* s, tr_peer* peer)
|
|||
--s->stats.peerCount;
|
||||
--s->stats.peerFromCount[atom->fromFirst];
|
||||
|
||||
if (replicationExists(s))
|
||||
{
|
||||
tr_decrReplicationFromBitfield(s, &peer->have);
|
||||
}
|
||||
|
||||
TR_ASSERT(s->stats.peerCount == tr_ptrArraySize(&s->peers));
|
||||
TR_ASSERT(s->stats.peerFromCount[atom->fromFirst] >= 0);
|
||||
|
||||
|
|
Loading…
Reference in New Issue