From a451bc7e6d9cc102c9926392f4ae6b2c40fce5e2 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Wed, 18 Mar 2015 18:35:22 +1100 Subject: [PATCH] Handle data going missing --- client.go | 16 ++++++++++++++-- data/blob/store.go | 4 ++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/client.go b/client.go index 7ff99428..d506f5f1 100644 --- a/client.go +++ b/client.go @@ -280,8 +280,20 @@ func (cl *Client) torrentReadAt(t *torrent, off int64, p []byte) (n int, err err if len(p) == 0 { panic(len(p)) } - cl.prepareRead(t, off) - return dataReadAt(t.data, p, off) + // TODO: ReadAt should always try to fill the buffer. + for { + avail := cl.prepareRead(t, off) + if avail < int64(len(p)) { + p = p[:avail] + } + n, err = dataReadAt(t.data, p, off) + if n != 0 || err != io.ErrUnexpectedEOF { + break + } + // If we reach here, the data we thought was ready, isn't. So we + // prepare it again, and retry. + } + return } // Sets priorities to download from the given offset. Returns when the piece diff --git a/data/blob/store.go b/data/blob/store.go index c69886e7..6bb411e4 100644 --- a/data/blob/store.go +++ b/data/blob/store.go @@ -124,6 +124,10 @@ func (me *store) pieceRead(p metainfo.Piece) (f *os.File) { if !os.IsNotExist(err) { panic(err) } + // Ermahgerd, self heal. This occurs when the underlying data goes + // missing, likely due to a "cache flush", also known as deleting the + // files. TODO: Trigger an asynchronous initCompleted. + delete(me.completed, sliceToPieceHashArray(p.Hash())) f, err = os.Open(me.path(p, false)) if err == nil { return