Set priorities ahead of the current read position

This commit is contained in:
Matt Joiner 2014-12-05 00:56:28 -06:00
parent ac1afa19b8
commit b6ae4caa6a
4 changed files with 58 additions and 17 deletions

View File

@ -264,22 +264,36 @@ func (cl *Client) torrentReadAt(t *torrent, off int64, p []byte) (n int, err err
err = io.EOF
return
}
cl.readRaisePiecePriorities(t, off, int64(len(p)))
if len(p) > pieceLeft {
p = p[:pieceLeft]
}
if len(p) == 0 {
panic(len(p))
}
cl.prioritizePiece(t, index, piecePriorityHigh)
for i := index + 1; i < index+7 && i < t.NumPieces(); i++ {
cl.prioritizePiece(t, i, piecePriorityNormal)
}
for !piece.Complete() {
piece.Event.Wait()
}
return t.Data.ReadAt(p, off)
}
func (cl *Client) readRaisePiecePriorities(t *torrent, off, _len int64) {
index := int(off / int64(t.UsualPieceSize()))
cl.raisePiecePriority(t, index, piecePriorityNow)
index++
if index >= t.NumPieces() {
return
}
cl.raisePiecePriority(t, index, piecePriorityNext)
for i := 0; i < 5; i++ {
index++
if index >= t.NumPieces() {
break
}
cl.raisePiecePriority(t, index, piecePriorityReadahead)
}
}
func (cl *Client) configDir() string {
return filepath.Join(os.Getenv("HOME"), ".config/torrent")
}
@ -292,6 +306,12 @@ func (t *torrent) connPendPiece(c *connection, piece int) {
c.pendPiece(piece, t.Pieces[piece].Priority)
}
func (cl *Client) raisePiecePriority(t *torrent, piece int, priority piecePriority) {
if t.Pieces[piece].Priority < priority {
cl.prioritizePiece(t, piece, priority)
}
}
func (cl *Client) prioritizePiece(t *torrent, piece int, priority piecePriority) {
if t.havePiece(piece) {
return
@ -1595,8 +1615,10 @@ func (t Torrent) DownloadAll() {
// TODO: Leave higher priorities as they were?
t.cl.prioritizePiece(t.torrent, i, piecePriorityNormal)
}
t.cl.prioritizePiece(t.torrent, 0, piecePriorityHigh)
t.cl.prioritizePiece(t.torrent, t.NumPieces()-1, piecePriorityHigh)
// Nice to have the first and last pieces soon for various interactive
// purposes.
t.cl.prioritizePiece(t.torrent, 0, piecePriorityReadahead)
t.cl.prioritizePiece(t.torrent, t.NumPieces()-1, piecePriorityReadahead)
t.cl.mu.Unlock()
}

View File

@ -8,7 +8,6 @@ import (
"expvar"
"fmt"
"io"
"log"
"net"
"sync"
"time"
@ -94,11 +93,15 @@ func (cn *connection) pendPiece(piece int, priority piecePriority) {
return
}
key := cn.piecePriorities[piece]
if priority == piecePriorityHigh {
key = -key
}
if piece == 0 {
log.Print(key)
// TODO: Have some kind of overlap here, so there's some probabilistic
// favouring of higher priority pieces.
switch priority {
case piecePriorityReadahead:
key -= len(cn.piecePriorities)
case piecePriorityNext:
key -= 2 * len(cn.piecePriorities)
case piecePriorityNow:
key -= 3 * len(cn.piecePriorities)
}
cn.pieceRequestOrder.SetPiece(piece, key)
}

View File

@ -43,7 +43,9 @@ type piecePriority byte
const (
piecePriorityNone piecePriority = iota
piecePriorityNormal
piecePriorityHigh
piecePriorityReadahead
piecePriorityNext
piecePriorityNow
)
type piece struct {

View File

@ -281,12 +281,26 @@ func (t *torrent) pieceStatusChar(index int) byte {
return 'H'
case !p.EverHashed:
return '?'
case p.Priority == piecePriorityHigh:
return '!'
case t.PiecePartiallyDownloaded(index):
return 'P'
switch p.Priority {
case piecePriorityNone:
return 'F' // Forgotten
default:
return 'P'
}
default:
return '.'
switch p.Priority {
case piecePriorityNone:
return 'z'
case piecePriorityNow:
return '!'
case piecePriorityReadahead:
return 'R'
case piecePriorityNext:
return 'N'
default:
return '.'
}
}
}