atomic fixes, removed tasked and muted

This commit is contained in:
Devaev Maxim
2020-03-03 23:48:53 +03:00
parent 3b16242cfa
commit 552bb93212
6 changed files with 124 additions and 153 deletions

View File

@@ -162,19 +162,17 @@ class Plugin(BaseAtx): # pylint: disable=too-many-instance-attributes
@aiotools.atomic
async def __click(self, name: str, pin: int, delay: float) -> None:
async with self.__region.exit_only_on_exception():
await self.__inner_click(name, pin, delay)
await aiotools.run_region_task(
"Can't perform ATX click or operation was not completed",
self.__region, self.__inner_click, name, pin, delay,
)
@aiotools.tasked
@aiotools.muted("Can't perform ATX click or operation was not completed")
@aiotools.atomic
async def __inner_click(self, name: str, pin: int, delay: float) -> None:
try:
gpio.write(pin, True)
await asyncio.sleep(delay)
finally:
try:
gpio.write(pin, False)
await asyncio.sleep(1)
finally:
await self.__region.exit()
gpio.write(pin, False)
await asyncio.sleep(1)
get_logger(0).info("Clicked ATX button %r", name)

View File

@@ -157,7 +157,7 @@ class Plugin(BaseHid, multiprocessing.Process): # pylint: disable=too-many-inst
self.__retries_delay = retries_delay
self.__noop = noop
self.__lock = asyncio.Lock()
self.__reset_wip = False
self.__events_queue: multiprocessing.queues.Queue = multiprocessing.Queue()
@@ -216,42 +216,39 @@ class Plugin(BaseHid, multiprocessing.Process): # pylint: disable=too-many-inst
@aiotools.atomic
async def reset(self) -> None:
async with aiotools.unlock_only_on_exception(self.__lock):
await self.__inner_reset()
@aiotools.tasked
@aiotools.muted("Can't reset HID or operation was not completed")
async def __inner_reset(self) -> None:
try:
gpio.write(self.__reset_pin, True)
await asyncio.sleep(self.__reset_delay)
finally:
if not self.__reset_wip:
try:
gpio.write(self.__reset_pin, False)
await asyncio.sleep(1)
self.__reset_wip = True
gpio.write(self.__reset_pin, True)
await asyncio.sleep(self.__reset_delay)
finally:
self.__lock.release()
get_logger(0).info("Reset HID performed")
try:
gpio.write(self.__reset_pin, False)
await asyncio.sleep(1)
finally:
self.__reset_wip = False
get_logger().info("Reset HID performed")
else:
get_logger().info("Another reset HID in progress")
@aiotools.atomic
async def cleanup(self) -> None:
logger = get_logger(0)
async with self.__lock:
try:
if self.is_alive():
logger.info("Stopping HID daemon ...")
self.__stop_event.set()
if self.exitcode is not None:
self.join()
if os.path.exists(self.__device_path):
get_logger().info("Clearing HID events ...")
try:
with self.__get_serial() as tty:
self.__process_command(tty, b"\x10\x00\x00\x00\x00")
except Exception:
logger.exception("Can't clear HID events")
finally:
gpio.write(self.__reset_pin, False)
try:
if self.is_alive():
logger.info("Stopping HID daemon ...")
self.__stop_event.set()
if self.exitcode is not None:
self.join()
if os.path.exists(self.__device_path):
get_logger().info("Clearing HID events ...")
try:
with self.__get_serial() as tty:
self.__process_command(tty, b"\x10\x00\x00\x00\x00")
except Exception:
logger.exception("Can't clear HID events")
finally:
gpio.write(self.__reset_pin, False)
# =====
@@ -272,8 +269,7 @@ class Plugin(BaseHid, multiprocessing.Process): # pylint: disable=too-many-inst
async def __queue_event(self, event: _BaseEvent) -> None:
if not self.__stop_event.is_set():
async with self.__lock:
self.__events_queue.put(event)
self.__events_queue.put_nowait(event)
def run(self) -> None: # pylint: disable=too-many-branches
logger = get_logger(0)

View File

@@ -352,6 +352,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
await self.__state_notifier.notify()
return self.__new_file_written
@aiotools.atomic
async def remove(self, name: str) -> None:
async with self.__state.busy():
assert self.__state.storage

View File

@@ -25,7 +25,6 @@ import stat
import fcntl
import struct
import asyncio
import asyncio.queues
import contextlib
import dataclasses
@@ -173,15 +172,14 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
self.__init_retries = init_retries
self.__reset_delay = reset_delay
self.__region = aiotools.AioExclusiveRegion(MsdIsBusyError)
self.__device_info: Optional[_DeviceInfo] = None
self.__connected = False
self.__device_file: Optional[aiofiles.base.AiofilesContextManager] = None
self.__written = 0
self.__state_queue: asyncio.queues.Queue = asyncio.Queue()
self.__state_notifier = aiotools.AioNotifier()
self.__region = aiotools.AioExclusiveRegion(MsdIsBusyError, self.__state_notifier)
logger = get_logger(0)
logger.info("Using %r as MSD", self.__device_path)
@@ -229,16 +227,22 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
}
async def poll_state(self) -> AsyncGenerator[Dict, None]:
prev_state: Dict = {}
while True:
yield (await self.__state_queue.get())
state = await self.get_state()
if state != prev_state:
yield state
prev_state = state
await self.__state_notifier.wait()
@aiotools.atomic
async def reset(self) -> None:
async with self.__region.exit_only_on_exception():
await self.__inner_reset()
await aiotools.run_region_task(
"Can't reset MSD or operation was not completed",
self.__region, self.__inner_reset,
)
@aiotools.tasked
@aiotools.muted("Can't reset MSD or operation was not completed")
@aiotools.atomic
async def __inner_reset(self) -> None:
try:
gpio.write(self.__reset_pin, True)
@@ -251,20 +255,19 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
await self.__load_device_info()
get_logger(0).info("MSD reset has been successful")
finally:
try:
gpio.write(self.__reset_pin, False)
finally:
await self.__region.exit()
await self.__state_queue.put(await self.get_state())
gpio.write(self.__reset_pin, False)
@aiotools.atomic
async def cleanup(self) -> None:
await self.__close_device_file()
gpio.write(self.__target_pin, False)
gpio.write(self.__reset_pin, False)
try:
await self.__close_device_file()
finally:
gpio.write(self.__target_pin, False)
gpio.write(self.__reset_pin, False)
# =====
@aiotools.atomic
async def set_params(self, name: Optional[str]=None, cdrom: Optional[bool]=None) -> None:
async with self.__working():
if name is not None:
@@ -275,66 +278,50 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
@aiotools.atomic
async def connect(self) -> None:
async with self.__working():
notify = False
try:
async with self.__region:
if self.__connected:
raise MsdConnectedError()
notify = True
async with self.__region:
if self.__connected:
raise MsdConnectedError()
gpio.write(self.__target_pin, True)
self.__connected = True
get_logger(0).info("MSD switched to Server")
finally:
if notify:
await self.__state_queue.put(await self.get_state())
gpio.write(self.__target_pin, True)
self.__connected = True
get_logger(0).info("MSD switched to Server")
@aiotools.atomic
async def disconnect(self) -> None:
async with self.__working():
notify = False
try:
async with self.__region:
if not self.__connected:
raise MsdDisconnectedError()
notify = True
async with self.__region:
if not self.__connected:
raise MsdDisconnectedError()
gpio.write(self.__target_pin, False)
try:
await self.__load_device_info()
except Exception:
if self.__connected:
gpio.write(self.__target_pin, True)
raise
self.__connected = False
get_logger(0).info("MSD switched to KVM: %s", self.__device_info)
finally:
if notify:
await self.__state_queue.put(await self.get_state())
gpio.write(self.__target_pin, False)
try:
await self.__load_device_info()
except Exception:
if self.__connected:
gpio.write(self.__target_pin, True)
raise
self.__connected = False
get_logger(0).info("MSD switched to KVM: %s", self.__device_info)
@contextlib.asynccontextmanager
async def write_image(self, name: str) -> AsyncGenerator[None, None]:
async with self.__working():
await self.__region.enter()
try:
assert self.__device_info
if self.__connected:
raise MsdConnectedError()
self.__device_file = await aiofiles.open(self.__device_info.path, mode="w+b", buffering=0)
self.__written = 0
await self.__write_image_info(name, complete=False)
await self.__state_queue.put(await self.get_state())
yield
await self.__write_image_info(name, complete=True)
finally:
async with self.__region:
try:
assert self.__device_info
if self.__connected:
raise MsdConnectedError()
self.__device_file = await aiofiles.open(self.__device_info.path, mode="w+b", buffering=0)
self.__written = 0
await self.__write_image_info(name, complete=False)
await self.__state_notifier.notify()
yield
await self.__write_image_info(name, complete=True)
finally:
await self.__close_device_file()
await self.__load_device_info()
finally:
await self.__region.exit()
await self.__state_queue.put(await self.get_state())
async def write_image_chunk(self, chunk: bytes) -> int:
assert self.__device_file
@@ -342,6 +329,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
self.__written += len(chunk)
return self.__written
@aiotools.atomic
async def remove(self, name: str) -> None:
async with self.__working():
raise MsdMultiNotSupported()