]> Sergey Matveev's repositories - btrtrc.git/blobdiff - t.go
Drop support for go 1.20
[btrtrc.git] / t.go
diff --git a/t.go b/t.go
index 8da398832be19c46bccfbef5ddcbc18318baad87..45856cc7acbeaa5988074f74435d078a49111a57 100644 (file)
--- a/t.go
+++ b/t.go
@@ -4,7 +4,9 @@ import (
        "strconv"
        "strings"
 
-       "github.com/anacrolix/missinggo/pubsub"
+       "github.com/anacrolix/chansync/events"
+       "github.com/anacrolix/missinggo/v2/pubsub"
+       "github.com/anacrolix/sync"
 
        "github.com/anacrolix/torrent/metainfo"
 )
@@ -15,24 +17,22 @@ func (t *Torrent) InfoHash() metainfo.Hash {
 }
 
 // Returns a channel that is closed when the info (.Info()) for the torrent has become available.
-func (t *Torrent) GotInfo() <-chan struct{} {
-       // TODO: We shouldn't need to lock to take a channel here, if the event is only ever set.
-       t.cl.lock()
-       defer t.cl.unlock()
-       return t.gotMetainfo.C()
+func (t *Torrent) GotInfo() events.Done {
+       return t.gotMetainfoC
 }
 
 // Returns the metainfo info dictionary, or nil if it's not yet available.
-func (t *Torrent) Info() *metainfo.Info {
-       t.cl.lock()
-       defer t.cl.unlock()
-       return t.info
+func (t *Torrent) Info() (info *metainfo.Info) {
+       t.nameMu.RLock()
+       info = t.info
+       t.nameMu.RUnlock()
+       return
 }
 
 // Returns a Reader bound to the torrent's data. All read calls block until the data requested is
 // actually available. Note that you probably want to ensure the Torrent Info is available first.
 func (t *Torrent) NewReader() Reader {
-       return t.newReader(0, *t.length)
+       return t.newReader(0, t.length())
 }
 
 func (t *Torrent) newReader(offset, length int64) Reader {
@@ -42,7 +42,7 @@ func (t *Torrent) newReader(offset, length int64) Reader {
                offset: offset,
                length: length,
        }
-       r.readaheadFunc = r.sqrtReadahead
+       r.readaheadFunc = defaultReadaheadFunc
        t.addReader(&r)
        return &r
 }
@@ -71,10 +71,11 @@ func (t *Torrent) PieceStateRuns() (runs PieceStateRuns) {
        return
 }
 
-func (t *Torrent) PieceState(piece pieceIndex) PieceState {
+func (t *Torrent) PieceState(piece pieceIndex) (ps PieceState) {
        t.cl.rLock()
-       defer t.cl.rUnlock()
-       return t.pieceState(piece)
+       ps = t.pieceState(piece)
+       t.cl.rUnlock()
+       return
 }
 
 // The number of pieces in the torrent. This requires that the info has been
@@ -85,8 +86,8 @@ func (t *Torrent) NumPieces() pieceIndex {
 
 // Get missing bytes count for specific piece.
 func (t *Torrent) PieceBytesMissing(piece int) int64 {
-       t.cl.lock()
-       defer t.cl.unlock()
+       t.cl.rLock()
+       defer t.cl.rUnlock()
 
        return int64(t.pieces[piece].bytesLeft())
 }
@@ -95,9 +96,14 @@ func (t *Torrent) PieceBytesMissing(piece int) int64 {
 // this. No data corruption can, or should occur to either the torrent's data,
 // or connected peers.
 func (t *Torrent) Drop() {
+       var wg sync.WaitGroup
+       defer wg.Wait()
        t.cl.lock()
        defer t.cl.unlock()
-       t.cl.dropTorrent(t.infoHash)
+       err := t.cl.dropTorrent(t.infoHash, &wg)
+       if err != nil {
+               panic(err)
+       }
 }
 
 // Number of bytes of the entire torrent we have completed. This is the sum of
@@ -112,27 +118,27 @@ func (t *Torrent) BytesCompleted() int64 {
 
 // The subscription emits as (int) the index of pieces as their state changes.
 // A state change is when the PieceState for a piece alters in value.
-func (t *Torrent) SubscribePieceStateChanges() *pubsub.Subscription {
+func (t *Torrent) SubscribePieceStateChanges() *pubsub.Subscription[PieceStateChange] {
        return t.pieceStateChanges.Subscribe()
 }
 
 // Returns true if the torrent is currently being seeded. This occurs when the
 // client is willing to upload without wanting anything in return.
-func (t *Torrent) Seeding() bool {
-       t.cl.lock()
-       defer t.cl.unlock()
-       return t.seeding()
+func (t *Torrent) Seeding() (ret bool) {
+       t.cl.rLock()
+       ret = t.seeding()
+       t.cl.rUnlock()
+       return
 }
 
-// Clobbers the torrent display name. The display name is used as the torrent
-// name if the metainfo is not available.
+// Clobbers the torrent display name if metainfo is unavailable.
+// The display name is used as the torrent name while the metainfo is unavailable.
 func (t *Torrent) SetDisplayName(dn string) {
        t.nameMu.Lock()
-       defer t.nameMu.Unlock()
-       if t.haveInfo() {
-               return
+       if !t.haveInfo() {
+               t.displayName = dn
        }
-       t.displayName = dn
+       t.nameMu.Unlock()
 }
 
 // The current working name for the torrent. Either the name in the info dict,
@@ -144,14 +150,14 @@ func (t *Torrent) Name() string {
 // The completed length of all the torrent data, in all its files. This is
 // derived from the torrent info, when it is available.
 func (t *Torrent) Length() int64 {
-       return *t.length
+       return t._length.Value
 }
 
 // Returns a run-time generated metainfo for the torrent that includes the
 // info bytes and announce-list as currently known to the client.
 func (t *Torrent) Metainfo() metainfo.MetaInfo {
-       t.cl.lock()
-       defer t.cl.unlock()
+       t.cl.rLock()
+       defer t.cl.rUnlock()
        return t.newMetaInfo()
 }
 
@@ -175,32 +181,32 @@ func (t *Torrent) deleteReader(r *reader) {
 // has been obtained, see Torrent.Info and Torrent.GotInfo.
 func (t *Torrent) DownloadPieces(begin, end pieceIndex) {
        t.cl.lock()
-       defer t.cl.unlock()
        t.downloadPiecesLocked(begin, end)
+       t.cl.unlock()
 }
 
 func (t *Torrent) downloadPiecesLocked(begin, end pieceIndex) {
        for i := begin; i < end; i++ {
                if t.pieces[i].priority.Raise(PiecePriorityNormal) {
-                       t.updatePiecePriority(i)
+                       t.updatePiecePriority(i, "Torrent.DownloadPieces")
                }
        }
 }
 
 func (t *Torrent) CancelPieces(begin, end pieceIndex) {
        t.cl.lock()
-       defer t.cl.unlock()
-       t.cancelPiecesLocked(begin, end)
+       t.cancelPiecesLocked(begin, end, "Torrent.CancelPieces")
+       t.cl.unlock()
 }
 
-func (t *Torrent) cancelPiecesLocked(begin, end pieceIndex) {
+func (t *Torrent) cancelPiecesLocked(begin, end pieceIndex, reason string) {
        for i := begin; i < end; i++ {
                p := &t.pieces[i]
                if p.priority == PiecePriorityNone {
                        continue
                }
                p.priority = PiecePriorityNone
-               t.updatePiecePriority(i)
+               t.updatePiecePriority(i, reason)
        }
 }
 
@@ -208,28 +214,17 @@ func (t *Torrent) initFiles() {
        var offset int64
        t.files = new([]*File)
        for _, fi := range t.info.UpvertedFiles() {
-               var path []string
-               if len(fi.PathUTF8) != 0 {
-                       path = fi.PathUTF8
-               } else {
-                       path = fi.Path
-               }
-               dp := t.info.Name
-               if len(fi.Path) != 0 {
-                       dp = strings.Join(fi.Path, "/")
-               }
                *t.files = append(*t.files, &File{
                        t,
-                       strings.Join(append([]string{t.info.Name}, path...), "/"),
+                       strings.Join(append([]string{t.info.BestName()}, fi.BestPath()...), "/"),
                        offset,
                        fi.Length,
                        fi,
-                       dp,
+                       fi.DisplayPath(t.info),
                        PiecePriorityNone,
                })
                offset += fi.Length
        }
-
 }
 
 // Returns handles to the files in the torrent. This requires that the Info is
@@ -238,11 +233,11 @@ func (t *Torrent) Files() []*File {
        return *t.files
 }
 
-func (t *Torrent) AddPeers(pp []PeerInfo) int {
-       cl := t.cl
-       cl.lock()
-       defer cl.unlock()
-       return t.addPeers(pp)
+func (t *Torrent) AddPeers(pp []PeerInfo) (n int) {
+       t.cl.lock()
+       defer t.cl.unlock()
+       n = t.addPeers(pp)
+       return
 }
 
 // Marks the entire torrent for download. Requires the info first, see