"github.com/anacrolix/log"
"github.com/anacrolix/missinggo/iter"
"github.com/anacrolix/missinggo/v2/bitmap"
- "github.com/anacrolix/missinggo/v2/prioritybitmap"
"github.com/anacrolix/multiless"
"github.com/anacrolix/chansync"
PeerExtensionIDs map[pp.ExtensionName]pp.ExtensionNumber
PeerClientName string
- pieceInclination []int
- _pieceRequestOrder prioritybitmap.PriorityBitmap
-
logger log.Logger
}
if !p.closed.Set() {
return
}
- p.discardPieceInclination()
- p._pieceRequestOrder.Clear()
p.peerImpl.onClose()
if p.t != nil {
p.t.decPeerPieceAvailability(p)
func (cn *PeerConn) updateRequests() {
if peerRequesting {
- cn.nextRequestState = cn.getDesiredRequestState()
cn.tickleWriter()
return
}
}
}
-// check callers updaterequests
-func (cn *Peer) stopRequestingPiece(piece pieceIndex) bool {
- return cn._pieceRequestOrder.Remove(piece)
-}
-
-// This is distinct from Torrent piece priority, which is the user's
-// preference. Connection piece priority is specific to a connection and is
-// used to pseudorandomly avoid connections always requesting the same pieces
-// and thus wasting effort.
-func (cn *Peer) updatePiecePriority(piece pieceIndex) bool {
- tpp := cn.t.piecePriority(piece)
- if !cn.peerHasPiece(piece) {
- tpp = PiecePriorityNone
- }
- if tpp == PiecePriorityNone {
- return cn.stopRequestingPiece(piece)
- }
- prio := cn.getPieceInclination()[piece]
- return cn._pieceRequestOrder.Set(piece, prio)
-}
-
-func (cn *Peer) getPieceInclination() []int {
- if cn.pieceInclination == nil {
- cn.pieceInclination = cn.t.getConnPieceInclination()
- }
- return cn.pieceInclination
-}
-
-func (cn *Peer) discardPieceInclination() {
- if cn.pieceInclination == nil {
- return
- }
- cn.t.putPieceInclination(cn.pieceInclination)
- cn.pieceInclination = nil
-}
-
func (cn *Peer) peerPiecesChanged() {
- if cn.t.haveInfo() {
- prioritiesChanged := false
- for i := pieceIndex(0); i < cn.t.numPieces(); i++ {
- if cn.updatePiecePriority(i) {
- prioritiesChanged = true
- }
- }
- if prioritiesChanged {
- cn.updateRequests()
- }
- }
+ cn.updateRequests()
cn.t.maybeDropMutuallyCompletePeer(cn)
}
cn.t.incPieceAvailability(piece)
}
cn._peerPieces.Add(uint32(piece))
- cn.t.maybeDropMutuallyCompletePeer(&cn.Peer)
- if cn.updatePiecePriority(piece) {
- cn.updateRequests()
- }
+ cn.peerPiecesChanged()
return nil
}
}
func (c *Peer) peerHasWantedPieces() bool {
- return !c._pieceRequestOrder.IsEmpty()
+ // TODO: Can this be done just with AndCardinality?
+ missingPeerHas := c.newPeerPieces()
+ missingPeerHas.AndNot(&c.t._completedPieces)
+ return !missingPeerHas.IsEmpty()
}
func (c *Peer) deleteRequest(r RequestIndex) bool {
}
func (t *Torrent) maybeDropMutuallyCompletePeer(
- // I'm not sure about taking peer here, not all peer implementations actually drop. Maybe that's okay?
+ // I'm not sure about taking peer here, not all peer implementations actually drop. Maybe that's
+ // okay?
p *Peer,
) {
if !t.cl.config.DropMutuallyCompletePeers {
}
func (t *Torrent) piecePriorityChanged(piece pieceIndex) {
- // t.logger.Printf("piece %d priority changed", piece)
- t.iterPeers(func(c *Peer) {
- if c.updatePiecePriority(piece) {
- // log.Print("conn piece priority changed")
+ if true || t._pendingPieces.Contains(piece) {
+ t.iterPeers(func(c *Peer) {
c.updateRequests()
- }
- })
+ })
+ }
t.maybeNewConns()
t.publishPieceChange(piece)
}