Return errors from Reader if data downloading won't occur
Chunk write errors to storage can disable data download. Previously Readers would wait indefinitely for the data to become available. This change returns an error instead of stalling.
This commit is contained in:
parent
2a7352aad2
commit
43891309ad
|
@ -199,6 +199,10 @@ func (r *reader) waitAvailable(pos, wanted int64, ctxErr *error, wait bool) (ava
|
||||||
err = *ctxErr
|
err = *ctxErr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if r.t.dataDownloadDisallowed || !r.t.networkingEnabled {
|
||||||
|
err = errors.New("downloading disabled and data not already available")
|
||||||
|
return
|
||||||
|
}
|
||||||
if !wait {
|
if !wait {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -73,7 +75,27 @@ func testReceiveChunkStorageFailure(t *testing.T, seederFast bool) {
|
||||||
// Tell the seeder to find the leecher. Is it guaranteed seeders will always try to do this?
|
// Tell the seeder to find the leecher. Is it guaranteed seeders will always try to do this?
|
||||||
seederTorrent.AddClientPeer(leecherClient)
|
seederTorrent.AddClientPeer(leecherClient)
|
||||||
<-leecherTorrent.GotInfo()
|
<-leecherTorrent.GotInfo()
|
||||||
assertReadAllGreeting(t, leecherTorrent.NewReader())
|
r := leecherTorrent.Files()[0].NewReader()
|
||||||
|
defer r.Close()
|
||||||
|
// We can't use assertReadAllGreeting here, because the default storage write error handler
|
||||||
|
// disables data downloads, which now causes Readers to error when they're blocked.
|
||||||
|
if false {
|
||||||
|
assertReadAllGreeting(t, leecherTorrent.NewReader())
|
||||||
|
} else {
|
||||||
|
for func() bool {
|
||||||
|
// We don't seem to need to seek, but that's probably just because the storage failure is
|
||||||
|
// happening on the first read.
|
||||||
|
r.Seek(0, io.SeekStart)
|
||||||
|
output, err := ioutil.ReadAll(r)
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("got error while reading: %v", err)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
assert.EqualValues(t, testutil.GreetingFileContents, output)
|
||||||
|
return false
|
||||||
|
}() {
|
||||||
|
}
|
||||||
|
}
|
||||||
// TODO: Check that PeerConns fastEnabled matches seederFast?
|
// TODO: Check that PeerConns fastEnabled matches seederFast?
|
||||||
//select {}
|
//select {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2024,6 +2024,7 @@ func (t *Torrent) onWriteChunkErr(err error) {
|
||||||
go t.userOnWriteChunkErr(err)
|
go t.userOnWriteChunkErr(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
t.logger.WithDefaultLevel(log.Critical).Printf("default chunk write error handler: disabling data download")
|
||||||
t.disallowDataDownloadLocked()
|
t.disallowDataDownloadLocked()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2038,12 +2039,14 @@ func (t *Torrent) disallowDataDownloadLocked() {
|
||||||
t.iterPeers(func(c *peer) {
|
t.iterPeers(func(c *peer) {
|
||||||
c.updateRequests()
|
c.updateRequests()
|
||||||
})
|
})
|
||||||
|
t.tickleReaders()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Torrent) AllowDataDownload() {
|
func (t *Torrent) AllowDataDownload() {
|
||||||
t.cl.lock()
|
t.cl.lock()
|
||||||
defer t.cl.unlock()
|
defer t.cl.unlock()
|
||||||
t.dataDownloadDisallowed = false
|
t.dataDownloadDisallowed = false
|
||||||
|
t.tickleReaders()
|
||||||
t.iterPeers(func(c *peer) {
|
t.iterPeers(func(c *peer) {
|
||||||
c.updateRequests()
|
c.updateRequests()
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue