fix bug #5372, 'wrong peer states displayed'.

This commit is contained in:
Jordan Lee 2013-07-08 16:41:12 +00:00
parent 59af132947
commit 058e430251
5 changed files with 137 additions and 77 deletions

View File

@ -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

View File

@ -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 */

View File

@ -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);
}
}

View File

@ -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));

View File

@ -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;