Use Option for cached Torrent length

Fixes https://github.com/anacrolix/torrent/issues/630.
This commit is contained in:
Matt Joiner 2022-05-12 13:47:12 +10:00
parent 9434fe58a2
commit eeb021b134
No known key found for this signature in database
GPG Key ID: 6B990B8185E7F782
3 changed files with 15 additions and 11 deletions

View File

@ -166,8 +166,8 @@ func (cl *Client) WriteStatus(_w io.Writer) {
w,
"%f%% of %d bytes (%s)",
100*(1-float64(t.bytesMissingLocked())/float64(t.info.TotalLength())),
*t.length,
humanize.Bytes(uint64(*t.length)))
t.length(),
humanize.Bytes(uint64(t.length())))
} else {
w.WriteString("<missing metainfo>")
}

4
t.go
View File

@ -32,7 +32,7 @@ func (t *Torrent) Info() (info *metainfo.Info) {
// Returns a Reader bound to the torrent's data. All read calls block until the data requested is
// actually available. Note that you probably want to ensure the Torrent Info is available first.
func (t *Torrent) NewReader() Reader {
return t.newReader(0, *t.length)
return t.newReader(0, t.length())
}
func (t *Torrent) newReader(offset, length int64) Reader {
@ -147,7 +147,7 @@ func (t *Torrent) Name() string {
// The completed length of all the torrent data, in all its files. This is
// derived from the torrent info, when it is available.
func (t *Torrent) Length() int64 {
return *t.length
return t._length.Value()
}
// Returns a run-time generated metainfo for the torrent that includes the

View File

@ -74,7 +74,7 @@ type Torrent struct {
chunkPool sync.Pool
// Total length of the torrent in bytes. Stored because it's not O(1) to
// get this from the info dict.
length *int64
_length Option[int64]
// The storage to open when the info dict becomes available.
storageOpener *storage.Client
@ -167,6 +167,10 @@ type Torrent struct {
requestIndexes []RequestIndex
}
func (t *Torrent) length() int64 {
return t._length.Value()
}
func (t *Torrent) selectivePieceAvailabilityFromPeers(i pieceIndex) (count int) {
// This could be done with roaring.BitSliceIndexing.
t.iterPeers(func(peer *Peer) {
@ -420,7 +424,7 @@ func (t *Torrent) cacheLength() {
for _, f := range t.info.UpvertedFiles() {
l += f.Length
}
t.length = &l
t._length = Some(l)
}
// TODO: This shouldn't fail for storage reasons. Instead we should handle storage failure
@ -895,13 +899,13 @@ func (t *Torrent) close(wg *sync.WaitGroup) (err error) {
}
func (t *Torrent) requestOffset(r Request) int64 {
return torrentRequestOffset(*t.length, int64(t.usualPieceSize()), r)
return torrentRequestOffset(t.length(), int64(t.usualPieceSize()), r)
}
// Return the request that would include the given offset into the torrent data. Returns !ok if
// there is no such request.
func (t *Torrent) offsetRequest(off int64) (req Request, ok bool) {
return torrentOffsetRequest(*t.length, t.info.PieceLength, int64(t.chunkSize), off)
return torrentOffsetRequest(t.length(), t.info.PieceLength, int64(t.chunkSize), off)
}
func (t *Torrent) writeChunk(piece int, begin int64, data []byte) (err error) {
@ -949,7 +953,7 @@ func (t *Torrent) pieceLength(piece pieceIndex) pp.Integer {
return 0
}
if piece == t.numPieces()-1 {
ret := pp.Integer(*t.length % t.info.PieceLength)
ret := pp.Integer(t.length() % t.info.PieceLength)
if ret != 0 {
return ret
}
@ -1225,7 +1229,7 @@ func (t *Torrent) updatePiecePriorities(begin, end pieceIndex, reason string) {
// Returns the range of pieces [begin, end) that contains the extent of bytes.
func (t *Torrent) byteRegionPieces(off, size int64) (begin, end pieceIndex) {
if off >= *t.length {
if off >= t.length() {
return
}
if off < 0 {
@ -1442,7 +1446,7 @@ func (t *Torrent) bytesCompleted() int64 {
if !t.haveInfo() {
return 0
}
return *t.length - t.bytesLeft()
return t.length() - t.bytesLeft()
}
func (t *Torrent) SetInfoBytes(b []byte) (err error) {