1 package requestStrategy
6 "github.com/anacrolix/multiless"
8 "github.com/anacrolix/torrent/metainfo"
9 "github.com/anacrolix/torrent/types"
14 ChunkIndex = RequestIndex
15 Request = types.Request
16 pieceIndex = types.PieceIndex
17 piecePriority = types.PiecePriority
18 // This can be made into a type-param later, will be great for testing.
19 ChunkSpec = types.ChunkSpec
22 func pieceOrderLess(i, j *pieceRequestOrderItem) multiless.Computation {
23 return multiless.New().Int(
24 int(j.state.Priority), int(i.state.Priority),
25 // TODO: Should we match on complete here to prevent churn when availability changes?
27 j.state.Partial, i.state.Partial,
29 // If this is done with relative availability, do we lose some determinism? If completeness
30 // is used, would that push this far enough down?
31 i.state.Availability, j.state.Availability,
33 i.key.Index, j.key.Index,
34 ).Lazy(func() multiless.Computation {
35 return multiless.New().Cmp(bytes.Compare(
42 // Calls f with requestable pieces in order.
43 func GetRequestablePieces(
44 input Input, pro *PieceRequestOrder,
45 f func(ih metainfo.Hash, pieceIndex int, orderState PieceRequestOrderState),
47 // Storage capacity left for this run, keyed by the storage capacity pointer on the storage
48 // TorrentImpl. A nil value means no capacity limit.
49 var storageLeft *int64
50 if cap, ok := input.Capacity(); ok {
53 var allTorrentsUnverifiedBytes int64
54 pro.tree.Scan(func(_i pieceRequestOrderItem) bool {
56 var t Torrent = input.Torrent(ih)
57 var piece Piece = t.Piece(_i.key.Index)
58 pieceLength := t.PieceLength()
59 if storageLeft != nil {
60 if *storageLeft < pieceLength {
63 *storageLeft -= pieceLength
65 if !piece.Request() || piece.NumPendingChunks() == 0 {
66 // TODO: Clarify exactly what is verified. Stuff that's being hashed should be
67 // considered unverified and hold up further requests.
70 if input.MaxUnverifiedBytes() != 0 && allTorrentsUnverifiedBytes+pieceLength > input.MaxUnverifiedBytes() {
73 allTorrentsUnverifiedBytes += pieceLength
74 f(ih, _i.key.Index, _i.state)
80 type Input interface {
81 Torrent(metainfo.Hash) Torrent
82 // Storage capacity, shared among all Torrents with the same storage.TorrentCapacity pointer in
83 // their storage.Torrent references.
84 Capacity() (cap int64, capped bool)
85 // Across all the Torrents. This might be partitioned by storage capacity key now.
86 MaxUnverifiedBytes() int64