2015-02-27 01:46:02 +11:00
|
|
|
package blob
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/hex"
|
|
|
|
"io"
|
2015-03-07 17:11:45 +11:00
|
|
|
|
2015-02-27 01:46:02 +11:00
|
|
|
"github.com/anacrolix/libtorgo/metainfo"
|
|
|
|
)
|
|
|
|
|
|
|
|
type data struct {
|
2015-03-11 02:41:21 +11:00
|
|
|
info *metainfo.Info
|
|
|
|
store *store
|
2015-02-27 01:46:02 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
func (me *data) pieceHashHex(i int) string {
|
|
|
|
return hex.EncodeToString(me.info.Pieces[i*20 : (i+1)*20])
|
|
|
|
}
|
|
|
|
|
|
|
|
func (me *data) Close() {}
|
|
|
|
|
2015-03-11 02:41:21 +11:00
|
|
|
func (me *data) ReadAt(b []byte, off int64) (n int, err error) {
|
|
|
|
p := me.info.Piece(int(off / me.info.PieceLength))
|
|
|
|
f := me.store.pieceRead(p)
|
|
|
|
if f == nil {
|
|
|
|
err = io.ErrUnexpectedEOF
|
2015-02-27 01:46:02 +11:00
|
|
|
return
|
|
|
|
}
|
|
|
|
defer f.Close()
|
2015-03-11 02:41:21 +11:00
|
|
|
n, err = f.ReadAt(b, off%me.info.PieceLength)
|
|
|
|
if err == io.EOF {
|
|
|
|
err = io.ErrUnexpectedEOF
|
|
|
|
}
|
|
|
|
return
|
2015-02-27 01:46:02 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
func (me *data) WriteAt(p []byte, off int64) (n int, err error) {
|
|
|
|
i := int(off / me.info.PieceLength)
|
|
|
|
off %= me.info.PieceLength
|
|
|
|
for len(p) != 0 {
|
2015-03-11 02:41:21 +11:00
|
|
|
f := me.store.pieceWrite(me.info.Piece(i))
|
2015-02-27 01:46:02 +11:00
|
|
|
p1 := p
|
|
|
|
maxN := me.info.Piece(i).Length() - off
|
|
|
|
if int64(len(p1)) > maxN {
|
|
|
|
p1 = p1[:maxN]
|
|
|
|
}
|
|
|
|
var n1 int
|
|
|
|
n1, err = f.WriteAt(p1, off)
|
|
|
|
f.Close()
|
|
|
|
n += n1
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
p = p[n1:]
|
|
|
|
off = 0
|
2015-03-11 02:41:21 +11:00
|
|
|
i++
|
2015-02-27 01:46:02 +11:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (me *data) pieceReader(piece int, off int64) (ret io.ReadCloser, err error) {
|
2015-03-11 02:41:21 +11:00
|
|
|
f := me.store.pieceRead(me.info.Piece(piece))
|
|
|
|
if f == nil {
|
|
|
|
err = io.ErrUnexpectedEOF
|
2015-02-27 01:46:02 +11:00
|
|
|
return
|
|
|
|
}
|
|
|
|
return struct {
|
|
|
|
io.Reader
|
|
|
|
io.Closer
|
2015-03-11 02:41:21 +11:00
|
|
|
}{
|
|
|
|
Reader: io.NewSectionReader(f, off, me.info.Piece(piece).Length()-off),
|
|
|
|
Closer: f,
|
|
|
|
}, nil
|
2015-02-27 01:46:02 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
func (me *data) WriteSectionTo(w io.Writer, off, n int64) (written int64, err error) {
|
|
|
|
i := int(off / me.info.PieceLength)
|
|
|
|
off %= me.info.PieceLength
|
|
|
|
for n != 0 {
|
|
|
|
var pr io.ReadCloser
|
|
|
|
pr, err = me.pieceReader(i, off)
|
|
|
|
if err != nil {
|
|
|
|
if err == io.EOF {
|
|
|
|
err = nil
|
|
|
|
}
|
|
|
|
return
|
2015-03-11 02:41:21 +11:00
|
|
|
pr.Close()
|
2015-02-27 01:46:02 +11:00
|
|
|
}
|
|
|
|
var n1 int64
|
|
|
|
n1, err = io.CopyN(w, pr, n)
|
2015-03-11 02:41:21 +11:00
|
|
|
pr.Close()
|
2015-02-27 01:46:02 +11:00
|
|
|
written += n1
|
|
|
|
n -= n1
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
off = 0
|
2015-03-11 02:41:21 +11:00
|
|
|
i++
|
2015-02-27 01:46:02 +11:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2015-02-27 12:45:55 +11:00
|
|
|
|
|
|
|
func (me *data) PieceCompleted(index int) (err error) {
|
2015-03-11 02:41:21 +11:00
|
|
|
return me.store.PieceCompleted(me.info.Piece(index))
|
2015-02-27 12:45:55 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
func (me *data) PieceComplete(piece int) bool {
|
2015-03-11 02:41:21 +11:00
|
|
|
return me.store.pieceComplete(me.info.Piece(piece))
|
2015-02-27 12:45:55 +11:00
|
|
|
}
|