@@ -159,10 +159,9 @@ func (dl *dlClient) ReadAt(p []byte, off int64) (int, error) {
159159}
160160
161161// idleTaskRun is called during idle periods to download missing blocks
162- // in the background. It runs in a separate goroutine.
162+ // in the background. It runs in a separate goroutine and downloads multiple
163+ // consecutive blocks until approximately 1 second has elapsed.
163164func (dl * dlClient ) idleTaskRun () {
164- // this is run in a separate process
165-
166165 defer func () {
167166 atomic .AddUintptr (& dl .taskCnt , ^ uintptr (0 ))
168167 atomic .AddUintptr (& dl .dlm .taskCnt , ^ uintptr (0 ))
@@ -181,90 +180,89 @@ func (dl *dlClient) idleTaskRun() {
181180 // increase timer now to avoid deletion
182181 dl .expire = time .Now ().Add (time .Minute )
183182
184- if dl .reader != nil {
185- cnt := dl .handler .wantsFollowing (dl .rPos )
186- if cnt > 0 {
183+ startTime := time .Now ()
184+ blocksDownloaded := 0
185+ blkSize := dl .handler .getBlockSize ()
186+ buf := make ([]byte , blkSize )
187+
188+ // Helper to save progress if we downloaded anything
189+ defer func () {
190+ if blocksDownloaded > 0 {
191+ dl .handler .savePart ()
192+ dl .dlm .logf ("idle: downloaded %d blocks in %v" , blocksDownloaded , time .Since (startTime ))
193+ }
194+ }()
195+
196+ // Download blocks until ~1 second has passed
197+ for time .Since (startTime ) < time .Second {
198+ // Check if we have an existing reader at a useful position
199+ if dl .reader != nil {
200+ cnt := dl .handler .wantsFollowing (dl .rPos )
201+ if cnt <= 0 {
202+ // Current position already downloaded, close and find new position
203+ dl .reader .Body .Close ()
204+ dl .reader = nil
205+ continue
206+ }
207+
208+ // Read the block
187209 rPos := dl .rPos
188- // let's just read this from existing reader
189- buf := make ([]byte , cnt )
190- n , err := io .ReadFull (dl .reader .Body , buf )
210+ readBuf := buf [:cnt ]
211+ n , err := io .ReadFull (dl .reader .Body , readBuf )
191212 if err != nil && err != io .ErrUnexpectedEOF {
192213 dl .dlm .logf ("idle read failed: %s" , err )
193214 dl .reader .Body .Close ()
194215 dl .reader = nil
216+ if n == 0 {
217+ continue
218+ }
195219 }
196220 dl .rPos += int64 (n )
197221
198- // feed it
199- err = dl .handler .ingestData ( buf [:n ], rPos )
222+ // Ingest without saving (we'll save once at the end)
223+ err = dl .handler .ingestDataBatch ( readBuf [:n ], rPos )
200224 if err != nil {
201225 dl .dlm .logf ("idle write failed: %s" , err )
202226 dl .failure = true
227+ return
203228 }
204- return
229+ blocksDownloaded ++
230+ continue
205231 }
206232
207- dl .reader .Body .Close ()
208- dl .reader = nil
209- }
210-
211- // let's just ask where to start
212- off := dl .handler .firstMissing ()
213- if off < 0 {
214- // do not download
215- if dl .handler .isComplete () {
216- dl .complete = true
233+ // No reader, find first missing block
234+ off := dl .handler .firstMissing ()
235+ if off < 0 {
236+ if dl .handler .isComplete () {
237+ dl .complete = true
238+ }
239+ return
217240 }
218- return
219- }
220-
221- // spawn a new reader
222- req , err := http .NewRequest ("GET" , dl .url , nil )
223- if err != nil {
224- dl .dlm .logf ("idle: failed to create request: %s" , err )
225- return
226- }
227-
228- if off != 0 {
229- req .Header .Set ("Range" , fmt .Sprintf ("bytes=%d-" , off ))
230- }
231-
232- dl .dlm .logf ("idle: initializing HTTP connection download at byte %d~" , off )
233241
234- // should respond with code 206 Partial Content
235- resp , err := dl .dlm .Client .Do (req )
236- if err != nil {
237- dl .dlm .logf ("idle download failed: %s" , err )
238- return
239- }
240- if resp .StatusCode > 299 {
241- // that's bad
242- resp .Body .Close ()
243- dl .dlm .logf ("idle download failed due to status %s" , resp .Status )
244- return
245- }
246- dl .reader = resp
247- dl .rPos = off
242+ // Create new HTTP request
243+ req , err := http .NewRequest ("GET" , dl .url , nil )
244+ if err != nil {
245+ dl .dlm .logf ("idle: failed to create request: %s" , err )
246+ return
247+ }
248248
249- cnt := dl .handler .wantsFollowing (off )
250- if cnt <= 0 {
251- // why?
252- return
253- }
249+ if off != 0 {
250+ req .Header .Set ("Range" , fmt .Sprintf ("bytes=%d-" , off ))
251+ }
254252
255- buf := make ([]byte , cnt )
256- n , err := io .ReadFull (dl .reader .Body , buf )
257- if err != nil && err != io .ErrUnexpectedEOF {
258- dl .dlm .logf ("idle read failed: %s" , err )
259- dl .reader .Body .Close ()
260- dl .reader = nil
261- }
262- dl .rPos += int64 (n )
253+ dl .dlm .logf ("idle: initializing HTTP connection download at byte %d~" , off )
263254
264- // feed it (use separate thread to avoid deadlock)
265- err = dl .handler .ingestData (buf [:n ], off )
266- if err != nil {
267- dl .dlm .logf ("idle write failed: %s" , err )
268- dl .failure = true
255+ resp , err := dl .dlm .Client .Do (req )
256+ if err != nil {
257+ dl .dlm .logf ("idle download failed: %s" , err )
258+ return
259+ }
260+ if resp .StatusCode > 299 {
261+ resp .Body .Close ()
262+ dl .dlm .logf ("idle download failed due to status %s" , resp .Status )
263+ return
264+ }
265+ dl .reader = resp
266+ dl .rPos = off
269267 }
270268}
0 commit comments