From db13747279e92d645b2f07753e886ed29e3c7e6a Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 14 Nov 2019 16:22:45 +0800 Subject: [PATCH] fix device_db alias corner case bugs. Closes #1140 --- artiq/examples/artiq_ipython_notebook.ipynb | 4 +- artiq/frontend/artiq_coremgmt.py | 3 +- artiq/master/databases.py | 8 +++- artiq/master/worker_db.py | 44 ++++++++++----------- 4 files changed, 31 insertions(+), 28 deletions(-) diff --git a/artiq/examples/artiq_ipython_notebook.ipynb b/artiq/examples/artiq_ipython_notebook.ipynb index 50b0b0905..7964cd5a4 100644 --- a/artiq/examples/artiq_ipython_notebook.ipynb +++ b/artiq/examples/artiq_ipython_notebook.ipynb @@ -72,8 +72,8 @@ "assert lda.get_attenuation() == 42\n", "\n", "# ... or we can wire it up ourselves if you know where it is\n", - "assert ddb.get(\"lda\")[\"host\"] == \"::1\"\n", - "assert ddb.get(\"lda\")[\"port\"] == 3253\n", + "assert ddb.get(\"lda\", resolve_alias=True)[\"host\"] == \"::1\"\n", + "assert ddb.get(\"lda\", resolve_alias=True)[\"port\"] == 3253\n", "\n", "# there are different Client types tailored to different use cases:\n", "\n", diff --git a/artiq/frontend/artiq_coremgmt.py b/artiq/frontend/artiq_coremgmt.py index db420c971..542e12925 100755 --- a/artiq/frontend/artiq_coremgmt.py +++ b/artiq/frontend/artiq_coremgmt.py @@ -142,7 +142,8 @@ def main(): common_args.init_logger_from_args(args) if args.device is None: - core_addr = DeviceDB(args.device_db).get("core")["arguments"]["host"] + ddb = DeviceDB(args.device_db) + core_addr = ddb.get("core", resolve_alias=True)["arguments"]["host"] else: core_addr = args.device mgmt = CommMgmt(core_addr) diff --git a/artiq/master/databases.py b/artiq/master/databases.py index 0eb59bf0e..977cfae44 100644 --- a/artiq/master/databases.py +++ b/artiq/master/databases.py @@ -25,8 +25,12 @@ class DeviceDB: def get_device_db(self): return self.data.raw_view - def get(self, key): - return self.data.raw_view[key] + def get(self, key, resolve_alias=False): + desc = self.data.raw_view[key] + if resolve_alias: + while isinstance(desc, str): + desc = self.data.raw_view[desc] + return desc class DatasetDB(TaskObject): diff --git a/artiq/master/worker_db.py b/artiq/master/worker_db.py index 6d3799576..172846145 100644 --- a/artiq/master/worker_db.py +++ b/artiq/master/worker_db.py @@ -5,7 +5,6 @@ standalone command line tools). """ from operator import setitem -from collections import OrderedDict import importlib import logging @@ -60,44 +59,43 @@ class DeviceManager: def __init__(self, ddb, virtual_devices=dict()): self.ddb = ddb self.virtual_devices = virtual_devices - self.active_devices = OrderedDict() + self.active_devices = [] def get_device_db(self): """Returns the full contents of the device database.""" return self.ddb.get_device_db() def get_desc(self, name): - desc = self.ddb.get(name) - while isinstance(desc, str): - # alias - desc = self.ddb.get(desc) - return desc + return self.ddb.get(name, resolve_alias=True) def get(self, name): """Get the device driver or controller client corresponding to a device database entry.""" if name in self.virtual_devices: return self.virtual_devices[name] - if name in self.active_devices: - return self.active_devices[name] - else: - try: - desc = self.get_desc(name) - except Exception as e: - raise DeviceError("Failed to get description of device '{}'" - .format(name)) from e - try: - dev = _create_device(desc, self) - except Exception as e: - raise DeviceError("Failed to create device '{}'" - .format(name)) from e - self.active_devices[name] = dev - return dev + + try: + desc = self.get_desc(name) + except Exception as e: + raise DeviceError("Failed to get description of device '{}'" + .format(name)) from e + + for existing_desc, existing_dev in self.active_devices: + if desc == existing_desc: + return existing_dev + + try: + dev = _create_device(desc, self) + except Exception as e: + raise DeviceError("Failed to create device '{}'" + .format(name)) from e + self.active_devices.append((desc, dev)) + return dev def close_devices(self): """Closes all active devices, in the opposite order as they were requested.""" - for dev in reversed(list(self.active_devices.values())): + for _desc, dev in reversed(self.active_devices): try: if isinstance(dev, (Client, BestEffortClient)): dev.close_rpc()