"""Module implementing the Ganeti locking code."""
-# pylint: disable-msg=W0613,W0201
+# pylint: disable-msg=W0212
+
+# W0212 since e.g. LockSet methods use (a lot) the internals of
+# SharedLock
import threading
# Wouldn't it be better to define LockingError in the locking module?
self.__nwait_shr += 1
try:
wait = False
- # If there is an exclusive holder waiting we have to wait. We'll
- # only do this once, though, when we start waiting for the lock. Then
- # we'll just wait while there are no exclusive holders.
+ # If there is an exclusive holder waiting we have to wait.
+ # We'll only do this once, though, when we start waiting for
+ # the lock. Then we'll just wait while there are no
+ # exclusive holders.
if self.__nwait_exc > 0:
# TODO: if !blocking...
wait = True
# If there are shared holders waiting (and not just scheduled to pass)
# there *must* be an exclusive holder waiting as well; otherwise what
# were they waiting for?
- assert (self.__nwait_exc > 0 or self.__npass_shr == self.__nwait_shr), \
- "Lock sharers waiting while no exclusive is queueing"
+ assert (self.__nwait_exc > 0 or
+ self.__npass_shr == self.__nwait_shr), \
+ "Lock sharers waiting while no exclusive is queueing"
# If there are no more shared holders either in or scheduled to pass,
# and some exclusive holders are waiting let's wake one up.
self.__lock.release()
-# Whenever we want to acquire a full LockSet we pass None as the value to acquire.
-# Hide this behing this nicely named constant.
+# Whenever we want to acquire a full LockSet we pass None as the value
+# to acquire. Hide this behind this nicely named constant.
ALL_SET = None
if isinstance(names, basestring):
names = [names]
else:
- names.sort()
+ names = sorted(names)
acquire_list = []
# First we look the locks up on __lockdict. We have no way of being sure
acquire_list.append((lname, lock))
except (KeyError):
if self.__lock._is_owned():
- # We are acquiring all the set, it doesn't matter if this particular
- # element is not there anymore.
+ # We are acquiring all the set, it doesn't matter if this
+ # particular element is not there anymore.
continue
else:
raise errors.LockError('non-existing lock in set (%s)' % lname)
acquired.add(lname)
except (errors.LockError):
if self.__lock._is_owned():
- # We are acquiring all the set, it doesn't matter if this particular
- # element is not there anymore.
+ # We are acquiring all the set, it doesn't matter if this
+ # particular element is not there anymore.
continue
else:
name_fail = lname
# Of course something is going to be really wrong, after this.
if lock._is_owned():
lock.release()
- raise
+ raise
except:
# If something went wrong and we had the set-lock let's release it...
class GanetiLockManager:
"""The Ganeti Locking Library
- The purpouse of this small library is to manage locking for ganeti clusters
+ The purpose of this small library is to manage locking for ganeti clusters
in a central place, while at the same time doing dynamic checks against
possible deadlocks. It will also make it easier to transition to a different
lock type should we migrate away from python threads.
# the test cases.
return utils.any((self._is_owned(l) for l in LEVELS[level + 1:]))
- def _BGL_owned(self):
+ def _BGL_owned(self): # pylint: disable-msg=C0103
"""Check if the current thread owns the BGL.
Both an exclusive or a shared acquisition work.
"""
return BGL in self.__keyring[LEVEL_CLUSTER]._list_owned()
- def _contains_BGL(self, level, names):
+ @staticmethod
+ def _contains_BGL(level, names): # pylint: disable-msg=C0103
"""Check if the level contains the BGL.
Check if acting on the given level and set of names will change
"""Acquire a set of resource locks, at the same level.
@param level: the level at which the locks shall be acquired;
- it must be a memmber of LEVELS.
+ it must be a member of LEVELS.
@param names: the names of the locks which shall be acquired
(special lock names, or instance/node names)
@param shared: whether to acquire in shared mode; by default
mode, before releasing them.
@param level: the level at which the locks shall be released;
- it must be a memmber of LEVELS
+ it must be a member of LEVELS
@param names: the names of the locks which shall be released
(defaults to all the locks acquired at that level)
"""Add locks at the specified level.
@param level: the level at which the locks shall be added;
- it must be a memmber of LEVELS_MOD.
+ it must be a member of LEVELS_MOD.
@param names: names of the locks to acquire
@param acquired: whether to acquire the newly added locks
@param shared: whether the acquisition will be shared
assert level in LEVELS_MOD, "Invalid or immutable level %s" % level
assert self._BGL_owned(), ("You must own the BGL before performing other"
" operations")
- # Check we either own the level or don't own anything from here up.
- # LockSet.remove() will check the case in which we don't own all the needed
- # resources, or we have a shared ownership.
+ # Check we either own the level or don't own anything from here
+ # up. LockSet.remove() will check the case in which we don't own
+ # all the needed resources, or we have a shared ownership.
assert self._is_owned(level) or not self._upper_owned(level), (
"Cannot remove locks at a level while not owning it or"
" owning some at a greater one")