summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDevaev Maxim <[email protected]>2020-03-01 03:58:08 +0300
committerDevaev Maxim <[email protected]>2020-03-01 03:58:08 +0300
commitff6e284e64c0e0a9e496fc047786a7d9c3aa907b (patch)
tree1640fa97b86b8342e08242f4ccf0441b24201e5d
parentcae9ad9a2191a10eeab8371601a24aaec8957dd8 (diff)
no busyloop in otg msd
-rw-r--r--kvmd/plugins/msd/otg/__init__.py37
1 files changed, 18 insertions, 19 deletions
diff --git a/kvmd/plugins/msd/otg/__init__.py b/kvmd/plugins/msd/otg/__init__.py
index f3695530..24d666f9 100644
--- a/kvmd/plugins/msd/otg/__init__.py
+++ b/kvmd/plugins/msd/otg/__init__.py
@@ -103,8 +103,8 @@ class _VirtualDriveState:
class _State:
- def __init__(self, changes_queue: asyncio.queues.Queue) -> None:
- self.__changes_queue = changes_queue
+ def __init__(self, notifier: aiotools.AioNotifier) -> None:
+ self.__notifier = notifier
self.storage: Optional[_StorageState] = None
self.vd: Optional[_VirtualDriveState] = None
@@ -116,13 +116,13 @@ class _State:
async def busy(self, check_online: bool=True) -> AsyncGenerator[None, None]:
with self._region:
async with self._lock:
- await self.__changes_queue.put(None)
+ await self.__notifier.notify()
if check_online:
if self.vd is None:
raise MsdOfflineError()
assert self.storage
yield
- await self.__changes_queue.put(None)
+ await self.__notifier.notify()
def is_busy(self) -> bool:
return self._region.is_busy()
@@ -154,9 +154,8 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
self.__new_file_written = 0
self.__new_file_tick = 0.0
- self.__changes_queue: asyncio.queues.Queue = asyncio.Queue()
-
- self.__state = _State(self.__changes_queue)
+ self.__state_notifier = aiotools.AioNotifier()
+ self.__state = _State(self.__state_notifier)
logger = get_logger(0)
logger.info("Using OTG gadget %r as MSD", gadget)
@@ -215,15 +214,15 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
if inotify_task.done():
RuntimeError("Inotify task is dead")
- try:
- await asyncio.wait_for(self.__changes_queue.get(), timeout=0.1)
- except asyncio.TimeoutError:
- continue
-
state = await self.get_state()
if state != prev_state:
yield state
prev_state = state
+
+ await asyncio.wait([
+ inotify_task,
+ self.__state_notifier.wait(),
+ ], return_when=asyncio.FIRST_COMPLETED)
finally:
if not inotify_task.done():
inotify_task.cancel()
@@ -308,7 +307,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
with self.__state._region: # pylint: disable=protected-access
try:
async with self.__state._lock: # pylint: disable=protected-access
- await self.__changes_queue.put(None)
+ await self.__state_notifier.notify()
assert self.__state.storage
assert self.__state.vd
@@ -324,7 +323,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
self.__new_file_written = 0
self.__new_file = await aiofiles.open(path, mode="w+b", buffering=0)
- await self.__changes_queue.put(None)
+ await self.__state_notifier.notify()
yield
self.__set_image_complete(name, True)
@@ -340,7 +339,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
# Между закрытием файла и эвентом айнотифи состояние может быть не обновлено,
# так что форсим обновление вручную, чтобы получить актуальное состояние.
await self.__reload_state()
- await self.__changes_queue.put(None)
+ await self.__state_notifier.notify()
async def write_image_chunk(self, chunk: bytes) -> int:
assert self.__new_file
@@ -350,7 +349,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
if self.__new_file_tick + 1 < now:
# Это нужно для ручного оповещения о свободном пространстве на диске, см. get_state()
self.__new_file_tick = now
- await self.__changes_queue.put(None)
+ await self.__state_notifier.notify()
return self.__new_file_written
async def remove(self, name: str) -> None:
@@ -399,7 +398,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
while True:
# Активно ждем, пока не будут на месте все каталоги.
await self.__reload_state()
- await self.__changes_queue.put(None)
+ await self.__state_notifier.notify()
if self.__state.vd:
break
await asyncio.sleep(5)
@@ -411,7 +410,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
# После установки вотчеров еще раз проверяем стейт, чтобы ничего не потерять
await self.__reload_state()
- await self.__changes_queue.put(None)
+ await self.__state_notifier.notify()
while self.__state.vd: # Если живы после предыдущей проверки
need_restart = False
@@ -427,7 +426,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
break
if need_reload_state:
await self.__reload_state()
- await self.__changes_queue.put(None)
+ await self.__state_notifier.notify()
except asyncio.CancelledError: # pylint: disable=try-except-raise
raise
except Exception: