Extent{6, 2},
2,
[]Extent{})
+ assertLocate(t, newLocater,
+ []Length{1652, 1514, 1554, 1618, 1546, 129241752, 1537}, // 128737588
+ Extent{0, 16384},
+ 0,
+ []Extent{
+ {0, 1652},
+ {0, 1514},
+ {0, 1554},
+ {0, 1618},
+ {0, 1546},
+ {0, 8500}})
+ assertLocate(t, newLocater,
+ []Length{1652, 1514, 1554, 1618, 1546, 129241752, 1537, 1536, 1551}, // 128737588
+ Extent{129236992, 16384},
+ 5,
+ []Extent{
+ {129229108, 12644},
+ {0, 1537},
+ {0, 1536},
+ {0, 667}})
}
func TestScan(t *testing.T) {
import (
"io"
+ "log"
"os"
"path/filepath"
"github.com/anacrolix/missinggo"
+ "github.com/anacrolix/torrent/common"
+ "github.com/anacrolix/torrent/segments"
"github.com/anacrolix/torrent/metainfo"
)
if err != nil {
return nil, err
}
+ upvertedFiles := info.UpvertedFiles()
return &fileTorrentImpl{
dir,
- info,
+ info.Name,
+ upvertedFiles,
+ segments.NewIndex(common.LengthIterFromUpvertedFiles(upvertedFiles)),
infoHash,
fs.pc,
}, nil
}
type fileTorrentImpl struct {
- dir string
- info *metainfo.Info
- infoHash metainfo.Hash
- completion PieceCompletion
+ dir string
+ infoName string
+ upvertedFiles []metainfo.FileInfo
+ segmentLocater segments.Index
+ infoHash metainfo.Hash
+ completion PieceCompletion
}
func (fts *fileTorrentImpl) Piece(p metainfo.Piece) PieceImpl {
// Only returns EOF at the end of the torrent. Premature EOF is ErrUnexpectedEOF.
func (fst fileTorrentImplIO) ReadAt(b []byte, off int64) (n int, err error) {
- for _, fi := range fst.fts.info.UpvertedFiles() {
- for off < fi.Length {
- n1, err1 := fst.readFileAt(fi, b, off)
- n += n1
- off += int64(n1)
- b = b[n1:]
- if len(b) == 0 {
- // Got what we need.
- return
- }
- if n1 != 0 {
- // Made progress.
- continue
- }
- err = err1
- return
- }
- off -= fi.Length
+ fst.fts.segmentLocater.Locate(segments.Extent{off, int64(len(b))}, func(i int, e segments.Extent) bool {
+ n1, err1 := fst.readFileAt(fst.fts.upvertedFiles[i], b[:e.Length], e.Start)
+ n += n1
+ b = b[n1:]
+ err = err1
+ return err == nil // && int64(n1) == e.Length
+ })
+ if len(b) != 0 && err == nil {
+ err = io.EOF
}
- err = io.EOF
return
}
func (fst fileTorrentImplIO) WriteAt(p []byte, off int64) (n int, err error) {
- for _, fi := range fst.fts.info.UpvertedFiles() {
- if off >= fi.Length {
- off -= fi.Length
- continue
- }
- n1 := len(p)
- if int64(n1) > fi.Length-off {
- n1 = int(fi.Length - off)
- }
- name := fst.fts.fileInfoName(fi)
+ log.Printf("write at %v: %v bytes", off, len(p))
+ fst.fts.segmentLocater.Locate(segments.Extent{off, int64(len(p))}, func(i int, e segments.Extent) bool {
+ name := fst.fts.fileInfoName(fst.fts.upvertedFiles[i])
os.MkdirAll(filepath.Dir(name), 0777)
var f *os.File
f, err = os.OpenFile(name, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
- return
- }
- n1, err = f.WriteAt(p[:n1], off)
- // TODO: On some systems, write errors can be delayed until the Close.
- f.Close()
- if err != nil {
- return
+ return false
}
+ var n1 int
+ n1, err = f.WriteAt(p[:e.Length], e.Start)
+ log.Printf("%v %v wrote %v: %v", i, e, n1, err)
+ closeErr := f.Close()
n += n1
- off = 0
p = p[n1:]
- if len(p) == 0 {
- break
+ if err == nil {
+ err = closeErr
}
- }
+ //if err == nil && int64(n1) != e.Length {
+ // err = io.ErrShortWrite
+ //}
+ return err == nil
+ })
return
}
func (fts *fileTorrentImpl) fileInfoName(fi metainfo.FileInfo) string {
- return filepath.Join(append([]string{fts.dir, fts.info.Name}, fi.Path...)...)
+ return filepath.Join(append([]string{fts.dir, fts.infoName}, fi.Path...)...)
}