diff --git a/libtransmission/peer-common.h b/libtransmission/peer-common.h index d1ead2ea8..d07108071 100644 --- a/libtransmission/peer-common.h +++ b/libtransmission/peer-common.h @@ -61,7 +61,6 @@ typedef enum TR_PEER_CLIENT_GOT_HAVE_ALL, TR_PEER_CLIENT_GOT_HAVE_NONE, TR_PEER_PEER_GOT_DATA, - TR_PEER_PEER_PROGRESS, TR_PEER_ERROR } PeerEventType; @@ -74,7 +73,6 @@ typedef struct struct tr_bitfield * bitfield; /* for GOT_BITFIELD */ uint32_t offset; /* for GOT_BLOCK */ uint32_t length; /* for GOT_BLOCK + GOT_DATA */ - float progress; /* for PEER_PROGRESS */ int err; /* errno for GOT_ERROR */ tr_bool wasPieceData; /* for GOT_DATA */ tr_port port; /* for GOT_PORT */ @@ -89,6 +87,10 @@ typedef void tr_peer_callback( struct tr_peer * peer, const tr_peer_event * event, void * client_data ); +/** Update the tr_peer.progress field based on the 'have' bitset. */ +void tr_peerUpdateProgress( tr_torrent * tor, struct tr_peer * ); + + #ifdef WIN32 #define EMSGSIZE WSAEMSGSIZE #endif diff --git a/libtransmission/peer-mgr.c b/libtransmission/peer-mgr.c index 2c97be2c9..4fc3387b9 100644 --- a/libtransmission/peer-mgr.c +++ b/libtransmission/peer-mgr.c @@ -99,7 +99,7 @@ enum CANCEL_HISTORY_SEC = 60 }; -const tr_peer_event TR_PEER_EVENT_INIT = { 0, 0, NULL, 0, 0, 0.0f, 0, FALSE, 0 }; +const tr_peer_event TR_PEER_EVENT_INIT = { 0, 0, NULL, 0, 0, 0, FALSE, 0 }; /** *** @@ -645,18 +645,24 @@ atomSetSeedProbability( struct peer_atom * atom, int seedProbability ) atom->flags &= ~ADDED_F_SEED_FLAG; } -static void -atomSetSeed( struct peer_atom * atom ) -{ - atomSetSeedProbability( atom, 100 ); -} - static inline tr_bool atomIsSeed( const struct peer_atom * atom ) { return atom->seedProbability == 100; } +static void +atomSetSeed( const Torrent * t, struct peer_atom * atom ) +{ + if( !atomIsSeed( atom ) ) + { + tordbg( t, "marking peer %s as a seed", tr_atomAddrStr( atom ) ); + + atomSetSeedProbability( atom, 100 ); + } +} + + tr_bool tr_peerMgrPeerIsSeed( const tr_torrent * tor, const tr_address * addr ) @@ -1699,19 +1705,6 @@ peerCallbackFunc( tr_peer * peer, const tr_peer_event * e, void * vt ) break; } - case TR_PEER_PEER_PROGRESS: - { - if( peer ) - { - struct peer_atom * atom = peer->atom; - if( e->progress >= 1.0 ) { - tordbg( t, "marking peer %s as a seed", tr_atomAddrStr( atom ) ); - atomSetSeed( atom ); - } - } - break; - } - case TR_PEER_CLIENT_GOT_BLOCK: { tr_torrent * tor = t->tor; @@ -2109,7 +2102,7 @@ tr_peerMgrMarkAllAsSeeds( tr_torrent * tor ) struct peer_atom ** end = it + n; while( it != end ) - atomSetSeed( *it++ ); + atomSetSeed( t, *it++ ); } tr_pex * @@ -2442,6 +2435,46 @@ tr_peerMgrRemoveTorrent( tr_torrent * tor ) torrentFree( tor->torrentPeers ); } +void +tr_peerUpdateProgress( tr_torrent * tor, tr_peer * peer ) +{ + const tr_bitset * have = &peer->have; + + if( have->haveAll ) + { + peer->progress = 1.0; + } + else if( have->haveNone ) + { + peer->progress = 0.0; + } + else + { + const float trueCount = tr_bitfieldCountTrueBits( &have->bitfield ); + + if( tr_torrentHasMetadata( tor ) ) + peer->progress = trueCount / tor->info.pieceCount; + else /* without pieceCount, this result is only a best guess... */ + peer->progress = trueCount / ( have->bitfield.bitCount + 1 ); + } + + if( peer->progress >= 1.0 ) + atomSetSeed( tor->torrentPeers, peer->atom ); +} + +void +tr_peerMgrOnTorrentGotMetainfo( tr_torrent * tor ) +{ + int i; + const int peerCount = tr_ptrArraySize( &tor->torrentPeers->peers ); + tr_peer ** peers = (tr_peer**) tr_ptrArrayBase( &tor->torrentPeers->peers ); + + /* some peer_msgs' progress fields may not be accurate if we + didn't have the metadata before now... so refresh them all... */ + for( i=0; ipeer->progress; - publish( msgs, &e ); -} - static void fireGotBlock( tr_peermsgs * msgs, const struct peer_request * req ) { @@ -1208,11 +1199,10 @@ readBtId( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen ) static void updatePeerProgress( tr_peermsgs * msgs ) { - msgs->peer->progress = tr_bitsetPercent( &msgs->peer->have ); - dbgmsg( msgs, "peer progress is %f", msgs->peer->progress ); + tr_peerUpdateProgress( msgs->torrent, msgs->peer ); + updateFastSet( msgs ); updateInterest( msgs ); - firePeerProgress( msgs ); } static void diff --git a/libtransmission/torrent.c b/libtransmission/torrent.c index 4f702b8c3..307032d9b 100644 --- a/libtransmission/torrent.c +++ b/libtransmission/torrent.c @@ -752,6 +752,8 @@ tr_torrentGotNewInfoDict( tr_torrent * tor ) { torrentInitFromInfo( tor ); + tr_peerMgrOnTorrentGotMetainfo( tor ); + tr_torrentFireMetadataCompleted( tor ); }