Skip to content

Commit 3135230

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

File tree

1 file changed

+29
-11
lines changed
  • internal_filesystem/builtin/apps/com.micropythonos.osupdate/assets

1 file changed

+29
-11
lines changed

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

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,8 @@ 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
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)
446447
self.total_size_expected = 0
447448

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

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

529531
# Add chunk to buffer
530532
self._chunk_buffer += chunk
@@ -601,14 +603,14 @@ async def download_and_install(self, url, progress_callback=None, speed_callback
601603
# Setup partition
602604
self._setup_partition()
603605

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

607-
# Build headers for resume
609+
# Build headers for resume (based on bytes received from network)
608610
headers = None
609-
if self.bytes_written_so_far > 0:
610-
headers = {'Range': f'bytes={self.bytes_written_so_far}-'}
611-
print(f"UpdateDownloader: Resuming from byte {self.bytes_written_so_far}")
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})")
612614

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

623625
# For initial download, we need to get total size first
624626
# DownloadManager doesn't expose Content-Length directly, so we estimate
625-
if self.bytes_written_so_far == 0:
627+
if self.bytes_received_so_far == 0:
626628
# We'll update total_size_expected as we download
627629
# For now, set a placeholder that will be updated
628630
self.total_size_expected = 0
@@ -653,6 +655,7 @@ async def chunk_handler(chunk):
653655
# Reset state for next download
654656
self.is_paused = False
655657
self.bytes_written_so_far = 0
658+
self.bytes_received_so_far = 0
656659
self.total_size_expected = 0
657660
self._current_partition = None
658661
self._block_index = 0
@@ -673,19 +676,34 @@ async def chunk_handler(chunk):
673676
# Check if cancelled by user
674677
if "cancelled" in error_msg.lower():
675678
result['error'] = error_msg
676-
result['bytes_written'] = self.bytes_written_so_far
679+
result['bytes_written'] = self.bytes_received_so_far # Report actual bytes received
677680
result['total_size'] = self.total_size_expected
678681
# Check if this is a network error that should trigger pause
679682
elif self._is_network_error(e):
680683
print(f"UpdateDownloader: Network error ({e}), pausing download")
684+
685+
# Flush buffer before pausing to ensure all received data is written
686+
# This prevents data loss/corruption on resume
687+
if self._chunk_buffer:
688+
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
696+
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}")
698+
681699
self.is_paused = True
682700
result['paused'] = True
683-
result['bytes_written'] = self.bytes_written_so_far
701+
result['bytes_written'] = self.bytes_received_so_far # Report actual bytes received for resume
684702
result['total_size'] = self.total_size_expected
685703
else:
686704
# Non-network error
687705
result['error'] = error_msg
688-
result['bytes_written'] = self.bytes_written_so_far
706+
result['bytes_written'] = self.bytes_received_so_far # Report actual bytes received
689707
result['total_size'] = self.total_size_expected
690708
print(f"UpdateDownloader: Error during download: {e}")
691709

0 commit comments

Comments
 (0)