X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/d4f4b3e763cf53d4718521d22c3651cbb3f349a1..c9d443ea4ab1a6c031306afe95f5e9e92d61d693:/lib/locking.py diff --git a/lib/locking.py b/lib/locking.py index f359678..647e14f 100644 --- a/lib/locking.py +++ b/lib/locking.py @@ -104,11 +104,10 @@ class SharedLock: def _is_owned(self, shared=-1): """Is the current thread somehow owning the lock at this time? - Args: - shared: - < 0: check for any type of ownership (default) - 0: check for exclusive ownership - > 0: check for shared ownership + @param shared: + - < 0: check for any type of ownership (default) + - 0: check for exclusive ownership + - > 0: check for shared ownership """ self.__lock.acquire() @@ -123,8 +122,7 @@ class SharedLock: """Wait on the given condition, and raise an exception if the current lock is declared deleted in the meantime. - Args: - c: condition to wait on + @param c: the condition to wait on """ c.wait() @@ -158,11 +156,10 @@ class SharedLock: def acquire(self, blocking=1, shared=0): """Acquire a shared lock. - Args: - shared: whether to acquire in shared mode. By default an exclusive lock - will be acquired. - blocking: whether to block while trying to acquire or to operate in - try-lock mode. this locking mode is not supported yet. + @param shared: whether to acquire in shared mode; by default an + exclusive lock will be acquired + @param blocking: whether to block while trying to acquire or to + operate in try-lock mode (this locking mode is not supported yet) """ if not blocking: @@ -182,9 +179,10 @@ class SharedLock: 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 @@ -245,8 +243,9 @@ class SharedLock: # 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. @@ -268,10 +267,9 @@ class SharedLock: acquired in exclusive mode if you don't already own it, then the lock will be put in a state where any future and pending acquire() fail. - Args: - blocking: whether to block while trying to acquire or to operate in - try-lock mode. this locking mode is not supported yet unless - you are already holding exclusively the lock. + @param blocking: whether to block while trying to acquire or to + operate in try-lock mode. this locking mode is not supported + yet unless you are already holding exclusively the lock. """ self.__lock.acquire() @@ -298,8 +296,8 @@ class SharedLock: 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 behing this nicely named constant. ALL_SET = None @@ -317,8 +315,7 @@ class LockSet: def __init__(self, members=None): """Constructs a new LockSet. - Args: - members: initial members of the set + @param members: initial members of the set """ # Used internally to guarantee coherency. @@ -406,21 +403,18 @@ class LockSet: def acquire(self, names, blocking=1, shared=0): """Acquire a set of resource locks. - Args: - names: the names of the locks which shall be acquired. - (special lock names, or instance/node names) - shared: whether to acquire in shared mode. By default an exclusive lock - will be acquired. - blocking: whether to block while trying to acquire or to operate in - try-lock mode. this locking mode is not supported yet. + @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 an + exclusive lock will be acquired + @param blocking: whether to block while trying to acquire or to + operate in try-lock mode (this locking mode is not supported yet) - Returns: - True: when all the locks are successfully acquired + @return: True when all the locks are successfully acquired - Raises: - errors.LockError: when any lock we try to acquire has been deleted - before we succeed. In this case none of the locks requested will be - acquired. + @raise errors.LockError: when any lock we try to acquire has + been deleted before we succeed. In this case none of the + locks requested will be acquired. """ if not blocking: @@ -457,7 +451,7 @@ class LockSet: 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 @@ -469,8 +463,8 @@ class LockSet: 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) @@ -489,8 +483,8 @@ class LockSet: 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 @@ -520,9 +514,8 @@ class LockSet: You must have acquired the locks, either in shared or in exclusive mode, before releasing them. - Args: - names: the names of the locks which shall be released. - (defaults to all the locks acquired at that level). + @param names: the names of the locks which shall be released + (defaults to all the locks acquired at that level). """ assert self._is_owned(), "release() on lock set while not owner" @@ -554,21 +547,20 @@ class LockSet: def add(self, names, acquired=0, shared=0): """Add a new set of elements to the set - Args: - names: names of the new elements to add - acquired: pre-acquire the new resource? - shared: is the pre-acquisition shared? + @param names: names of the new elements to add + @param acquired: pre-acquire the new resource? + @param shared: is the pre-acquisition shared? """ - - assert not self.__lock._is_owned(shared=1), ( - "Cannot add new elements while sharing the set-lock") + # Check we don't already own locks at this level + assert not self._is_owned() or self.__lock._is_owned(shared=0), \ + "Cannot add locks if the set is only partially owned, or shared" # Support passing in a single resource to add rather than many if isinstance(names, basestring): names = [names] - # If we don't already own the set-level lock acquire it in an exclusive way + # If we don't already own the set-level lock acquired in an exclusive way # we'll get it and note we need to release it later. release_lock = False if not self.__lock._is_owned(): @@ -616,15 +608,14 @@ class LockSet: You can either not hold anything in the lockset or already hold a superset of the elements you want to delete, exclusively. - Args: - names: names of the resource to remove. - blocking: whether to block while trying to acquire or to operate in - try-lock mode. this locking mode is not supported yet unless - you are already holding exclusively the locks. + @param names: names of the resource to remove. + @param blocking: whether to block while trying to acquire or to + operate in try-lock mode (this locking mode is not supported + yet unless you are already holding exclusively the locks) - Returns: - A list of lock which we removed. The list is always equal to the names - list if we were holding all the locks exclusively. + @return:: a list of locks which we removed; the list is always + equal to the names list if we were holding all the locks + exclusively """ if not blocking and not self._is_owned(): @@ -712,12 +703,13 @@ class GanetiLockManager: There should be only a GanetiLockManager object at any time, so this function raises an error if this is not the case. - Args: - nodes: list of node names - instances: list of instance names + @param nodes: list of node names + @param instances: list of instance names """ - assert self.__class__._instance is None, "double GanetiLockManager instance" + assert self.__class__._instance is None, \ + "double GanetiLockManager instance" + self.__class__._instance = self # The keyring contains all the locks, at their level and in the correct @@ -730,10 +722,10 @@ class GanetiLockManager: def _names(self, level): """List the lock names at the given level. - Used for debugging/testing purposes. - Args: - level: the level whose list of locks to get + This can be used for debugging/testing purposes. + + @param level: the level whose list of locks to get """ assert level in LEVELS, "Invalid locking level %s" % level @@ -770,8 +762,10 @@ class GanetiLockManager: return BGL in self.__keyring[LEVEL_CLUSTER]._list_owned() def _contains_BGL(self, level, names): - """Check if acting on the given level and set of names will change the - status of the Big Ganeti Lock. + """Check if the level contains the BGL. + + Check if acting on the given level and set of names will change + the status of the Big Ganeti Lock. """ return level == LEVEL_CLUSTER and (names is None or BGL in names) @@ -779,15 +773,14 @@ class GanetiLockManager: def acquire(self, level, names, blocking=1, shared=0): """Acquire a set of resource locks, at the same level. - Args: - level: the level at which the locks shall be acquired. - It must be a memmber of LEVELS. - names: the names of the locks which shall be acquired. - (special lock names, or instance/node names) - shared: whether to acquire in shared mode. By default an exclusive lock - will be acquired. - blocking: whether to block while trying to acquire or to operate in - try-lock mode. this locking mode is not supported yet. + @param level: the level at which the locks shall be acquired; + it must be a memmber 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 + an exclusive lock will be acquired + @param blocking: whether to block while trying to acquire or to + operate in try-lock mode (this locking mode is not supported yet) """ assert level in LEVELS, "Invalid locking level %s" % level @@ -812,14 +805,13 @@ class GanetiLockManager: def release(self, level, names=None): """Release a set of resource locks, at the same level. - You must have acquired the locks, either in shared or in exclusive mode, - before releasing them. + You must have acquired the locks, either in shared or in exclusive + mode, before releasing them. - Args: - level: the level at which the locks shall be released. - It must be a memmber of LEVELS. - names: the names of the locks which shall be released. - (defaults to all the locks acquired at that level). + @param level: the level at which the locks shall be released; + it must be a memmber of LEVELS + @param names: the names of the locks which shall be released + (defaults to all the locks acquired at that level) """ assert level in LEVELS, "Invalid locking level %s" % level @@ -834,12 +826,12 @@ class GanetiLockManager: def add(self, level, names, acquired=0, shared=0): """Add locks at the specified level. - Args: - level: the level at which the locks shall be added. - It must be a memmber of LEVELS_MOD. - names: names of the locks to acquire - acquired: whether to acquire the newly added locks - shared: whether the acquisition will be shared + @param level: the level at which the locks shall be added; + it must be a memmber 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" @@ -851,24 +843,23 @@ class GanetiLockManager: def remove(self, level, names, blocking=1): """Remove locks from the specified level. - You must either already own the locks you are trying to remove exclusively - or not own any lock at an upper level. + You must either already own the locks you are trying to remove + exclusively or not own any lock at an upper level. - Args: - level: the level at which the locks shall be removed. - It must be a memmber of LEVELS_MOD. - names: the names of the locks which shall be removed. - (special lock names, or instance/node names) - blocking: whether to block while trying to operate in try-lock mode. - this locking mode is not supported yet. + @param level: the level at which the locks shall be removed; + it must be a member of LEVELS_MOD + @param names: the names of the locks which shall be removed + (special lock names, or instance/node names) + @param blocking: whether to block while trying to operate in + try-lock mode (this locking mode is not supported yet) """ 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")