Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recommended way to know when a torrent is completely downloaded #168

Closed
oliverpool opened this issue Jul 13, 2017 · 7 comments
Closed

Recommended way to know when a torrent is completely downloaded #168

oliverpool opened this issue Jul 13, 2017 · 7 comments

Comments

@oliverpool
Copy link

oliverpool commented Jul 13, 2017

Hi,

the first example of the documentation waits for all downloads to be completed:

c, _ := torrent.NewClient(nil)
defer c.Close()
t, _ := c.AddMagnet("magnet:?xt=urn:btih:ZOCMZQIPFFW7OLLMIC5HUB6BPCSDEOQU")
<-t.GotInfo()
t.DownloadAll()
c.WaitAll()
log.Print("ermahgerd, torrent downloaded")

I would like to be notified when a specific torrent is downloaded.

Should I do an busy-wait loop with t.BytesCompleted() == t.Info().TotalLength()? (like https://github.com/anacrolix/torrent/blob/master/cmd/torrent/main.go#L50) with some time.Sleep in between

When BytesCompleted is the right value, does it also mean that the content was successfully written to the disk ? (or might there be some delay?)

Ideally, I would like a Completed method (which would return a channel) like the Closed.

Thank you!

@oliverpool oliverpool changed the title Recommended way to know when download is completed Recommended way to know when a torrent is completely downloaded Jul 13, 2017
@anacrolix
Copy link
Owner

Hi, some good ideas. I'll try to give a full response in a day or two.

@christian-roggia
Copy link

+1

@anacrolix
Copy link
Owner

You could subscribe to Torrent.PieceStateChanges, every time you get an event, check for the state you want.

pcs := t.SubscribePieceStateChanges()
for t.BytesCompleted() != t.Info().TotalLength() {
    t.DownloadAll()
    <-pcs.Values
}

Depending on how you intend to use the data, the more typical way to do this with this library is make use of the Reader. Something like this, with error checking not included:

t.DownloadAll() // Just to inform the client to get everything, even during pauses in use of Reader.
r := t.NewReader()
defer r.Close()
for _, f := range t.Files() {
    outputPath := filepath.Join(outputDir, filepath.FromSlash(f.DisplayPath()))
    os.MkdirAll(filepath.Dir(outputPath))
    g, _ := os.Open(outputPath, os.O_CREATE|os.O_WRONLY)
    io.Copy(g, missinggo.NewSectionReadSeeker(r, f.Offset(), f.Length()))
    g.Close()
}

@anacrolix
Copy link
Owner

Has this worked for you guys?

@christian-roggia
Copy link

I think that a Completed method that returns a channel would be ideally the best solution, as pointed out by the author of this PR, but the workaround you provided works as well.

@anacrolix
Copy link
Owner

After reading #243 , I think a method for this is a good idea. In particular, a context.Context can be given to allow "giving up", and the method can return an error if for some reason the entire torrent, or the file waited on, is not correctly prioritized, to prevent indefinite stalling due to incorrect priorities. Testing this will also be much easier as a result.

@anacrolix
Copy link
Owner

There's nothing in the works to address this in the manner you request. I think it might detract from the flexibility of the package to encourage it. Feel free to discuss more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants