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
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
if !callback(i, e1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
needle.Start -= e1.Length
|
needle.Start = 0
|
||||||
needle.Length -= e1.Length
|
needle.Length -= e1.Length
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,19 +70,24 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
type fileTorrentImpl struct {
|
type fileTorrentImpl struct {
|
||||||
dir string
|
dir string
|
||||||
info *metainfo.Info
|
infoName string
|
||||||
infoHash metainfo.Hash
|
upvertedFiles []metainfo.FileInfo
|
||||||
completion PieceCompletion
|
segmentLocater segments.Index
|
||||||
|
infoHash metainfo.Hash
|
||||||
|
completion PieceCompletion
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fts *fileTorrentImpl) Piece(p metainfo.Piece) PieceImpl {
|
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.
|
// 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
|
b = b[n1:]
|
||||||
off += int64(n1)
|
err = err1
|
||||||
b = b[n1:]
|
return err == nil // && int64(n1) == e.Length
|
||||||
if len(b) == 0 {
|
})
|
||||||
// Got what we need.
|
if len(b) != 0 && err == nil {
|
||||||
return
|
err = io.EOF
|
||||||
}
|
|
||||||
if n1 != 0 {
|
|
||||||
// Made progress.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
err = err1
|
|
||||||
return
|
|
||||||
}
|
|
||||||
off -= fi.Length
|
|
||||||
}
|
}
|
||||||
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...)...)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue