115 lines
2.3 KiB
Go
115 lines
2.3 KiB
Go
package pieceStore
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"io"
|
|
|
|
"github.com/anacrolix/torrent/metainfo"
|
|
)
|
|
|
|
type data struct {
|
|
info *metainfo.Info
|
|
store *store
|
|
}
|
|
|
|
func (me *data) pieceHashHex(i int) string {
|
|
return hex.EncodeToString(me.info.Pieces[i*20 : (i+1)*20])
|
|
}
|
|
|
|
func (me *data) Close() {}
|
|
|
|
// TODO: Make sure that reading completed can't read from incomplete. Then
|
|
// also it'll be possible to verify that the Content-Range on completed
|
|
// returns the correct piece length so there aren't short reads.
|
|
|
|
func (me *data) ReadAt(b []byte, off int64) (n int, err error) {
|
|
for len(b) != 0 {
|
|
if off >= me.info.TotalLength() {
|
|
err = io.EOF
|
|
break
|
|
}
|
|
p := me.info.Piece(int(off / me.info.PieceLength))
|
|
b1 := b
|
|
maxN1 := int(p.Length() - off%me.info.PieceLength)
|
|
if len(b1) > maxN1 {
|
|
b1 = b1[:maxN1]
|
|
}
|
|
var n1 int
|
|
n1, err = me.store.pieceReadAt(p, b1, off%me.info.PieceLength)
|
|
n += n1
|
|
off += int64(n1)
|
|
b = b[n1:]
|
|
if err != nil {
|
|
break
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// TODO: Rewrite this later, on short writes to a piece it will start to play up.
|
|
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 {
|
|
p1 := p
|
|
maxN := me.info.Piece(i).Length() - off
|
|
if int64(len(p1)) > maxN {
|
|
p1 = p1[:maxN]
|
|
}
|
|
var n1 int
|
|
n1, err = me.store.pieceWriteAt(me.info.Piece(i), p1, off)
|
|
n += n1
|
|
if err != nil {
|
|
return
|
|
}
|
|
p = p[n1:]
|
|
off = 0
|
|
i++
|
|
}
|
|
return
|
|
}
|
|
|
|
func (me *data) pieceReader(p metainfo.Piece, off int64) (ret io.ReadCloser, err error) {
|
|
return me.store.getPieceRange(p, off, p.Length()-off)
|
|
}
|
|
|
|
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 {
|
|
if i >= me.info.NumPieces() {
|
|
err = io.EOF
|
|
break
|
|
}
|
|
p := me.info.Piece(i)
|
|
if off >= p.Length() {
|
|
err = io.EOF
|
|
break
|
|
}
|
|
var pr io.ReadCloser
|
|
pr, err = me.pieceReader(p, off)
|
|
if err != nil {
|
|
return
|
|
}
|
|
var n1 int64
|
|
n1, err = io.CopyN(w, pr, n)
|
|
pr.Close()
|
|
written += n1
|
|
n -= n1
|
|
if err != nil {
|
|
return
|
|
}
|
|
off = 0
|
|
i++
|
|
}
|
|
return
|
|
}
|
|
|
|
func (me *data) PieceCompleted(index int) (err error) {
|
|
return me.store.PieceCompleted(me.info.Piece(index))
|
|
}
|
|
|
|
func (me *data) PieceComplete(piece int) bool {
|
|
return me.store.pieceComplete(me.info.Piece(piece))
|
|
}
|