Fixes #957.
github.com/anacrolix/log v0.15.3-0.20240627045001-cd912c641d83
github.com/anacrolix/missinggo v1.3.0
github.com/anacrolix/missinggo/v2 v2.7.4
- github.com/anacrolix/multiless v0.3.0
+ github.com/anacrolix/multiless v0.4.0
github.com/anacrolix/possum/go v0.1.1-0.20240321122240-a01f3a22f2d1
github.com/anacrolix/squirrel v0.6.4
github.com/anacrolix/sync v0.5.1
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1
go.opentelemetry.io/otel/sdk v1.11.1
go.opentelemetry.io/otel/trace v1.11.1
- golang.org/x/exp v0.0.0-20240823005443-9b4947da3948
golang.org/x/sync v0.8.0
golang.org/x/sys v0.18.0
golang.org/x/time v0.0.0-20220609170525-579cf78fd858
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
+ golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
github.com/anacrolix/mmsg v0.0.0-20180515031531-a4a3ba1fc8bb/go.mod h1:x2/ErsYUmT77kezS63+wzZp8E3byYB0gzirM/WMBLfw=
github.com/anacrolix/mmsg v1.0.0 h1:btC7YLjOn29aTUAExJiVUhQOuf/8rhm+/nWCMAnL3Hg=
github.com/anacrolix/mmsg v1.0.0/go.mod h1:x8kRaJY/dCrY9Al0PEcj1mb/uFHwP6GCJ9fLl4thEPc=
-github.com/anacrolix/multiless v0.3.0 h1:5Bu0DZncjE4e06b9r1Ap2tUY4Au0NToBP5RpuEngSis=
-github.com/anacrolix/multiless v0.3.0/go.mod h1:TrCLEZfIDbMVfLoQt5tOoiBS/uq4y8+ojuEVVvTNPX4=
+github.com/anacrolix/multiless v0.4.0 h1:lqSszHkliMsZd2hsyrDvHOw4AbYWa+ijQ66LzbjqWjM=
+github.com/anacrolix/multiless v0.4.0/go.mod h1:zJv1JF9AqdZiHwxqPgjuOZDGWER6nyE48WBCi/OOrMM=
github.com/anacrolix/possum/go v0.1.1-0.20240321122240-a01f3a22f2d1 h1:lINi1HW+PExnMJkECx30AZSt0XT0cng9dVo3Zz5rSRM=
github.com/anacrolix/possum/go v0.1.1-0.20240321122240-a01f3a22f2d1/go.mod h1:pw5HEMBSiL+otYzHe4q5jGaVuy5unl+Mt4Bx6SDemW8=
github.com/anacrolix/squirrel v0.6.4 h1:K6ABRMCms0xwpEIdY3kAaDBUqiUeUYCKLKI0yHTr9IQ=
package metainfo
import (
- "sort"
+ "maps"
+ "slices"
g "github.com/anacrolix/generics"
- "golang.org/x/exp/maps"
"github.com/anacrolix/torrent/bencode"
)
}
func (ft *FileTree) orderedKeys() []string {
- keys := maps.Keys(ft.Dir)
- sort.Strings(keys)
- return keys
+ return slices.Sorted(maps.Keys(ft.Dir))
}
func (ft *FileTree) upvertedFiles(pieceLength int64, out func(fi FileInfo)) {
return ret
}
-func connLessTrusted(l, r *Peer) bool {
- return l.trust().Less(r.trust())
+func comparePeerTrust(l, r *Peer) int {
+ return l.trust().Cmp(r.trust())
}
func connIsIpv6(nc interface {
"errors"
"expvar"
"fmt"
- "github.com/anacrolix/torrent/internal/ctxrw"
"io"
"math"
"math/big"
"strconv"
"sync"
+
+ "github.com/anacrolix/torrent/internal/ctxrw"
)
const (
NetGoodPiecesDirted int64
}
-func (l connectionTrust) Less(r connectionTrust) bool {
- return multiless.New().Bool(l.Implicit, r.Implicit).Int64(l.NetGoodPiecesDirted, r.NetGoodPiecesDirted).Less()
+func (l connectionTrust) Cmp(r connectionTrust) int {
+ return multiless.New().Bool(l.Implicit, r.Implicit).Int64(l.NetGoodPiecesDirted, r.NetGoodPiecesDirted).OrderingInt()
}
// Returns a new Bitmap that includes bits for all pieces the peer could have based on their claims.
"github.com/anacrolix/log"
"github.com/anacrolix/missinggo/v2/bitmap"
"github.com/anacrolix/multiless"
- "golang.org/x/exp/maps"
"golang.org/x/time/rate"
"github.com/anacrolix/torrent/bencode"
if !cn.supportsExtension(pp.ExtensionNamePex) {
return "unsupported"
}
- if true {
- return fmt.Sprintf(
- "%v conns, %v unsent events",
- len(cn.pex.remoteLiveConns),
- cn.pex.numPending(),
- )
- } else {
- // This alternative branch prints out the remote live conn addresses.
- return fmt.Sprintf(
- "%v conns, %v unsent events",
- strings.Join(generics.SliceMap(
- maps.Keys(cn.pex.remoteLiveConns),
- func(from netip.AddrPort) string {
- return from.String()
- }), ","),
- cn.pex.numPending(),
- )
- }
+ return fmt.Sprintf(
+ "%v conns, %v unsent events",
+ len(cn.pex.remoteLiveConns),
+ cn.pex.numPending(),
+ )
}
func (cn *PeerConn) peerImplStatusLines() []string {
"crypto/rand"
"fmt"
"io"
+ "log/slog"
"net/http"
"os"
"path/filepath"
"github.com/anacrolix/log"
"github.com/anacrolix/sync"
"github.com/dustin/go-humanize"
- "golang.org/x/exp/slog"
"github.com/anacrolix/torrent"
"github.com/anacrolix/torrent/bencode"
"fmt"
"hash"
"io"
+ "iter"
+ "maps"
"math/rand"
"net/netip"
"net/url"
- "sort"
+ "slices"
"strings"
"text/tabwriter"
"time"
. "github.com/anacrolix/generics"
g "github.com/anacrolix/generics"
"github.com/anacrolix/log"
- "github.com/anacrolix/missinggo/slices"
"github.com/anacrolix/missinggo/v2"
"github.com/anacrolix/missinggo/v2/bitmap"
"github.com/anacrolix/missinggo/v2/pubsub"
"github.com/anacrolix/multiless"
"github.com/anacrolix/sync"
"github.com/pion/datachannel"
- "golang.org/x/exp/maps"
"golang.org/x/sync/errgroup"
"github.com/anacrolix/torrent/bencode"
fmt.Fprintln(w)
fmt.Fprintf(w, "Enabled trackers:\n")
- func() {
+ {
tw := tabwriter.NewWriter(w, 0, 0, 2, ' ', 0)
fmt.Fprintf(tw, " URL\tExtra\n")
- for _, ta := range slices.Sort(slices.FromMapElems(t.trackerAnnouncers), func(l, r torrentTrackerAnnouncer) bool {
- lu := l.URL()
- ru := r.URL()
- var luns, runs url.URL = *lu, *ru
- luns.Scheme = ""
- runs.Scheme = ""
- var ml missinggo.MultiLess
- ml.StrictNext(luns.String() == runs.String(), luns.String() < runs.String())
- ml.StrictNext(lu.String() == ru.String(), lu.String() < ru.String())
- return ml.Less()
- }).([]torrentTrackerAnnouncer) {
+ sortedTrackerAnnouncers := slices.SortedFunc(
+ maps.Values(t.trackerAnnouncers),
+ func(l, r torrentTrackerAnnouncer) int {
+ lu := l.URL()
+ ru := r.URL()
+ var luns, runs url.URL = *lu, *ru
+ luns.Scheme = ""
+ runs.Scheme = ""
+ var ml multiless.Computation
+ ml = multiless.EagerOrdered(ml, luns.String(), runs.String())
+ ml = multiless.EagerOrdered(ml, lu.String(), ru.String())
+ return ml.OrderingInt()
+ },
+ )
+ for _, ta := range sortedTrackerAnnouncers {
fmt.Fprintf(tw, " %q\t%v\n", ta.URL(), ta.statusLine())
}
tw.Flush()
- }()
+ }
fmt.Fprintf(w, "DHT Announces: %d\n", t.numDHTAnnounces)
fmt.Fprintf(w, "webseeds:\n")
t.writePeerStatuses(w, maps.Values(t.webSeeds))
- peerConns := maps.Keys(t.conns)
// Peers without priorities first, then those with. I'm undecided about how to order peers
// without priorities.
- sort.Slice(peerConns, func(li, ri int) bool {
- l := peerConns[li]
- r := peerConns[ri]
+ peerConns := slices.SortedFunc(maps.Keys(t.conns), func(l, r *PeerConn) int {
ml := multiless.New()
lpp := g.ResultFromTuple(l.peerPriority()).ToOption()
rpp := g.ResultFromTuple(r.peerPriority()).ToOption()
ml = ml.Bool(lpp.Ok, rpp.Ok)
ml = ml.Uint32(rpp.Value, lpp.Value)
- return ml.Less()
+ return ml.OrderingInt()
})
fmt.Fprintf(w, "%v peer conns:\n", len(peerConns))
- t.writePeerStatuses(w, g.SliceMap(peerConns, func(pc *PeerConn) *Peer {
- return &pc.Peer
- }))
+ var peerIter iter.Seq[*Peer] = func(yield func(*Peer) bool) {
+ for _, pc := range peerConns {
+ if !yield(&pc.Peer) {
+ return
+ }
+ }
+ }
+ t.writePeerStatuses(w, peerIter)
}
-func (t *Torrent) writePeerStatuses(w io.Writer, peers []*Peer) {
+func (t *Torrent) writePeerStatuses(w io.Writer, peers iter.Seq[*Peer]) {
var buf bytes.Buffer
- for _, c := range peers {
+ for c := range peers {
fmt.Fprintf(w, "- ")
buf.Reset()
c.writeStatus(&buf)
}
}
t.clearPieceTouchers(piece)
- slices.Sort(bannableTouchers, connLessTrusted)
+ slices.SortFunc(bannableTouchers, comparePeerTrust)
if t.cl.config.Debug {
t.logger.Printf(