Add Torrent.Stats.ConnectedSeeders

Fixes #231
This commit is contained in:
Matt Joiner 2018-01-29 18:18:08 +11:00
parent 9a6f88b0fd
commit ef4c0f1413
3 changed files with 29 additions and 11 deletions

View File

@ -82,7 +82,7 @@ type connection struct {
peerPieces bitmap.Bitmap
// The peer has everything. This can occur due to a special message, when
// we may not even know the number of pieces in the torrent yet.
peerHasAll bool
peerSentHaveAll bool
// The highest possible number of pieces the torrent could have based on
// communication with the peer. Generally only useful until we have the
// torrent info.
@ -102,6 +102,16 @@ type connection struct {
writerCond sync.Cond
}
func (cn *connection) peerHasAllPieces() (all bool, known bool) {
if cn.peerSentHaveAll {
return true, true
}
if !cn.t.haveInfo() {
return false, false
}
return bitmap.Flip(cn.peerPieces, 0, cn.t.numPieces()).IsEmpty(), true
}
func (cn *connection) mu() sync.Locker {
return &cn.t.cl.mu
}
@ -234,7 +244,7 @@ func (cn *connection) Close() {
}
func (cn *connection) PeerHasPiece(piece int) bool {
return cn.peerHasAll || cn.peerPieces.Contains(piece)
return cn.peerSentHaveAll || cn.peerPieces.Contains(piece)
}
func (cn *connection) Post(msg pp.Message) {
@ -695,7 +705,7 @@ func (cn *connection) peerSentHave(piece int) error {
}
func (cn *connection) peerSentBitfield(bf []bool) error {
cn.peerHasAll = false
cn.peerSentHaveAll = false
if len(bf)%8 != 0 {
panic("expected bitfield length divisible by 8")
}
@ -716,8 +726,8 @@ func (cn *connection) peerSentBitfield(bf []bool) error {
return nil
}
func (cn *connection) peerSentHaveAll() error {
cn.peerHasAll = true
func (cn *connection) onPeerSentHaveAll() error {
cn.peerSentHaveAll = true
cn.peerPieces.Clear()
cn.peerPiecesChanged()
return nil
@ -725,7 +735,7 @@ func (cn *connection) peerSentHaveAll() error {
func (cn *connection) peerSentHaveNone() error {
cn.peerPieces.Clear()
cn.peerHasAll = false
cn.peerSentHaveAll = false
cn.peerPiecesChanged()
return nil
}
@ -883,7 +893,7 @@ func (c *connection) mainReadLoop() error {
case pp.Bitfield:
err = c.peerSentBitfield(msg.Bitfield)
case pp.HaveAll:
err = c.peerSentHaveAll()
err = c.onPeerSentHaveAll()
case pp.HaveNone:
err = c.peerSentHaveNone()
case pp.Piece:

View File

@ -1354,6 +1354,12 @@ func (t *Torrent) statsLocked() TorrentStats {
t.stats.HalfOpenPeers = len(t.halfOpen)
t.stats.PendingPeers = len(t.peers)
t.stats.TotalPeers = t.numTotalPeers()
t.stats.ConnectedSeeders = 0
for c := range t.conns {
if all, ok := c.peerHasAllPieces(); all && ok {
t.stats.ConnectedSeeders++
}
}
return t.stats
}

View File

@ -3,8 +3,10 @@ package torrent
type TorrentStats struct {
ConnStats // Aggregates stats over all connections past and present.
ActivePeers int
HalfOpenPeers int
PendingPeers int
TotalPeers int
// Ordered by expected descending quantities (if all is well).
TotalPeers int
PendingPeers int
ActivePeers int
ConnectedSeeders int
HalfOpenPeers int
}