diff --git a/misc.go b/misc.go index ab6dcf78..8f13a179 100644 --- a/misc.go +++ b/misc.go @@ -121,3 +121,11 @@ func validateInfo(info *metainfo.Info) error { } return nil } + +func chunkIndexSpec(index int, pieceLength, chunkSize pp.Integer) chunkSpec { + ret := chunkSpec{pp.Integer(index) * chunkSize, chunkSize} + if ret.Begin+ret.Length > pieceLength { + ret.Length = pieceLength - ret.Begin + } + return ret +} diff --git a/piece.go b/piece.go index bcc09546..104602f3 100644 --- a/piece.go +++ b/piece.go @@ -69,14 +69,6 @@ func (p *piece) pendChunkIndex(i int) { p.DirtyChunks.Remove(i) } -func chunkIndexSpec(index int, pieceLength, chunkSize pp.Integer) chunkSpec { - ret := chunkSpec{pp.Integer(index) * chunkSize, chunkSize} - if ret.Begin+ret.Length > pieceLength { - ret.Length = pieceLength - ret.Begin - } - return ret -} - func (p *piece) numChunks() int { return p.t.pieceNumChunks(p.index) } @@ -112,3 +104,45 @@ func (p *piece) waitNoPendingWrites() { } p.pendingWritesMutex.Unlock() } + +func (p *piece) chunkIndexDirty(chunk int) bool { + return p.DirtyChunks.Contains(chunk) +} + +func (p *piece) chunkIndexSpec(chunk int) chunkSpec { + return chunkIndexSpec(chunk, p.length(), p.chunkSize()) +} + +func (p *piece) numDirtyBytes() (ret pp.Integer) { + defer func() { + if ret > p.length() { + panic("too many dirty bytes") + } + }() + numRegularDirtyChunks := p.numDirtyChunks() + if p.chunkIndexDirty(p.numChunks() - 1) { + numRegularDirtyChunks-- + ret += p.chunkIndexSpec(p.lastChunkIndex()).Length + } + ret += pp.Integer(numRegularDirtyChunks) * p.chunkSize() + return +} + +func (p *piece) length() pp.Integer { + return p.t.pieceLength(p.index) +} + +func (p *piece) chunkSize() pp.Integer { + return p.t.chunkSize +} + +func (p *piece) lastChunkIndex() int { + return p.numChunks() - 1 +} + +func (p *piece) bytesLeft() (ret pp.Integer) { + if p.t.pieceComplete(p.index) { + return 0 + } + return p.length() - p.numDirtyBytes() +} diff --git a/torrent.go b/torrent.go index 6453c508..598c1718 100644 --- a/torrent.go +++ b/torrent.go @@ -29,25 +29,6 @@ func (t *torrent) chunkIndexSpec(chunkIndex, piece int) chunkSpec { return chunkIndexSpec(chunkIndex, t.pieceLength(piece), t.chunkSize) } -func (t *torrent) pieceNumPendingBytes(index int) (count pp.Integer) { - if t.pieceComplete(index) { - return - } - piece := &t.Pieces[index] - count = t.pieceLength(index) - if !piece.EverHashed { - return - } - regularDirty := piece.numDirtyChunks() - lastChunkIndex := t.pieceNumChunks(index) - 1 - if piece.pendingChunkIndex(lastChunkIndex) { - regularDirty-- - count -= t.chunkIndexSpec(lastChunkIndex, index).Length - } - count -= pp.Integer(regularDirty) * t.chunkSize - return -} - type peersKey struct { IPBytes string Port int @@ -511,11 +492,8 @@ func (t *torrent) MetaInfo() *metainfo.MetaInfo { } func (t *torrent) bytesLeft() (left int64) { - if !t.haveInfo() { - return -1 - } for i := 0; i < t.numPieces(); i++ { - left += int64(t.pieceNumPendingBytes(i)) + left += int64(t.Pieces[i].bytesLeft()) } return }