client.go | 34 ++++++++++++++++++++++++++++------ connection.go | 15 +++++++++------ misc.go | 4 +++- torrent.go | 22 ++++++++++++++++++---- diff --git a/client.go b/client.go index 3361132ae5cb6a7a3d73c2d8f39b9953ed08761b..84a11f59058ba874d5bfb80c1617731c94c6c0c0 100644 --- a/client.go +++ b/client.go @@ -264,22 +264,36 @@ if pieceLeft <= 0 { 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") } @@ -290,6 +304,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) { @@ -1595,8 +1615,10 @@ for i := 0; i < t.NumPieces(); i++ { // 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 1d55dd5732458de86b8d49807f40be1018689702..42b1a75d005e5e94309073b061f27e617efb293d 100644 --- a/connection.go +++ b/connection.go @@ -8,7 +8,6 @@ "errors" "expvar" "fmt" "io" - "log" "net" "sync" "time" @@ -94,11 +93,15 @@ cn.pieceRequestOrder.RemovePiece(piece) 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 a32404495b18d052067a1d2a2228a70be1654dbd..5ac9d53874f2776bd70242c8a64ecb7566c33be7 100644 --- a/misc.go +++ b/misc.go @@ -43,7 +43,9 @@ const ( piecePriorityNone piecePriority = iota piecePriorityNormal - piecePriorityHigh + piecePriorityReadahead + piecePriorityNext + piecePriorityNow ) type piece struct { diff --git a/torrent.go b/torrent.go index 56b738a8d1d3922632dd669e42890832c31a991b..91e550d9e8b85b9e20364a759b954953b07b72be 100644 --- a/torrent.go +++ b/torrent.go @@ -281,12 +281,26 @@ case p.Hashing: 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 '.' + } } }