fix bug #5372, 'wrong peer states displayed'.
This commit is contained in:
parent
59af132947
commit
058e430251
|
@ -149,6 +149,32 @@ void tr_peerDestruct (struct tr_peer * peer);
|
|||
/** Update the tr_peer.progress field based on the 'have' bitset. */
|
||||
void tr_peerUpdateProgress (tr_torrent * tor, struct tr_peer *);
|
||||
|
||||
bool tr_peerIsSeed (const struct tr_peer * peer);
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
typedef struct tr_swarm_stats
|
||||
{
|
||||
int activePeerCount[2];
|
||||
int activeWebseedCount;
|
||||
int peerCount;
|
||||
int peerFromCount[TR_PEER_FROM__MAX];
|
||||
}
|
||||
tr_swarm_stats;
|
||||
|
||||
extern const tr_swarm_stats TR_SWARM_STATS_INIT;
|
||||
|
||||
void tr_swarmGetStats (const struct tr_swarm * swarm, tr_swarm_stats * setme);
|
||||
|
||||
void tr_swarmIncrementActivePeers (struct tr_swarm * swarm, tr_direction direction, bool is_active);
|
||||
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#define EMSGSIZE WSAEMSGSIZE
|
||||
|
|
|
@ -103,6 +103,8 @@ enum
|
|||
|
||||
const tr_peer_event TR_PEER_EVENT_INIT = { 0, 0, NULL, 0, 0, 0, 0 };
|
||||
|
||||
const tr_swarm_stats TR_SWARM_STATS_INIT = { { 0, 0 }, 0, 0, { 0, 0, 0, 0, 0, 0, 0 } };
|
||||
|
||||
/**
|
||||
***
|
||||
**/
|
||||
|
@ -184,6 +186,8 @@ enum piece_sort_state
|
|||
/** @brief Opaque, per-torrent data structure for peer connection information */
|
||||
typedef struct tr_swarm
|
||||
{
|
||||
tr_swarm_stats stats;
|
||||
|
||||
tr_ptrArray outgoingHandshakes; /* tr_handshake */
|
||||
tr_ptrArray pool; /* struct peer_atom */
|
||||
tr_ptrArray peers; /* tr_peerMsgs */
|
||||
|
@ -485,19 +489,6 @@ replicationNew (tr_swarm * s)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
resetTorrentStats (tr_torrent * tor)
|
||||
{
|
||||
int i;
|
||||
|
||||
tor->peerCount = 0;
|
||||
tor->activePeerCount[TR_UP] = 0;
|
||||
tor->activePeerCount[TR_DOWN] = 0;
|
||||
tor->activeWebseedCount = 0;
|
||||
for (i=0; i<TR_PEER_FROM__MAX; i++)
|
||||
tor->peerFromCount[i] = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
swarmFree (void * vs)
|
||||
{
|
||||
|
@ -513,7 +504,7 @@ swarmFree (void * vs)
|
|||
tr_ptrArrayDestruct (&s->pool, (PtrArrayForeachFunc)tr_free);
|
||||
tr_ptrArrayDestruct (&s->outgoingHandshakes, NULL);
|
||||
tr_ptrArrayDestruct (&s->peers, NULL);
|
||||
resetTorrentStats (s->tor);
|
||||
s->stats = TR_SWARM_STATS_INIT;
|
||||
|
||||
replicationFree (s);
|
||||
|
||||
|
@ -533,7 +524,7 @@ rebuildWebseedArray (tr_swarm * s, tr_torrent * tor)
|
|||
/* clear the array */
|
||||
tr_ptrArrayDestruct (&s->webseeds, (PtrArrayForeachFunc)tr_peerFree);
|
||||
s->webseeds = TR_PTR_ARRAY_INIT;
|
||||
s->tor->activeWebseedCount = 0;
|
||||
s->stats.activeWebseedCount = 0;
|
||||
|
||||
/* repopulate it */
|
||||
for (i=0; i<inf->webseedCount; ++i)
|
||||
|
@ -1935,11 +1926,11 @@ createBitTorrentPeer (tr_torrent * tor,
|
|||
atom->peer = peer;
|
||||
|
||||
tr_ptrArrayInsertSorted (&swarm->peers, peer, peerCompare);
|
||||
++tor->peerCount;
|
||||
++tor->peerFromCount[atom->fromFirst];
|
||||
++swarm->stats.peerCount;
|
||||
++swarm->stats.peerFromCount[atom->fromFirst];
|
||||
|
||||
assert (tor->peerCount == tr_ptrArraySize (&swarm->peers));
|
||||
assert (tor->peerFromCount[atom->fromFirst] <= tor->peerCount);
|
||||
assert (swarm->stats.peerCount == tr_ptrArraySize (&swarm->peers));
|
||||
assert (swarm->stats.peerFromCount[atom->fromFirst] <= swarm->stats.peerCount);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2575,8 +2566,33 @@ tr_peerMgrTorrentAvailability (const tr_torrent * tor,
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
peerIsSeed (const tr_peer * peer)
|
||||
void
|
||||
tr_swarmGetStats (const tr_swarm * swarm, tr_swarm_stats * setme)
|
||||
{
|
||||
assert (swarm != NULL);
|
||||
assert (setme != NULL);
|
||||
|
||||
*setme = swarm->stats;
|
||||
}
|
||||
|
||||
void
|
||||
tr_swarmIncrementActivePeers (tr_swarm * swarm, tr_direction direction, bool is_active)
|
||||
{
|
||||
int n = swarm->stats.activePeerCount[direction];
|
||||
|
||||
if (is_active)
|
||||
++n;
|
||||
else
|
||||
--n;
|
||||
|
||||
assert (0 <= n);
|
||||
assert (n <= swarm->stats.peerCount);
|
||||
|
||||
swarm->stats.activePeerCount[direction] = n;
|
||||
}
|
||||
|
||||
bool
|
||||
tr_peerIsSeed (const tr_peer * peer)
|
||||
{
|
||||
if (peer->progress >= 1.0)
|
||||
return true;
|
||||
|
@ -2704,7 +2720,7 @@ tr_peerMgrPeerStats (const tr_torrent * tor, int * setmeCount)
|
|||
stat->isIncoming = tr_peerMsgsIsIncomingConnection (msgs);
|
||||
stat->isDownloadingFrom = tr_peerMsgsIsActive (msgs, TR_PEER_TO_CLIENT);
|
||||
stat->isUploadingTo = tr_peerMsgsIsActive (msgs, TR_CLIENT_TO_PEER);
|
||||
stat->isSeed = peerIsSeed (peer);
|
||||
stat->isSeed = tr_peerIsSeed (peer);
|
||||
|
||||
stat->blocksToPeer = tr_historyGet (&peer->blocksSentToPeer, now, CANCEL_HISTORY_SEC);
|
||||
stat->blocksToClient = tr_historyGet (&peer->blocksSentToClient, now, CANCEL_HISTORY_SEC);
|
||||
|
@ -2765,7 +2781,7 @@ isPeerInteresting (tr_torrent * const tor,
|
|||
assert (!tr_torrentIsSeed (tor));
|
||||
assert (tr_torrentIsPieceTransferAllowed (tor, TR_PEER_TO_CLIENT));
|
||||
|
||||
if (peerIsSeed (peer))
|
||||
if (tr_peerIsSeed (peer))
|
||||
return true;
|
||||
|
||||
for (i=0, n=tor->info.pieceCount; i<n; ++i)
|
||||
|
@ -3055,7 +3071,7 @@ rechokeUploads (tr_swarm * s, const uint64_t now)
|
|||
|
||||
struct peer_atom * atom = peer->atom;
|
||||
|
||||
if (peerIsSeed (peer)) /* choke seeds and partial seeds */
|
||||
if (tr_peerIsSeed (peer)) /* choke seeds and partial seeds */
|
||||
{
|
||||
tr_peerMsgsSetChoke (PEER_MSGS(peer), true);
|
||||
}
|
||||
|
@ -3148,11 +3164,15 @@ rechokePulse (int foo UNUSED, short bar UNUSED, void * vmgr)
|
|||
|
||||
while ((tor = tr_torrentNext (mgr->session, tor)))
|
||||
{
|
||||
if (tor->isRunning && tor->peerCount)
|
||||
if (tor->isRunning)
|
||||
{
|
||||
tr_swarm * s = tor->swarm;
|
||||
rechokeUploads (s, now);
|
||||
rechokeDownloads (s);
|
||||
|
||||
if (s->stats.peerCount > 0)
|
||||
{
|
||||
rechokeUploads (s, now);
|
||||
rechokeDownloads (s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3184,7 +3204,7 @@ shouldPeerBeClosed (const tr_swarm * s,
|
|||
}
|
||||
|
||||
/* disconnect if we're both seeds and enough time has passed for PEX */
|
||||
if (tr_torrentIsSeed (tor) && peerIsSeed (peer))
|
||||
if (tr_torrentIsSeed (tor) && tr_peerIsSeed (peer))
|
||||
return !tr_torrentAllowsPex (tor) || (now-atom->time>=30);
|
||||
|
||||
/* disconnect if it's been too long since piece data has been transferred.
|
||||
|
@ -3285,15 +3305,15 @@ removePeer (tr_swarm * s, tr_peer * peer)
|
|||
atom->time = tr_time ();
|
||||
|
||||
removed = tr_ptrArrayRemoveSorted (&s->peers, peer, peerCompare);
|
||||
--s->tor->peerCount;
|
||||
--s->tor->peerFromCount[atom->fromFirst];
|
||||
--s->stats.peerCount;
|
||||
--s->stats.peerFromCount[atom->fromFirst];
|
||||
|
||||
if (replicationExists (s))
|
||||
tr_decrReplicationFromBitfield (s, &peer->have);
|
||||
|
||||
assert (removed == peer);
|
||||
assert (s->tor->peerCount == tr_ptrArraySize (&s->peers));
|
||||
assert (s->tor->peerFromCount[atom->fromFirst] >= 0);
|
||||
assert (s->stats.peerCount == tr_ptrArraySize (&s->peers));
|
||||
assert (s->stats.peerFromCount[atom->fromFirst] >= 0);
|
||||
|
||||
tr_peerFree (removed);
|
||||
}
|
||||
|
@ -3332,7 +3352,7 @@ removeAllPeers (tr_swarm * s)
|
|||
while (!tr_ptrArrayEmpty (&s->peers))
|
||||
removePeer (s, tr_ptrArrayNth (&s->peers, 0));
|
||||
|
||||
assert (!s->tor->peerCount);
|
||||
assert (!s->stats.peerCount);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -3618,7 +3638,7 @@ bandwidthPulse (int foo UNUSED, short bar UNUSED, void * vmgr)
|
|||
tr_torrentStop (tor);
|
||||
|
||||
/* update the torrent's stats */
|
||||
tor->activeWebseedCount = countActiveWebseeds (tor->swarm);
|
||||
tor->swarm->stats.activeWebseedCount = countActiveWebseeds (tor->swarm);
|
||||
}
|
||||
|
||||
/* pump the queues */
|
||||
|
|
|
@ -689,13 +689,50 @@ updateFastSet (tr_peerMsgs * msgs UNUSED)
|
|||
**** ACTIVE
|
||||
***/
|
||||
|
||||
bool
|
||||
tr_peerMsgsIsActive (const tr_peerMsgs * msgs, tr_direction direction)
|
||||
static bool
|
||||
tr_peerMsgsCalculateActive (const tr_peerMsgs * msgs, tr_direction direction)
|
||||
{
|
||||
bool is_active;
|
||||
|
||||
assert (tr_isPeerMsgs (msgs));
|
||||
assert (tr_isDirection (direction));
|
||||
|
||||
return msgs->is_active[direction];
|
||||
if (direction == TR_CLIENT_TO_PEER)
|
||||
{
|
||||
is_active = tr_peerMsgsIsPeerInterested (msgs)
|
||||
&& !tr_peerMsgsIsPeerChoked (msgs);
|
||||
|
||||
if (is_active)
|
||||
assert (!tr_peerIsSeed (&msgs->peer));
|
||||
}
|
||||
else /* TR_PEER_TO_CLIENT */
|
||||
{
|
||||
if (!tr_torrentHasMetadata (msgs->torrent))
|
||||
is_active = true;
|
||||
else
|
||||
is_active = tr_peerMsgsIsClientInterested (msgs)
|
||||
&& !tr_peerMsgsIsClientChoked (msgs);
|
||||
|
||||
if (is_active)
|
||||
assert (!tr_torrentIsSeed (msgs->torrent));
|
||||
}
|
||||
|
||||
return is_active;
|
||||
}
|
||||
|
||||
bool
|
||||
tr_peerMsgsIsActive (const tr_peerMsgs * msgs, tr_direction direction)
|
||||
{
|
||||
bool is_active;
|
||||
|
||||
assert (tr_isPeerMsgs (msgs));
|
||||
assert (tr_isDirection (direction));
|
||||
|
||||
is_active = msgs->is_active[direction];
|
||||
|
||||
assert (is_active == tr_peerMsgsCalculateActive (msgs, direction));
|
||||
|
||||
return is_active;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -703,46 +740,22 @@ tr_peerMsgsSetActive (tr_peerMsgs * msgs,
|
|||
tr_direction direction,
|
||||
bool is_active)
|
||||
{
|
||||
dbgmsg (msgs, "direction [%d] is_active [%d]", (int)direction, (int)is_active);
|
||||
|
||||
if (msgs->is_active[direction] != is_active)
|
||||
{
|
||||
int n = msgs->torrent->activePeerCount[direction];
|
||||
|
||||
msgs->is_active[direction] = is_active;
|
||||
|
||||
if (is_active)
|
||||
++n;
|
||||
else
|
||||
--n;
|
||||
assert (0 <= n);
|
||||
assert (n <= msgs->torrent->peerCount);
|
||||
|
||||
msgs->torrent->activePeerCount[direction] = n;
|
||||
tr_swarmIncrementActivePeers (msgs->torrent->swarm, direction, is_active);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tr_peerMsgsUpdateActive (tr_peerMsgs * msgs, tr_direction direction)
|
||||
{
|
||||
bool active;
|
||||
const bool is_active = tr_peerMsgsCalculateActive (msgs, direction);
|
||||
|
||||
assert (tr_isPeerMsgs (msgs));
|
||||
assert (tr_isDirection (direction));
|
||||
|
||||
if (direction == TR_CLIENT_TO_PEER)
|
||||
{
|
||||
active = tr_peerMsgsIsPeerInterested (msgs)
|
||||
&& !tr_peerMsgsIsPeerChoked (msgs);
|
||||
}
|
||||
else /* TR_PEER_TO_CLIENT */
|
||||
{
|
||||
if (!tr_torrentHasMetadata (msgs->torrent))
|
||||
active = true;
|
||||
else
|
||||
active = tr_peerMsgsIsClientInterested (msgs)
|
||||
&& !tr_peerMsgsIsClientChoked (msgs);
|
||||
}
|
||||
|
||||
tr_peerMsgsSetActive (msgs, direction, active);
|
||||
tr_peerMsgsSetActive (msgs, direction, is_active);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -846,6 +859,7 @@ tr_peerMsgsSetChoke (tr_peerMsgs * msgs, bool peer_is_choked)
|
|||
cancelAllRequestsToClient (msgs);
|
||||
protocolSendChoke (msgs, peer_is_choked);
|
||||
msgs->chokeChangedAt = now;
|
||||
tr_peerMsgsUpdateActive (msgs, TR_CLIENT_TO_PEER);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1255,12 +1255,18 @@ tr_torrentStat (tr_torrent * tor)
|
|||
const uint64_t now = tr_time_msec ();
|
||||
unsigned int pieceUploadSpeed_Bps;
|
||||
unsigned int pieceDownloadSpeed_Bps;
|
||||
struct tr_swarm_stats swarm_stats;
|
||||
int i;
|
||||
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
tor->lastStatTime = tr_time ();
|
||||
|
||||
if (tor->swarm != NULL)
|
||||
tr_swarmGetStats (tor->swarm, &swarm_stats);
|
||||
else
|
||||
swarm_stats = TR_SWARM_STATS_INIT;
|
||||
|
||||
s = &tor->stats;
|
||||
s->id = tor->uniqueId;
|
||||
s->activity = tr_torrentGetActivity (tor);
|
||||
|
@ -1270,13 +1276,12 @@ tr_torrentStat (tr_torrent * tor)
|
|||
tr_strlcpy (s->errorString, tor->errorString, sizeof (s->errorString));
|
||||
|
||||
s->manualAnnounceTime = tr_announcerNextManualAnnounce (tor);
|
||||
|
||||
s->peersConnected = tor->peerCount;
|
||||
s->peersSendingToUs = tor->activePeerCount[TR_DOWN];
|
||||
s->peersGettingFromUs = tor->activePeerCount[TR_UP];
|
||||
s->webseedsSendingToUs = tor->activeWebseedCount;
|
||||
s->peersConnected = swarm_stats.peerCount;
|
||||
s->peersSendingToUs = swarm_stats.activePeerCount[TR_DOWN];
|
||||
s->peersGettingFromUs = swarm_stats.activePeerCount[TR_UP];
|
||||
s->webseedsSendingToUs = swarm_stats.activeWebseedCount;
|
||||
for (i=0; i<TR_PEER_FROM__MAX; i++)
|
||||
s->peersFrom[i] = tor->peerFromCount[i];
|
||||
s->peersFrom[i] = swarm_stats.peerFromCount[i];
|
||||
|
||||
s->rawUploadSpeed_KBps = toSpeedKBps (tr_bandwidthGetRawSpeed_Bps (&tor->bandwidth, now, TR_UP));
|
||||
s->rawDownloadSpeed_KBps = toSpeedKBps (tr_bandwidthGetRawSpeed_Bps (&tor->bandwidth, now, TR_DOWN));
|
||||
|
|
|
@ -226,11 +226,6 @@ struct tr_torrent
|
|||
int secondsDownloading;
|
||||
int secondsSeeding;
|
||||
|
||||
int peerCount;
|
||||
int peerFromCount[TR_PEER_FROM__MAX];
|
||||
int activePeerCount[2];
|
||||
int activeWebseedCount;
|
||||
|
||||
int queuePosition;
|
||||
|
||||
tr_torrent_metadata_func * metadata_func;
|
||||
|
|
Loading…
Reference in New Issue