From 60c9d89a4064bee8f48717a197c40ac5bc28af79 Mon Sep 17 00:00:00 2001 From: Peter Amstutz Date: Mon, 24 Apr 2023 16:59:27 -0400 Subject: [PATCH] 20422: Do GET when cache slot is empty instead of raising an error Arvados-DCO-1.1-Signed-off-by: Peter Amstutz --- sdk/python/arvados/keep.py | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/sdk/python/arvados/keep.py b/sdk/python/arvados/keep.py index 6804f355a8..8658774cbb 100644 --- a/sdk/python/arvados/keep.py +++ b/sdk/python/arvados/keep.py @@ -1174,21 +1174,37 @@ class KeepClient(object): try: locator = KeepLocator(loc_s) if method == "GET": - slot, first = self.block_cache.reserve_cache(locator.md5sum) - if not first: + while slot is None: + slot, first = self.block_cache.reserve_cache(locator.md5sum) + if first: + # Fresh and empty "first time it is used" slot + break if prefetch: - # this is request for a prefetch, if it is - # already in flight, return immediately. - # clear 'slot' to prevent finally block from - # calling slot.set() + # this is request for a prefetch to fill in + # the cache, don't need to wait for the + # result, so if it is already in flight return + # immediately. Clear 'slot' to prevent + # finally block from calling slot.set() slot = None return None - self.hits_counter.add(1) + blob = slot.get() - if blob is None: - raise arvados.errors.KeepReadError( - "failed to read {}".format(loc_s)) - return blob + if blob is not None: + self.hits_counter.add(1) + return blob + + # If blob is None, this means either + # + # (a) another thread was fetching this block and + # failed with an error or + # + # (b) cache thrashing caused the slot to be + # evicted (content set to None) by another thread + # between the call to reserve_cache() and get(). + # + # We'll handle these cases by reserving a new slot + # and then doing a full GET request. + slot = None self.misses_counter.add(1) -- 2.30.2