From e9ee3e054636733ced9d92a5ff27aac20a821334 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 6 May 2021 07:21:50 +0530 Subject: [PATCH] Use a context manager for vls_cache_lock --- src/calibre/db/cache.py | 17 +++++++---------- src/calibre/db/locking.py | 11 +++++++++++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/calibre/db/cache.py b/src/calibre/db/cache.py index e4f1f86051..9792574338 100644 --- a/src/calibre/db/cache.py +++ b/src/calibre/db/cache.py @@ -29,7 +29,9 @@ from calibre.db.categories import get_categories from calibre.db.errors import NoSuchBook, NoSuchFormat from calibre.db.fields import IDENTITY, InvalidLinkTable, create_field from calibre.db.lazy import FormatMetadata, FormatsList, ProxyMetadata -from calibre.db.locking import LockingError, DowngradeLockError, SafeReadLock, create_locks +from calibre.db.locking import ( + DowngradeLockError, LockingError, SafeReadLock, create_locks, try_lock +) from calibre.db.search import Search from calibre.db.tables import VirtualTable from calibre.db.utils import type_safe_sort_key_function @@ -2232,12 +2234,10 @@ class Cache(object): if self.vls_for_books_cache is None: # Using a list is slightly faster than a set. c = defaultdict(list) - got_lock = False - try: - # use a primitive lock to ensure that only one thread is updating - # the cache and that recursive calls don't do the update. This - # method can recurse via self._search() - got_lock = self.vls_cache_lock.acquire(blocking=False) + # use a primitive lock to ensure that only one thread is updating + # the cache and that recursive calls don't do the update. This + # method can recurse via self._search() + with try_lock(self.vls_cache_lock) as got_lock: if not got_lock: # We get here if resolving the books in a VL triggers another VL # calculation. This can be 'real' recursion, in which case the @@ -2258,9 +2258,6 @@ class Cache(object): if book: c[book].append(_('[Error in Virtual library {0}: {1}]').format(lib, str(e))) self.vls_for_books_cache = {b:tuple(sorted(libs, key=sort_key)) for b, libs in c.items()} - finally: - if got_lock: - self.vls_cache_lock.release() if not book_ids: book_ids = self._all_book_ids() # book_ids is usually 1 long. The loop will be faster than a comprehension diff --git a/src/calibre/db/locking.py b/src/calibre/db/locking.py index e0830f46d8..b4da772633 100644 --- a/src/calibre/db/locking.py +++ b/src/calibre/db/locking.py @@ -8,9 +8,20 @@ __docformat__ = 'restructuredtext en' import traceback, sys from threading import Lock, Condition, current_thread +from contextlib import contextmanager from calibre.utils.config_base import tweaks +@contextmanager +def try_lock(lock): + got_lock = lock.acquire(blocking=False) + try: + yield got_lock + finally: + if got_lock: + lock.release() + + class LockingError(RuntimeError): is_locking_error = True