From d97b487229734071b89604b068830e0d41274a72 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Wed, 25 Mar 2015 17:32:42 +1100 Subject: [PATCH] cmd/torrent: Report progress Fixes #6 --- client.go | 8 ++++++ cmd/torrent/main.go | 60 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/client.go b/client.go index 9587a948..50fe4691 100644 --- a/client.go +++ b/client.go @@ -1998,6 +1998,14 @@ type Torrent struct { *torrent } +// Don't call this before the info is available. +func (t *torrent) BytesCompleted() int64 { + if !t.haveInfo() { + return 0 + } + return t.Info.TotalLength() - t.bytesLeft() +} + func (t Torrent) NumPieces() int { return t.numPieces() } diff --git a/cmd/torrent/main.go b/cmd/torrent/main.go index 6ec09230..0e0295ba 100644 --- a/cmd/torrent/main.go +++ b/cmd/torrent/main.go @@ -8,6 +8,9 @@ import ( _ "net/http/pprof" "os" "strings" + "time" + + "github.com/dustin/go-humanize" "github.com/jessevdk/go-flags" @@ -35,6 +38,38 @@ func resolvedPeerAddrs(ss []string) (ret []torrent.Peer, err error) { return } +func bytesCompleted(tc *torrent.Client) (ret int64) { + for _, t := range tc.Torrents() { + if t.Info != nil { + ret += t.BytesCompleted() + } + } + return +} + +// Returns an estimate of the total bytes for all torrents. +func totalBytesEstimate(tc *torrent.Client) (ret int64) { + var noInfo, hadInfo int64 + for _, t := range tc.Torrents() { + if t.Info == nil { + noInfo++ + continue + } + ret += t.Info.TotalLength() + hadInfo++ + } + if hadInfo != 0 { + // Treat each torrent without info as the average of those with, + // rounded up. + ret += (noInfo*ret + hadInfo - 1) / hadInfo + } + return +} + +func progressLine(tc *torrent.Client) string { + return fmt.Sprintf("\033[K%s / %s\r", humanize.Bytes(uint64(bytesCompleted(tc))), humanize.Bytes(uint64(totalBytesEstimate(tc)))) +} + func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) var rootGroup struct { @@ -98,13 +133,26 @@ func main() { t.DownloadAll() }() } + done := make(chan struct{}) + go func() { + defer close(done) + if client.WaitAll() { + log.Print("downloaded ALL the torrents") + } else { + log.Fatal("y u no complete torrents?!") + } + }() + ticker := time.NewTicker(time.Second) +waitDone: + for { + select { + case <-done: + break waitDone + case <-ticker.C: + os.Stdout.WriteString(progressLine(client)) + } + } if rootGroup.Seed { - // We never finish, since we intend to seed indefinitely. select {} } - if client.WaitAll() { - log.Print("downloaded ALL the torrents") - } else { - log.Fatal("y u no complete torrents?!") - } }