diff --git a/client.go b/client.go index 3361132a..84a11f59 100644 --- a/client.go +++ b/client.go @@ -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() } diff --git a/connection.go b/connection.go index 1d55dd57..42b1a75d 100644 --- a/connection.go +++ b/connection.go @@ -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) } diff --git a/misc.go b/misc.go index a3240449..5ac9d538 100644 --- a/misc.go +++ b/misc.go @@ -43,7 +43,9 @@ type piecePriority byte const ( piecePriorityNone piecePriority = iota piecePriorityNormal - piecePriorityHigh + piecePriorityReadahead + piecePriorityNext + piecePriorityNow ) type piece struct { diff --git a/torrent.go b/torrent.go index 56b738a8..91e550d9 100644 --- a/torrent.go +++ b/torrent.go @@ -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 '.' + } } }