]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Begin exposing all the magic that Client.WriteStatus has so people can parse Client...
authorMatt Joiner <anacrolix@gmail.com>
Fri, 29 Jul 2016 14:37:52 +0000 (00:37 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Fri, 29 Jul 2016 14:37:52 +0000 (00:37 +1000)
It wasn't possible to move Client.WriteStatus to an external package to verify it doesn't depend on same-package access to data because then it can't be used in the tests, and it's extremely useful there. So I've settled for not locking the Client, and trying to use all the public methods. It's a work in progress.

client.go
metainfo/hash.go
torrent.go

index d1654f8f186f974fe2a152e5b67f267bf2d42966..0e0d18eb1b95fa2c3856af8f4064a1924389d0e7 100644 (file)
--- a/client.go
+++ b/client.go
@@ -9,11 +9,9 @@ import (
        "fmt"
        "io"
        "log"
-       "math/big"
        mathRand "math/rand"
        "net"
        "net/url"
-       "sort"
        "strconv"
        "strings"
        "time"
@@ -85,6 +83,12 @@ type Client struct {
        torrents map[metainfo.Hash]*Torrent
 }
 
+func (cl *Client) BadPeerIPs() []string {
+       cl.mu.RLock()
+       defer cl.mu.RUnlock()
+       return slices.FromMapKeys(cl.badPeerIPs).([]string)
+}
+
 func (cl *Client) IPBlockList() iplist.Ranger {
        cl.mu.Lock()
        defer cl.mu.Unlock()
@@ -117,67 +121,45 @@ func (cl *Client) ListenAddr() net.Addr {
        return torrentAddr(cl.listenAddr)
 }
 
-type hashSorter struct {
-       Hashes []metainfo.Hash
-}
-
-func (hs hashSorter) Len() int {
-       return len(hs.Hashes)
-}
-
-func (hs hashSorter) Less(a, b int) bool {
-       return (&big.Int{}).SetBytes(hs.Hashes[a][:]).Cmp((&big.Int{}).SetBytes(hs.Hashes[b][:])) < 0
-}
-
-func (hs hashSorter) Swap(a, b int) {
-       hs.Hashes[a], hs.Hashes[b] = hs.Hashes[b], hs.Hashes[a]
-}
-
 func (cl *Client) sortedTorrents() (ret []*Torrent) {
-       var hs hashSorter
-       for ih := range cl.torrents {
-               hs.Hashes = append(hs.Hashes, ih)
-       }
-       sort.Sort(hs)
-       for _, ih := range hs.Hashes {
-               ret = append(ret, cl.torrent(ih))
-       }
-       return
+       return slices.Sort(slices.FromMapElems(cl.torrents), func(l, r metainfo.Hash) bool {
+               return l.AsString() < r.AsString()
+       }).([]*Torrent)
 }
 
 // Writes out a human readable status of the client, such as for writing to a
 // HTTP status page.
 func (cl *Client) WriteStatus(_w io.Writer) {
-       cl.mu.RLock()
-       defer cl.mu.RUnlock()
        w := bufio.NewWriter(_w)
        defer w.Flush()
        if addr := cl.ListenAddr(); addr != nil {
-               fmt.Fprintf(w, "Listening on %s\n", cl.ListenAddr())
+               fmt.Fprintf(w, "Listening on %s\n", addr)
        } else {
                fmt.Fprintln(w, "Not listening!")
        }
-       fmt.Fprintf(w, "Peer ID: %+q\n", cl.peerID)
-       fmt.Fprintf(w, "Banned IPs: %d\n", len(cl.badPeerIPs))
-       if cl.dHT != nil {
-               dhtStats := cl.dHT.Stats()
+       fmt.Fprintf(w, "Peer ID: %+q\n", cl.PeerID())
+       fmt.Fprintf(w, "Banned IPs: %d\n", len(cl.BadPeerIPs()))
+       if dht := cl.DHT(); dht != nil {
+               dhtStats := dht.Stats()
                fmt.Fprintf(w, "DHT nodes: %d (%d good, %d banned)\n", dhtStats.Nodes, dhtStats.GoodNodes, dhtStats.BadNodes)
-               fmt.Fprintf(w, "DHT Server ID: %x\n", cl.dHT.ID())
-               fmt.Fprintf(w, "DHT port: %d\n", missinggo.AddrPort(cl.dHT.Addr()))
+               fmt.Fprintf(w, "DHT Server ID: %x\n", dht.ID())
+               fmt.Fprintf(w, "DHT port: %d\n", missinggo.AddrPort(dht.Addr()))
                fmt.Fprintf(w, "DHT announces: %d\n", dhtStats.ConfirmedAnnounces)
                fmt.Fprintf(w, "Outstanding transactions: %d\n", dhtStats.OutstandingTransactions)
        }
-       fmt.Fprintf(w, "# Torrents: %d\n", len(cl.torrents))
+       fmt.Fprintf(w, "# Torrents: %d\n", len(cl.Torrents()))
        fmt.Fprintln(w)
-       for _, t := range cl.sortedTorrents() {
-               if t.name() == "" {
+       for _, t := range slices.Sorted(cl.Torrents(), func(l, r *Torrent) bool {
+               return l.InfoHash().AsString() < r.InfoHash().AsString()
+       }).([]*Torrent) {
+               if t.Name() == "" {
                        fmt.Fprint(w, "<unknown name>")
                } else {
-                       fmt.Fprint(w, t.name())
+                       fmt.Fprint(w, t.Name())
                }
                fmt.Fprint(w, "\n")
-               if t.haveInfo() {
-                       fmt.Fprintf(w, "%f%% of %d bytes (%s)", 100*(1-float64(t.bytesLeft())/float64(t.length)), t.length, humanize.Bytes(uint64(t.length)))
+               if t.Info() != nil {
+                       fmt.Fprintf(w, "%f%% of %d bytes (%s)", 100*(1-float64(t.BytesMissing())/float64(t.Info().TotalLength())), t.length, humanize.Bytes(uint64(t.Info().TotalLength())))
                } else {
                        w.WriteString("<missing metainfo>")
                }
index c755468c0716269a4ba50837270c433b49ced9e3..000179ee4ef0935ea7534535b2b0b35bb054ce44 100644 (file)
@@ -13,7 +13,7 @@ func (h Hash) Bytes() []byte {
        return h[:]
 }
 
-func (h *Hash) AsString() string {
+func (h Hash) AsString() string {
        return string(h[:])
 }
 
index eefee14c2f0b10335567d9076fdd4c70422566f1..da0c92bbe13d93bb454ea52315bb18ee4ee6114d 100644 (file)
@@ -488,6 +488,12 @@ func (t *Torrent) newMetaInfo() (mi *metainfo.MetaInfo) {
        return
 }
 
+func (t *Torrent) BytesMissing() int64 {
+       t.mu().RLock()
+       defer t.mu().RUnlock()
+       return t.bytesLeft()
+}
+
 func (t *Torrent) bytesLeft() (left int64) {
        for i := 0; i < t.numPieces(); i++ {
                left += int64(t.pieces[i].bytesLeft())
@@ -1366,3 +1372,7 @@ func (t *Torrent) SetMaxEstablishedConns(max int) (oldMax int) {
        t.openNewConns()
        return oldMax
 }
+
+func (t *Torrent) mu() missinggo.RWLocker {
+       return &t.cl.mu
+}