client.go | 6 +++--- common/upverted_files.go | 18 ++++++++++++++++++ segments/segments.go | 2 +- segments/segments_test.go | 20 ++++++++++++++++++++ storage/file.go | 84 ++++++++++++++++++++++++----------------------------- diff --git a/client.go b/client.go index 9861f7ef3ee052c9aa3e664ed6fe933a8b25f840..a607b912477232d54b9c15c024b7f628af7f279d 100644 --- a/client.go +++ b/client.go @@ -1233,9 +1233,9 @@ T, _, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi)) 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 0000000000000000000000000000000000000000..1933e16a13bdaff14c620a65f5838a542de3fdfc --- /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 97b611da02858f4e9692708ba61db2592691d829..4b3f5e8b67c4fb26bbb939df60fadb182488be89 100644 --- a/segments/segments.go +++ b/segments/segments.go @@ -43,7 +43,7 @@ if e1.Length >= 0 { 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 836fdbe0be916e7fec6f68206188d6a0c2a26ac0..8dcff6cc8a86faa162578f396d891d22a438fecb 100644 --- a/segments/segments_test.go +++ b/segments/segments_test.go @@ -57,6 +57,26 @@ []Length{1, 0, 2, 0, 3}, 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 013351d77f9be42066cdd1ad7728ad5cf50543bf..d0c0dfab38abde019247576cf7ae0122eceac54b 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 @@ err := CreateNativeZeroLengthFiles(info, dir) 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 @@ } // 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...)...) }