Got file storage working with segment index
This commit is contained in:
parent
3cbdf4aa98
commit
69a0f2f1e4
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,19 +70,24 @@ 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
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -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)
|
||||
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...)...)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue