]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Try a state-delta function for updating request state
authorMatt Joiner <anacrolix@gmail.com>
Thu, 17 Aug 2017 15:51:02 +0000 (01:51 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Thu, 17 Aug 2017 15:51:02 +0000 (01:51 +1000)
Also adds Torrent.networkingEnabled, though it isn't yet useful.

client.go
connection.go
torrent.go

index 13f5d24abac96a2c4970f293da741a284decca5c..e66e519c9d29c215ae81baf2bb5aaab34081abbf 100644 (file)
--- a/client.go
+++ b/client.go
@@ -1178,6 +1178,8 @@ func (cl *Client) newTorrent(ih metainfo.Hash, specStorage storage.ClientImpl) (
 
                storageOpener:       storageClient,
                maxEstablishedConns: defaultEstablishedConnsPerTorrent,
+
+               networkingEnabled: true,
        }
        t.setChunkSize(defaultChunkSize)
        return
index aca2b348587a1b16ac155aaddda38d0a768b5260..d496f0c70032e66330df72cc1b6bd0d3850952c0 100644 (file)
@@ -484,26 +484,67 @@ func (cn *connection) Bitfield(haves []bool) {
        cn.sentHaves = append([]bool(nil), haves...)
 }
 
+func nextRequestState(
+       networkingEnabled bool,
+       currentRequests map[request]struct{},
+       peerChoking bool,
+       nextPieces prioritybitmap.PriorityBitmap,
+       pendingChunks func(piece int, f func(chunkSpec) bool) bool,
+       requestsLowWater int,
+       requestsHighWater int,
+) (
+       requests map[request]struct{},
+       interested bool,
+) {
+       if !networkingEnabled || nextPieces.IsEmpty() {
+               return nil, false
+       }
+       if peerChoking || len(currentRequests) > requestsLowWater {
+               return currentRequests, true
+       }
+       requests = make(map[request]struct{}, requestsHighWater)
+       for r := range currentRequests {
+               requests[r] = struct{}{}
+       }
+       nextPieces.IterTyped(func(piece int) bool {
+               return pendingChunks(piece, func(cs chunkSpec) bool {
+                       if len(requests) >= requestsHighWater {
+                               return false
+                       }
+                       r := request{pp.Integer(piece), cs}
+                       requests[r] = struct{}{}
+                       return true
+               })
+       })
+       return requests, true
+}
+
 func (cn *connection) updateRequests() {
-       if !cn.t.haveInfo() {
-               return
-       }
-       if cn.Interested {
-               if cn.PeerChoked {
-                       return
-               }
-               if len(cn.Requests) > cn.requestsLowWater {
-                       return
+       rs, i := nextRequestState(
+               cn.t.networkingEnabled,
+               cn.Requests,
+               cn.PeerChoked,
+               cn.pieceRequestOrder,
+               func(piece int, f func(chunkSpec) bool) bool {
+                       return undirtiedChunks(piece, cn.t, f)
+               },
+               cn.requestsLowWater,
+               cn.nominalMaxRequests())
+       for r := range cn.Requests {
+               if _, ok := rs[r]; !ok {
+                       if !cn.Cancel(r) {
+                               panic("wat")
+                       }
                }
        }
-       cn.fillRequests()
-       if len(cn.Requests) == 0 && !cn.PeerChoked {
-               // So we're not choked, but we don't want anything right now. We may
-               // have completed readahead, and the readahead window has not rolled
-               // over to the next piece. Better to stay interested in case we're
-               // going to want data in the near future.
-               cn.SetInterested(!cn.t.haveAllPieces())
+       for r := range rs {
+               if _, ok := cn.Requests[r]; !ok {
+                       if !cn.Request(r) {
+                               panic("how")
+                       }
+               }
        }
+       cn.SetInterested(i)
 }
 
 func (cn *connection) fillRequests() {
@@ -526,6 +567,13 @@ func (c *connection) requestPiecePendingChunks(piece int) (again bool) {
        })
 }
 
+func undirtiedChunks(piece int, t *Torrent, f func(chunkSpec) bool) bool {
+       chunkIndices := t.pieces[piece].undirtiedChunkIndices().ToSortedSlice()
+       return iter.ForPerm(len(chunkIndices), func(i int) bool {
+               return f(t.chunkIndexSpec(chunkIndices[i], piece))
+       })
+}
+
 func (cn *connection) stopRequestingPiece(piece int) {
        cn.pieceRequestOrder.Remove(piece)
        cn.updateRequests()
index 8230acbfd574ad7164c44b28b55d304713c82644..d361bd6e338828f0289b934d4d7dd7ae5b5d3ad0 100644 (file)
@@ -43,6 +43,8 @@ type peersKey struct {
 type Torrent struct {
        cl *Client
 
+       networkingEnabled bool
+
        closed   missinggo.Event
        infoHash metainfo.Hash
        pieces   []piece
@@ -1348,6 +1350,9 @@ func (t *Torrent) addConnection(c *connection, outgoing bool) bool {
 }
 
 func (t *Torrent) wantConns() bool {
+       if !t.networkingEnabled {
+               return false
+       }
        if t.closed.IsSet() {
                return false
        }