This should save some allocation overhead, especially for torrents that have 20k+ pieces.
// Currently doesn't really queue, but should in the future.
func (cl *Client) queuePieceCheck(t *torrent, pieceIndex pp.Integer) {
- piece := t.Pieces[pieceIndex]
+ piece := &t.Pieces[pieceIndex]
if piece.QueuedForHash {
return
}
// Queue a piece check if one isn't already queued, and the piece has never
// been checked before.
func (cl *Client) queueFirstHash(t *torrent, piece int) {
- p := t.Pieces[piece]
+ p := &t.Pieces[piece]
if p.EverHashed || p.Hashing || p.QueuedForHash || t.pieceComplete(piece) {
return
}
if priority != PiecePriorityNone {
cl.queueFirstHash(t, piece)
}
- p := t.Pieces[piece]
+ p := &t.Pieces[piece]
if p.Priority != priority {
p.Priority = priority
cl.pieceChanged(t, piece)
// Count the chunk being sent, even if it isn't.
c.chunksSent++
b := make([]byte, r.Length)
- tp := t.Pieces[r.Index]
+ tp := &t.Pieces[r.Index]
tp.pendingWritesMutex.Lock()
for tp.pendingWrites != 0 {
tp.noPendingWrites.Wait()
if !cl.config.NoUpload {
// Queue all pieces for hashing. This is done sequentially to avoid
// spamming goroutines.
- for _, p := range t.Pieces {
- p.QueuedForHash = true
+ for i := range t.Pieces {
+ t.Pieces[i].QueuedForHash = true
}
go func() {
for i := range t.Pieces {
c.pieceRequestOrder.DeletePiece(pieceIndex)
continue
}
- piece := t.Pieces[pieceIndex]
+ piece := &t.Pieces[pieceIndex]
for _, cs := range piece.shuffledPendingChunkSpecs(t.pieceLength(pieceIndex), pp.Integer(t.chunkSize)) {
r := request{pp.Integer(pieceIndex), cs}
if !addRequest(r) {
unexpectedChunksReceived.Add(1)
}
- piece := t.Pieces[req.Index]
+ piece := &t.Pieces[req.Index]
// Do we actually want this chunk?
if !t.wantChunk(req) {
}
func (me *Client) pieceHashed(t *torrent, piece pp.Integer, correct bool) {
- p := t.Pieces[piece]
+ p := &t.Pieces[piece]
if p.EverHashed {
// Don't score the first time a piece is hashed, it could be an
// initial check.
// TODO: Check this isn't called more than once for each piece being correct.
func (me *Client) pieceChanged(t *torrent, piece int) {
correct := t.pieceComplete(piece)
- p := t.Pieces[piece]
+ p := &t.Pieces[piece]
defer t.publishPieceChange(piece)
defer p.Event.Broadcast()
if correct {
func (cl *Client) verifyPiece(t *torrent, index pp.Integer) {
cl.mu.Lock()
defer cl.mu.Unlock()
- p := t.Pieces[index]
+ p := &t.Pieces[index]
for p.Hashing || t.data == nil {
cl.event.Wait()
}
if len(tor.Pieces) != 3 {
t.Fatal("wrong number of pieces")
}
- p := tor.Pieces[0]
+ p := &tor.Pieces[0]
tor.pendAllChunkSpecs(0)
assert.EqualValues(t, 3, p.numPendingChunks())
assert.EqualValues(t, chunkSpec{4, 1}, chunkIndexSpec(2, tor.pieceLength(0), tor.chunkSize))
r.t.cl.mu.Unlock()
b1 := b[:avail]
pi := int(pos / r.t.Info().PieceLength)
- tp := r.t.torrent.Pieces[pi]
+ tp := &r.t.torrent.Pieces[pi]
ip := r.t.Info().Piece(pi)
po := pos % ip.Length()
if int64(len(b1)) > ip.Length()-po {
if t.pieceComplete(index) {
return 0
}
- piece := t.Pieces[index]
+ piece := &t.Pieces[index]
pieceLength := t.pieceLength(index)
if !piece.EverHashed {
return pieceLength
ceasingNetworking chan struct{}
InfoHash InfoHash
- Pieces []*piece
+ Pieces []piece
// Values are the piece indices that changed.
pieceStateChanges *pubsub.PubSub
chunkSize pp.Integer
}
t.MetaData = infoBytes
t.metadataHave = nil
- for _, hash := range infoPieceHashes(md) {
- piece := &piece{}
+ hashes := infoPieceHashes(md)
+ t.Pieces = make([]piece, len(hashes))
+ for i, hash := range hashes {
+ piece := &t.Pieces[i]
piece.Event.L = eventLocker
piece.noPendingWrites.L = &piece.pendingWritesMutex
missinggo.CopyExact(piece.Hash[:], hash)
- t.Pieces = append(t.Pieces, piece)
}
for _, conn := range t.Conns {
t.initRequestOrdering(conn)
}
func (t *torrent) pieceState(index int) (ret PieceState) {
- p := t.Pieces[index]
+ p := &t.Pieces[index]
ret.Priority = p.Priority
if t.pieceComplete(index) {
ret.Complete = true
}
func (t *torrent) bitfield() (bf []bool) {
- for _, p := range t.Pieces {
+ for i := range t.Pieces {
+ p := &t.Pieces[i]
// TODO: Check this logic.
bf = append(bf, p.EverHashed && p.numPendingChunks() == 0)
}
}
func (t *torrent) pendAllChunkSpecs(pieceIndex int) {
- piece := t.Pieces[pieceIndex]
+ piece := &t.Pieces[pieceIndex]
if piece.PendingChunkSpecs == nil {
// Allocate to exact size.
piece.PendingChunkSpecs = make([]bool, (t.pieceLength(pieceIndex)+t.chunkSize-1)/t.chunkSize)
func (t *torrent) hashPiece(piece pp.Integer) (ps pieceSum) {
hash := pieceHash.New()
- p := t.Pieces[piece]
+ p := &t.Pieces[piece]
p.pendingWritesMutex.Lock()
for p.pendingWrites != 0 {
p.noPendingWrites.Wait()
if t.pieceComplete(int(r.Index)) {
return true
}
- p := t.Pieces[r.Index]
+ p := &t.Pieces[r.Index]
if p.PendingChunkSpecs == nil {
return false
}
if !t.haveInfo() {
return false
}
- p := t.Pieces[index]
+ p := &t.Pieces[index]
if p.QueuedForHash {
return false
}
func (t *torrent) publishPieceChange(piece int) {
cur := t.pieceState(piece)
- p := t.Pieces[piece]
+ p := &t.Pieces[piece]
if cur != p.PublicPieceState {
t.pieceStateChanges.Publish(piece)
}