diff options
author | Gregory Haynes <greg@greghaynes.net> | 2014-09-11 17:51:57 -0700 |
---|---|---|
committer | Devananda van der Veen <devananda.vdv@gmail.com> | 2014-09-29 15:57:55 -0700 |
commit | 9de2d21a96f440807b9822173de3fd3b6119fbe8 (patch) | |
tree | 7f2589abb11809b0d4347ee78d5dc47f6a87f73b /ironic/common/hash_ring.py | |
parent | 8a0923c437acf5bd840dc7f64db5e555962c15ac (diff) | |
download | ironic-9de2d21a96f440807b9822173de3fd3b6119fbe8.tar.gz |
Add HashRingManager to wrap hash ring singleton
Currently, the API service creates a new hash ring on every request.
Instead of that, we should cache the hash ring object -- but we should
also expose a way to refresh it when necessary. This method will also
be used by the ConductorManager to cache and refresh the hash ring
when conductors join / leave the cluster.
This patch preserves the existing API behavior by resetting the hash
ring on every request. This should be addressed in a subsequent patch.
Co-Authored-By: Devananda van der Veen <devananda.vdv@gmail.com>
Change-Id: Ib7ab55452499d1e1c362e4cd127f1e6e38106d6c
Diffstat (limited to 'ironic/common/hash_ring.py')
-rw-r--r-- | ironic/common/hash_ring.py | 38 |
1 files changed, 22 insertions, 16 deletions
diff --git a/ironic/common/hash_ring.py b/ironic/common/hash_ring.py index db3081fca..40f421424 100644 --- a/ironic/common/hash_ring.py +++ b/ironic/common/hash_ring.py @@ -114,10 +114,23 @@ class HashRing(object): class HashRingManager(object): + _hash_rings = None + _lock = threading.Lock() + def __init__(self): - self._lock = threading.Lock() self.dbapi = dbapi.get_instance() - self.hash_rings = None + + @property + def ring(self): + # Hot path, no lock + if self._hash_rings is not None: + return self._hash_rings + + with self._lock: + if self._hash_rings is None: + rings = self._load_hash_rings() + self.__class__._hash_rings = rings + return self._hash_rings def _load_hash_rings(self): rings = {} @@ -127,21 +140,14 @@ class HashRingManager(object): rings[driver_name] = HashRing(hosts) return rings - def _ensure_rings_fresh(self): - # Hot path, no lock - # TODO(russell_h): Consider adding time-based invalidation of rings - if self.hash_rings is not None: - return - + @classmethod + def reset(self): with self._lock: - if self.hash_rings is None: - self.hash_rings = self._load_hash_rings() - - def get_hash_ring(self, driver_name): - self._ensure_rings_fresh() + self._hash_rings = None + def __getitem__(self, driver_name): try: - return self.hash_rings[driver_name] + return self.ring[driver_name] except KeyError: - raise exception.DriverNotFound(_("The driver '%s' is unknown.") % - driver_name) + raise exception.DriverNotFound( + _("The driver '%s' is unknown.") % driver_name) |