client.go | 6 +----- cmd/torrent-verify/main.go | 19 +++++++++---------- mmap_span.go | 18 ++++++++++++++++++ diff --git a/client.go b/client.go index 7247321b248554f8291bc9eb0aa36855547d6c41..1eb15b9d8e0971a476403013034be39aeadc131d 100644 --- a/client.go +++ b/client.go @@ -229,13 +229,9 @@ } return } -func (t *Torrent) PieceReader(piece int) io.Reader { - return io.NewSectionReader(t.Data, int64(piece)*t.MetaInfo.PieceLength, t.MetaInfo.PieceLength) -} - func (t *Torrent) HashPiece(piece int) (ps pieceSum) { hash := PieceHash.New() - n, err := io.Copy(hash, t.PieceReader(piece)) + n, err := t.Data.WriteSectionTo(hash, int64(piece)*t.MetaInfo.PieceLength, int64(piece)*t.MetaInfo.PieceLength) if err != nil { panic(err) } diff --git a/cmd/torrent-verify/main.go b/cmd/torrent-verify/main.go index 7259f0e244ab088e3d5f92050d5b05a856b0e2b2..993dfedbb6e6057e7726c1e12f004242555b113c 100644 --- a/cmd/torrent-verify/main.go +++ b/cmd/torrent-verify/main.go @@ -5,8 +5,9 @@ "bitbucket.org/anacrolix/go.torrent" "bytes" "crypto/sha1" "flag" + "fmt" + "github.com/davecheney/profile" metainfo "github.com/nsf/libtorgo/torrent" - "io" "launchpad.net/gommap" "log" "os" @@ -23,6 +24,7 @@ flag.Parse() } func main() { + defer profile.Start(profile.CPUProfile).Stop() metaInfo, err := metainfo.LoadFromFile(*filePath) if err != nil { log.Fatal(err) @@ -32,7 +34,7 @@ if err != nil { log.Print(err) } defer devZero.Close() - var mmapSpan torrent.MmapSpan + var mMapSpan torrent.MMapSpan for _, file := range metaInfo.Files { filename := filepath.Join(append([]string{*dirPath, metaInfo.Name}, file.Path...)...) osFile, err := os.Open(filename) @@ -52,24 +54,21 @@ if int64(len(goMMap)) != file.Length { log.Printf("file mmap has wrong size: %#v", filename) } osFile.Close() - mmapSpan = append(mmapSpan, torrent.Mmap{goMMap}) + mMapSpan = append(mMapSpan, torrent.MMap{goMMap}) } log.Println(len(metaInfo.Files)) - log.Println(mmapSpan.Size()) + log.Println(mMapSpan.Size()) log.Println(len(metaInfo.Pieces)) - for piece := int64(0); ; piece++ { + for piece := 0; piece < (len(metaInfo.Pieces)+sha1.Size-1)/sha1.Size; piece++ { expectedHash := metaInfo.Pieces[sha1.Size*piece : sha1.Size*(piece+1)] if len(expectedHash) == 0 { break } hash := sha1.New() - n, err := io.Copy(hash, io.NewSectionReader(mmapSpan, piece*metaInfo.PieceLength, metaInfo.PieceLength)) - if n != metaInfo.PieceLength { - panic("oh no") - } + _, err := mMapSpan.WriteSectionTo(hash, int64(piece)*metaInfo.PieceLength, metaInfo.PieceLength) if err != nil { log.Fatal(err) } - log.Println(piece, bytes.Equal(hash.Sum(nil), expectedHash)) + fmt.Println(piece, bytes.Equal(hash.Sum(nil), expectedHash)) } } diff --git a/mmap_span.go b/mmap_span.go index 9d2f39bb31c9c6b1c0d2d42f8020f8dee92ea1dc..fcc5cd4e09368ced715b40d9cd76d604d9799096 100644 --- a/mmap_span.go +++ b/mmap_span.go @@ -48,6 +48,24 @@ } return } +func (me MMapSpan) WriteSectionTo(w io.Writer, off, n int64) (written int64, err error) { + me.span().ApplyTo(off, func(intervalOffset int64, interval sizer) (stop bool) { + var _n int + p := interval.(MMap).MMap[intervalOffset:] + if n < int64(len(p)) { + p = p[:n] + } + _n, err = w.Write(p) + written += int64(_n) + n -= int64(_n) + if err != nil { + return true + } + return n != 0 + }) + return +} + func (me MMapSpan) WriteAt(p []byte, off int64) (n int, err error) { me.span().ApplyTo(off, func(iOff int64, i sizer) (stop bool) { _n := copy(i.(MMap).MMap[iOff:], p)