Skip to content

Commit 13747b8

Browse files
OSUpdate app: fix resume logic
1 parent 3135230 commit 13747b8

File tree

1 file changed

+17
-24
lines changed
  • internal_filesystem/builtin/apps/com.micropythonos.osupdate/assets

1 file changed

+17
-24
lines changed

internal_filesystem/builtin/apps/com.micropythonos.osupdate/assets/osupdate.py

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,7 @@ def __init__(self, partition_module=None, connectivity_manager=None, download_ma
442442

443443
# Download state for pause/resume
444444
self.is_paused = False
445-
self.bytes_written_so_far = 0 # Bytes written to partition (in 4096-byte blocks)
446-
self.bytes_received_so_far = 0 # Actual bytes received from network (for resume)
445+
self.bytes_written_so_far = 0 # Bytes written to partition (in complete 4096-byte blocks)
447446
self.total_size_expected = 0
448447

449448
# Internal state for chunk processing
@@ -524,9 +523,8 @@ async def _process_chunk(self, chunk):
524523
self.is_paused = True
525524
raise OSError(-113, "Network lost during download")
526525

527-
# Track total bytes received (for accurate resume position)
526+
# Track total bytes received
528527
self._total_bytes_received += len(chunk)
529-
self.bytes_received_so_far += len(chunk)
530528

531529
# Add chunk to buffer
532530
self._chunk_buffer += chunk
@@ -603,14 +601,16 @@ async def download_and_install(self, url, progress_callback=None, speed_callback
603601
# Setup partition
604602
self._setup_partition()
605603

606-
# Initialize block index from resume position (based on bytes written to partition)
604+
# Initialize block index from resume position
607605
self._block_index = self.bytes_written_so_far // self.CHUNK_SIZE
608606

609-
# Build headers for resume (based on bytes received from network)
607+
# Build headers for resume - use bytes_written_so_far (last complete block)
608+
# This ensures we re-download any partial/buffered data and overwrite any
609+
# potentially corrupted block from when the error occurred
610610
headers = None
611-
if self.bytes_received_so_far > 0:
612-
headers = {'Range': f'bytes={self.bytes_received_so_far}-'}
613-
print(f"UpdateDownloader: Resuming from byte {self.bytes_received_so_far} (written: {self.bytes_written_so_far})")
611+
if self.bytes_written_so_far > 0:
612+
headers = {'Range': f'bytes={self.bytes_written_so_far}-'}
613+
print(f"UpdateDownloader: Resuming from byte {self.bytes_written_so_far} (last complete block)")
614614

615615
# Get the download manager (use injected one for testing, or global)
616616
dm = self.download_manager if self.download_manager else DownloadManager
@@ -624,7 +624,7 @@ async def chunk_handler(chunk):
624624

625625
# For initial download, we need to get total size first
626626
# DownloadManager doesn't expose Content-Length directly, so we estimate
627-
if self.bytes_received_so_far == 0:
627+
if self.bytes_written_so_far == 0:
628628
# We'll update total_size_expected as we download
629629
# For now, set a placeholder that will be updated
630630
self.total_size_expected = 0
@@ -655,7 +655,6 @@ async def chunk_handler(chunk):
655655
# Reset state for next download
656656
self.is_paused = False
657657
self.bytes_written_so_far = 0
658-
self.bytes_received_so_far = 0
659658
self.total_size_expected = 0
660659
self._current_partition = None
661660
self._block_index = 0
@@ -676,34 +675,28 @@ async def chunk_handler(chunk):
676675
# Check if cancelled by user
677676
if "cancelled" in error_msg.lower():
678677
result['error'] = error_msg
679-
result['bytes_written'] = self.bytes_received_so_far # Report actual bytes received
678+
result['bytes_written'] = self.bytes_written_so_far
680679
result['total_size'] = self.total_size_expected
681680
# Check if this is a network error that should trigger pause
682681
elif self._is_network_error(e):
683682
print(f"UpdateDownloader: Network error ({e}), pausing download")
684683

685-
# Flush buffer before pausing to ensure all received data is written
686-
# This prevents data loss/corruption on resume
684+
# Clear buffer - we'll re-download this data on resume
685+
# This ensures we overwrite any potentially corrupted block
687686
if self._chunk_buffer:
688687
buffer_len = len(self._chunk_buffer)
689-
print(f"UpdateDownloader: Flushing {buffer_len} bytes from buffer before pause")
690-
# Pad to 4096 bytes and write
691-
padded = self._chunk_buffer + b'\xFF' * (self.CHUNK_SIZE - buffer_len)
692-
if not self.simulate:
693-
self._current_partition.writeblocks(self._block_index, padded)
694-
self._block_index += 1
695-
self.bytes_written_so_far += self.CHUNK_SIZE
688+
print(f"UpdateDownloader: Discarding {buffer_len} bytes from buffer (will re-download on resume)")
696689
self._chunk_buffer = b''
697-
print(f"UpdateDownloader: Buffer flushed, bytes_written_so_far now: {self.bytes_written_so_far}, bytes_received: {self.bytes_received_so_far}")
698690

699691
self.is_paused = True
700692
result['paused'] = True
701-
result['bytes_written'] = self.bytes_received_so_far # Report actual bytes received for resume
693+
result['bytes_written'] = self.bytes_written_so_far # Resume from last complete block
702694
result['total_size'] = self.total_size_expected
695+
print(f"UpdateDownloader: Will resume from byte {self.bytes_written_so_far} (last complete block)")
703696
else:
704697
# Non-network error
705698
result['error'] = error_msg
706-
result['bytes_written'] = self.bytes_received_so_far # Report actual bytes received
699+
result['bytes_written'] = self.bytes_written_so_far
707700
result['total_size'] = self.total_size_expected
708701
print(f"UpdateDownloader: Error during download: {e}")
709702

0 commit comments

Comments
 (0)