]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Comments and tidies
authorMatt Joiner <anacrolix@gmail.com>
Mon, 28 Apr 2025 00:15:18 +0000 (10:15 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Mon, 28 Apr 2025 00:15:18 +0000 (10:15 +1000)
client_test.go
misc.go
reader.go
storage/possum/key-sorter.go [new file with mode: 0644]
storage/possum/possum-provider.go
storage/wrappers.go
torrent.go

index b6ee1c8d2f8f22c3356eebae127248cce49f8353..26714deba7ea9d40abae391866d7f4c3b59d3133 100644 (file)
@@ -323,7 +323,7 @@ func TestTorrentDroppedDuringResponsiveRead(t *testing.T) {
        }())
        leecherTorrent.AddClientPeer(seeder)
        reader := leecherTorrent.NewReader()
-       defer reader.Close()
+       t.Cleanup(func() { reader.Close() })
        reader.SetReadahead(0)
        reader.SetResponsive()
        b := make([]byte, 2)
diff --git a/misc.go b/misc.go
index 16538b781ecfede8d2658aba26ad80c7b34a6402..b657d104288b4fbc6fcda64508bc0ef5ce00270e 100644 (file)
--- a/misc.go
+++ b/misc.go
@@ -124,29 +124,6 @@ func connIsIpv6(nc interface {
        return rip.To4() == nil && rip.To16() != nil
 }
 
-func clamp(min, value, max int64) int64 {
-       if min > max {
-               panic("harumph")
-       }
-       if value < min {
-               value = min
-       }
-       if value > max {
-               value = max
-       }
-       return value
-}
-
-func max(as ...int64) int64 {
-       ret := as[0]
-       for _, a := range as[1:] {
-               if a > ret {
-                       ret = a
-               }
-       }
-       return ret
-}
-
 func maxInt(as ...int) int {
        ret := as[0]
        for _, a := range as[1:] {
index 31d4682c39e4d970d9bf571e98e07a913cec82da..a283a2ba91b323c8da9acc64dd9db85c138e046a 100644 (file)
--- a/reader.go
+++ b/reader.go
@@ -12,9 +12,14 @@ import (
 )
 
 // Accesses Torrent data via a Client. Reads block until the data is available. Seeks and readahead
-// also drive Client behaviour. Not safe for concurrent use.
+// also drive Client behaviour. Not safe for concurrent use. There are Torrent, File and Piece
+// constructors for this.
 type Reader interface {
+       // Read/Seek and not ReadAt because we want to return data as soon as it's available, and
+       // because we want a single read head.
        io.ReadSeekCloser
+       // Deprecated: This prevents type asserting for optional interfaces because a wrapper is
+       // required to adapt back to io.Reader.
        missinggo.ReadContexter
        // Configure the number of bytes ahead of a read that should also be prioritized in preparation
        // for further reads. Overridden by non-nil readahead func, see SetReadaheadFunc.
@@ -24,7 +29,8 @@ type Reader interface {
        // locked.
        SetReadaheadFunc(ReadaheadFunc)
        // Don't wait for pieces to complete and be verified. Read calls return as soon as they can when
-       // the underlying chunks become available.
+       // the underlying chunks become available. May be deprecated, although BitTorrent v2 will mean
+       // we can support this without piece hashing.
        SetResponsive()
 }
 
@@ -220,7 +226,7 @@ func (r *reader) waitAvailable(ctx context.Context, pos, wanted int64, wait bool
 }
 
 // Adds the reader's torrent offset to the reader object offset (for example the reader might be
-// constrainted to a particular file within the torrent).
+// constrained to a particular file within the torrent).
 func (r *reader) torrentOffset(readerPos int64) int64 {
        return r.offset + readerPos
 }
diff --git a/storage/possum/key-sorter.go b/storage/possum/key-sorter.go
new file mode 100644 (file)
index 0000000..b1a44c0
--- /dev/null
@@ -0,0 +1,24 @@
+package possumTorrentStorage
+
+import (
+       "cmp"
+)
+
+// Sorts by a precomputed key but swaps on another slice at the same time.
+type keySorter[T any, K cmp.Ordered] struct {
+       orig []T
+       keys []K
+}
+
+func (o keySorter[T, K]) Len() int {
+       return len(o.keys)
+}
+
+func (o keySorter[T, K]) Less(i, j int) bool {
+       return o.keys[i] < o.keys[j]
+}
+
+func (o keySorter[T, K]) Swap(i, j int) {
+       o.keys[i], o.keys[j] = o.keys[j], o.keys[i]
+       o.orig[i], o.orig[j] = o.orig[j], o.orig[i]
+}
index 9eff1bb249a55f8db9b73ef4493c4834a1a7892b..12dc83d4b1a120c4ced112143f0993e973ea5f81 100644 (file)
@@ -3,7 +3,6 @@
 package possumTorrentStorage
 
 import (
-       "cmp"
        "fmt"
        "io"
        "sort"
@@ -27,25 +26,6 @@ type Provider struct {
 
 var _ storage.ConsecutiveChunkReader = Provider{}
 
-// Sorts by a precomputed key but swaps on another slice at the same time.
-type keySorter[T any, K cmp.Ordered] struct {
-       orig []T
-       keys []K
-}
-
-func (o keySorter[T, K]) Len() int {
-       return len(o.keys)
-}
-
-func (o keySorter[T, K]) Less(i, j int) bool {
-       return o.keys[i] < o.keys[j]
-}
-
-func (o keySorter[T, K]) Swap(i, j int) {
-       o.keys[i], o.keys[j] = o.keys[j], o.keys[i]
-       o.orig[i], o.orig[j] = o.orig[j], o.orig[i]
-}
-
 // TODO: Should the parent ReadConsecutiveChunks method take the expected number of bytes to avoid
 // trying to read discontinuous or incomplete sequences of chunks?
 func (p Provider) ReadConsecutiveChunks(prefix string) (rc io.ReadCloser, err error) {
index 92b3e785c9b94d95dd1140eae91d2407cb5e9a9e..4f239736d2c4b79df28f11e56b848ab64520e48f 100644 (file)
@@ -85,6 +85,8 @@ func (p Piece) WriteAt(b []byte, off int64) (n int, err error) {
        return p.PieceImpl.WriteAt(b, off)
 }
 
+// If you're calling this you're probably doing something very inefficient. Consider WriteTo which
+// handles data spread across multiple objects in storage.
 func (p Piece) ReadAt(b []byte, off int64) (n int, err error) {
        if off < 0 {
                err = os.ErrInvalid
index 280ae4507d6d8cd319a37766d5d07ef3851029f9..3903e0ec201cd07f8f0ee21a9a251dd5185f570d 100644 (file)
@@ -149,7 +149,8 @@ type Torrent struct {
        _readerReadaheadPieces bitmap.Bitmap
 
        // A cache of pieces we need to get. Calculated from various piece and file priorities and
-       // completion states elsewhere. Includes piece data and piece v2 hashes.
+       // completion states elsewhere. Includes piece data and piece v2 hashes. Used for efficient set
+       // logic with peer pieces.
        _pendingPieces roaring.Bitmap
        // A cache of completed piece indices.
        _completedPieces roaring.Bitmap
@@ -1424,11 +1425,7 @@ func (t *Torrent) readerPosChanged(from, to pieceRange) {
                t.updatePiecePriorities(h.begin, h.end, "Torrent.readerPosChanged")
        } else {
                // Ranges overlap.
-               end := l.end
-               if h.end > end {
-                       end = h.end
-               }
-               t.updatePiecePriorities(l.begin, end, "Torrent.readerPosChanged")
+               t.updatePiecePriorities(l.begin, max(l.end, h.end), "Torrent.readerPosChanged")
        }
 }
 
@@ -3040,6 +3037,7 @@ func (t *Torrent) numActivePeers() int {
        return len(t.conns) + len(t.webSeeds)
 }
 
+// Specifically, whether we can expect data to vanish while trying to read.
 func (t *Torrent) hasStorageCap() bool {
        f := t.storage.Capacity
        if f == nil {