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 var ss []string
slices.MakeInto(&ss, mi.Nodes) slices.MakeInto(&ss, mi.Nodes)
cl.AddDHTNodes(ss) cl.AddDHTNodes(ss)
for _, url := range mi.UrlList { //for _, url := range mi.UrlList {
T.addWebSeed(url) //T.addWebSeed(url)
} //}
return 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) { if !callback(i, e1) {
return return
} }
needle.Start -= e1.Length needle.Start = 0
needle.Length -= e1.Length needle.Length -= e1.Length
} }
} else { } else {

View File

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

View File

@ -2,10 +2,13 @@ package storage
import ( import (
"io" "io"
"log"
"os" "os"
"path/filepath" "path/filepath"
"github.com/anacrolix/missinggo" "github.com/anacrolix/missinggo"
"github.com/anacrolix/torrent/common"
"github.com/anacrolix/torrent/segments"
"github.com/anacrolix/torrent/metainfo" "github.com/anacrolix/torrent/metainfo"
) )
@ -67,9 +70,12 @@ func (fs *fileClientImpl) OpenTorrent(info *metainfo.Info, infoHash metainfo.Has
if err != nil { if err != nil {
return nil, err return nil, err
} }
upvertedFiles := info.UpvertedFiles()
return &fileTorrentImpl{ return &fileTorrentImpl{
dir, dir,
info, info.Name,
upvertedFiles,
segments.NewIndex(common.LengthIterFromUpvertedFiles(upvertedFiles)),
infoHash, infoHash,
fs.pc, fs.pc,
}, nil }, nil
@ -77,7 +83,9 @@ func (fs *fileClientImpl) OpenTorrent(info *metainfo.Info, infoHash metainfo.Has
type fileTorrentImpl struct { type fileTorrentImpl struct {
dir string dir string
info *metainfo.Info infoName string
upvertedFiles []metainfo.FileInfo
segmentLocater segments.Index
infoHash metainfo.Hash infoHash metainfo.Hash
completion PieceCompletion 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. // 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) { func (fst fileTorrentImplIO) ReadAt(b []byte, off int64) (n int, err error) {
for _, fi := range fst.fts.info.UpvertedFiles() { fst.fts.segmentLocater.Locate(segments.Extent{off, int64(len(b))}, func(i int, e segments.Extent) bool {
for off < fi.Length { n1, err1 := fst.readFileAt(fst.fts.upvertedFiles[i], b[:e.Length], e.Start)
n1, err1 := fst.readFileAt(fi, b, off)
n += n1 n += n1
off += int64(n1)
b = b[n1:] b = b[n1:]
if len(b) == 0 {
// Got what we need.
return
}
if n1 != 0 {
// Made progress.
continue
}
err = err1 err = err1
return return err == nil // && int64(n1) == e.Length
} })
off -= fi.Length if len(b) != 0 && err == nil {
}
err = io.EOF err = io.EOF
}
return return
} }
func (fst fileTorrentImplIO) WriteAt(p []byte, off int64) (n int, err error) { func (fst fileTorrentImplIO) WriteAt(p []byte, off int64) (n int, err error) {
for _, fi := range fst.fts.info.UpvertedFiles() { log.Printf("write at %v: %v bytes", off, len(p))
if off >= fi.Length { fst.fts.segmentLocater.Locate(segments.Extent{off, int64(len(p))}, func(i int, e segments.Extent) bool {
off -= fi.Length name := fst.fts.fileInfoName(fst.fts.upvertedFiles[i])
continue
}
n1 := len(p)
if int64(n1) > fi.Length-off {
n1 = int(fi.Length - off)
}
name := fst.fts.fileInfoName(fi)
os.MkdirAll(filepath.Dir(name), 0777) os.MkdirAll(filepath.Dir(name), 0777)
var f *os.File var f *os.File
f, err = os.OpenFile(name, os.O_WRONLY|os.O_CREATE, 0666) f, err = os.OpenFile(name, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil { if err != nil {
return return false
}
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
} }
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 n += n1
off = 0
p = p[n1:] p = p[n1:]
if len(p) == 0 { if err == nil {
break err = closeErr
}
} }
//if err == nil && int64(n1) != e.Length {
// err = io.ErrShortWrite
//}
return err == nil
})
return return
} }
func (fts *fileTorrentImpl) fileInfoName(fi metainfo.FileInfo) string { 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...)...)
} }