Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added workaround for corrupted zip chunks #7243

Merged
merged 13 commits into from
Dec 8, 2023
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Fixed

- Added workaround for corrupted cached chunks
(<https://github.com/opencv/cvat/pull/7243>)
27 changes: 20 additions & 7 deletions cvat/apps/engine/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from io import BytesIO
import shutil
import tempfile
import zlib

from typing import Optional, Tuple

Expand Down Expand Up @@ -43,17 +44,30 @@ def __init__(self, dimension=DimensionType.DIM_2D):
self._cache = caches['media']

def _get_or_set_cache_item(self, key, create_function):
slogger.glob.info(f'Starting to get chunk from cache: key {key}')
item = self._cache.get(key)
slogger.glob.info(f'Ending to get chunk from cache: key {key}, is_cached {bool(item)}')
if not item:
def create_item():
slogger.glob.info(f'Starting to prepare chunk: key {key}')
item = create_function()
slogger.glob.info(f'Ending to prepare chunk: key {key}')

if item[0]:
item = (item[0], item[1], zlib.crc32(item[0].getbuffer()))
self._cache.set(key, item)

return item
return item

slogger.glob.info(f'Starting to get chunk from cache: key {key}')
item = self._cache.get(key)
slogger.glob.info(f'Ending to get chunk from cache: key {key}, is_cached {bool(item)}')
if not item:
item = create_item()
else:
# compare checksum
item_checksum = item[2] if len(item) == 3 else None
if item_checksum != zlib.crc32(item[0].getbuffer()):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

item[0] might not be a BytesIO if it's loaded from a cache created by a previous version.

slogger.glob.info(f'Recreating cache item {key} due to checksum mismatch')
item = create_item()
bsekachev marked this conversation as resolved.
Show resolved Hide resolved

return item[0], item[1]

def get_task_chunk_data_with_mime(self, chunk_number, quality, db_data):
item = self._get_or_set_cache_item(
Expand Down Expand Up @@ -323,6 +337,5 @@ def _prepare_context_image(self, db_data, frame_number):
if not success:
raise Exception('Failed to encode image to ".jpeg" format')
zip_file.writestr(f'{name}.jpg', result.tobytes())
buff = zip_buffer.getvalue()
mime_type = 'application/zip'
return buff, mime_type
return zip_buffer, mime_type
SpecLad marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 1 addition & 1 deletion cvat/apps/engine/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ def __call__(self, request, start: int, stop: int, db_data: Optional[Data]):
buff, mime = cache.get_frame_context_images(db_data, self.number)
if not buff:
return HttpResponseNotFound()
return HttpResponse(io.BytesIO(buff), content_type=mime)
return HttpResponse(buff, content_type=mime)
else:
return Response(data='unknown data type {}.'.format(self.type),
status=status.HTTP_400_BAD_REQUEST)
Expand Down
Loading