Got file storage working with segment index

This commit is contained in:
Matt Joiner 2020-06-01 00:14:51 +10:00
parent 3cbdf4aa98
commit 69a0f2f1e4
5 changed files with 80 additions and 50 deletions

View File

@ -1233,9 +1233,9 @@ func (cl *Client) AddTorrent(mi *metainfo.MetaInfo) (T *Torrent, err error) {
var ss []string
slices.MakeInto(&ss, mi.Nodes)
cl.AddDHTNodes(ss)
for _, url := range mi.UrlList {
T.addWebSeed(url)
}
//for _, url := range mi.UrlList {
//T.addWebSeed(url)
//}
return
}

18
common/upverted_files.go Normal file
View File

@ -0,0 +1,18 @@
package common
import (
"github.com/anacrolix/torrent/metainfo"
"github.com/anacrolix/torrent/segments"
)
func LengthIterFromUpvertedFiles(fis []metainfo.FileInfo) segments.LengthIter {
i := 0
return func() (segments.Length, bool) {
if i == len(fis) {
return -1, false
}
l := fis[i].Length
i++
return l, true
}
}

View File

@ -43,7 +43,7 @@ func Scan(haystack func() (Length, bool), needle Extent, callback Callback) {
if !callback(i, e1) {
return
}
needle.Start -= e1.Length
needle.Start = 0
needle.Length -= e1.Length
}
} else {

View File

@ -57,6 +57,26 @@ func testLocater(t *testing.T, newLocater newLocater) {
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) {

View File

@ -2,10 +2,13 @@ package storage
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"
)
@ -67,9 +70,12 @@ func (fs *fileClientImpl) OpenTorrent(info *metainfo.Info, infoHash metainfo.Has
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
@ -77,7 +83,9 @@ func (fs *fileClientImpl) OpenTorrent(info *metainfo.Info, infoHash metainfo.Has
type fileTorrentImpl struct {
dir string
info *metainfo.Info
infoName string
upvertedFiles []metainfo.FileInfo
segmentLocater segments.Index
infoHash metainfo.Hash
completion PieceCompletion
}
@ -154,62 +162,46 @@ func (fst *fileTorrentImplIO) readFileAt(fi metainfo.FileInfo, b []byte, off int
// 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)
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
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
}
return err == nil // && int64(n1) == e.Length
})
if len(b) != 0 && err == nil {
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...)...)
}