From 69a0f2f1e470be3da3fa6160a397db141247f333 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Mon, 1 Jun 2020 00:14:51 +1000 Subject: [PATCH] Got file storage working with segment index --- client.go | 6 +-- common/upverted_files.go | 18 +++++++++ segments/segments.go | 2 +- segments/segments_test.go | 20 ++++++++++ storage/file.go | 84 ++++++++++++++++++--------------------- 5 files changed, 80 insertions(+), 50 deletions(-) create mode 100644 common/upverted_files.go diff --git a/client.go b/client.go index 9861f7ef..a607b912 100644 --- a/client.go +++ b/client.go @@ -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 } diff --git a/common/upverted_files.go b/common/upverted_files.go new file mode 100644 index 00000000..1933e16a --- /dev/null +++ b/common/upverted_files.go @@ -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 + } +} diff --git a/segments/segments.go b/segments/segments.go index 97b611da..4b3f5e8b 100644 --- a/segments/segments.go +++ b/segments/segments.go @@ -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 { diff --git a/segments/segments_test.go b/segments/segments_test.go index 836fdbe0..8dcff6cc 100644 --- a/segments/segments_test.go +++ b/segments/segments_test.go @@ -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) { diff --git a/storage/file.go b/storage/file.go index 013351d7..d0c0dfab 100644 --- a/storage/file.go +++ b/storage/file.go @@ -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...)...) } -- 2.48.1