}
}
-// 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) {
// 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")
}
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
}
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)
+}