From: Matt Joiner Date: Wed, 2 Jul 2025 05:06:34 +0000 (+1000) Subject: Consider dirty chunks in apriori webseed request generation X-Git-Tag: v1.59.0~53 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=d0ecabddcf9c4b617031e1e672e2630ccbcc0123;p=btrtrc.git Consider dirty chunks in apriori webseed request generation --- diff --git a/piece.go b/piece.go index ce98e8a0..4d6985c1 100644 --- a/piece.go +++ b/piece.go @@ -155,6 +155,19 @@ func (p *Piece) chunkIndexDirty(chunk chunkIndexType) bool { return p.t.dirtyChunks.Contains(p.requestIndexBegin() + chunk) } +func (p *Piece) firstCleanChunk() (_ g.Option[chunkIndexType]) { + it := p.t.dirtyChunks.Iterator() + begin := uint32(p.requestIndexBegin()) + end := uint32(p.requestIndexMaxEnd()) + it.AdvanceIfNeeded(begin) + for next := begin; next < end; next++ { + if !it.HasNext() || it.Next() != next { + return g.Some(chunkIndexType(next - begin)) + } + } + return +} + func (p *Piece) chunkIndexSpec(chunk chunkIndexType) ChunkSpec { return chunkIndexSpec(pp.Integer(chunk), p.length(), p.chunkSize()) } @@ -426,9 +439,9 @@ func (p *Piece) publishStateChange() { } } -func (p *Piece) fileExtents() iter.Seq2[int, segments.Extent] { +func (p *Piece) fileExtents(offsetIntoPiece int64) iter.Seq2[int, segments.Extent] { return p.t.info.FileSegmentsIndex().LocateIter(segments.Extent{ - p.torrentBeginOffset(), - segments.Int(p.length()), + p.torrentBeginOffset() + offsetIntoPiece, + int64(p.length()) - offsetIntoPiece, }) } diff --git a/typed-roaring/bitmap.go b/typed-roaring/bitmap.go index 7f7b1a7e..4e42dda7 100644 --- a/typed-roaring/bitmap.go +++ b/typed-roaring/bitmap.go @@ -46,3 +46,5 @@ func (me *Bitmap[T]) Remove(x T) { func (Bitmap[T]) IteratorType() Iterator[T] { return Iterator[T]{} } + +// TODO: Override Bitmap.Iterator. diff --git a/webseed-requesting.go b/webseed-requesting.go index 0a7c0333..7a001603 100644 --- a/webseed-requesting.go +++ b/webseed-requesting.go @@ -180,10 +180,20 @@ func (cl *Client) iterWebseed() iter.Seq2[webseedUniqueRequestKey, webseedReques value.pieces, func(ih metainfo.Hash, pieceIndex int, orderState requestStrategy.PieceRequestOrderState) bool { t := cl.torrentsByShortHash[ih] - for i, e := range t.piece(pieceIndex).fileExtents() { + p := t.piece(pieceIndex) + cleanOpt := p.firstCleanChunk() + if !cleanOpt.Ok { + // Could almost return true here, as clearly something is going on with the piece. + return false + } + // Pretty sure we want this and not the order state priority. That one is for + // client piece request order and ignores other states like hashing, marking + // etc. Order state priority would be faster otherwise. + priority := p.effectivePriority() + for i, e := range p.fileExtents(int64(cleanOpt.Value) * int64(t.chunkSize)) { for url, ws := range t.webSeeds { - // Return value from this function doesn't terminate, so don't pretend - // it does here either. + // Return value from this function (RequestPieceFunc) doesn't terminate + // iteration, so propagate that to not handling the yield return value. yield( webseedUniqueRequestKey{ aprioriWebseedRequestKey{ @@ -194,7 +204,7 @@ func (cl *Client) iterWebseed() iter.Seq2[webseedUniqueRequestKey, webseedReques e.Start, }, webseedRequestOrderValue{ - priority: orderState.Priority, + priority: priority, costKey: ws.hostKey, }, )