client.go | 15 +-------------- reader.go | 4 +--- torrent.go | 11 +++++++++++ diff --git a/client.go b/client.go index 9b3c870bca6636d2ff6c7f15aa7ce29eacae2d7a..612152ef622cdaa06dd96edb1c19799a510f2aae 100644 --- a/client.go +++ b/client.go @@ -253,17 +253,6 @@ fmt.Fprintln(w) } } -// TODO: Make this non-blocking Read on Torrent. -func dataReadAt(d Data, b []byte, off int64) (n int, err error) { - // defer func() { - // if err == io.ErrUnexpectedEOF && n != 0 { - // err = nil - // } - // }() - // log.Println("data read at", len(b), off) - return d.ReadAt(b, off) -} - // Calculates the number of pieces to set to Readahead priority, after the // Now, and Next pieces. func readaheadPieces(readahead, pieceLength int64) (ret int) { @@ -1357,10 +1346,8 @@ func (me *Client) sendChunk(t *torrent, c *connection, r request) error { // Count the chunk being sent, even if it isn't. c.chunksSent++ b := make([]byte, r.Length) - tp := &t.Pieces[r.Index] - tp.waitNoPendingWrites() p := t.Info.Piece(int(r.Index)) - n, err := dataReadAt(t.data, b, p.Offset()+int64(r.Begin)) + n, err := t.readAt(b, p.Offset()+int64(r.Begin)) if n != len(b) { if err == nil { panic("expected error") diff --git a/reader.go b/reader.go index 571ce4f2de620f56fe28ae0fdeb0b444af9b869e..12caf4cad06d16c37dcfa1079edd66d4f8ade975 100644 --- a/reader.go +++ b/reader.go @@ -125,14 +125,12 @@ } } b1 := b[:avail] pi := int(pos / r.t.Info().PieceLength) - tp := &r.t.torrent.Pieces[pi] ip := r.t.Info().Piece(pi) po := pos % ip.Length() if int64(len(b1)) > ip.Length()-po { b1 = b1[:ip.Length()-po] } - tp.waitNoPendingWrites() - n, err = dataReadAt(r.t.torrent.data, b1, pos) + n, err = r.t.torrent.readAt(b1, pos) if n != 0 { return } diff --git a/torrent.go b/torrent.go index 0fffe67ff2e555d5df091389f87bd909a343dfa6..daca65c0a3871fe2fc4a3e1146150a2c6e8a86dc 100644 --- a/torrent.go +++ b/torrent.go @@ -1039,3 +1039,14 @@ func (t *torrent) updatePieceCompletion(piece int) { t.completedPieces.Set(piece, t.pieceCompleteUncached(piece)) } + +// Non-blocking read. Client lock is not required. +func (t *torrent) readAt(b []byte, off int64) (n int, err error) { + if off+int64(len(b)) > t.length { + b = b[:t.length-off] + } + for pi := off / t.Info.PieceLength; pi*t.Info.PieceLength < off+int64(len(b)); pi++ { + t.Pieces[pi].waitNoPendingWrites() + } + return t.data.ReadAt(b, off) +}