def _inner_acquire(self, timeout, ephemeral=True): # wait until it's our chance to get it.. if self.is_acquired: raise ForceRetryError() # make sure our election parent node exists if not self.assured_path: yield self._ensure_path() node = None if self.create_tried: node = yield self._find_node() else: self.create_tried = True if not node: node = yield self.tornado_kazoo.create( self.create_path, self.data, ephemeral=ephemeral, sequence=True) # strip off path to node node = node[len(self.path) + 1:] self.node = node while True: self.wake_event.clear() # bail out with an exception if cancellation has been requested if self.cancelled: raise CancelledError() children = yield self._get_sorted_children() try: our_index = children.index(node) except ValueError: # pragma: nocover # somehow we aren't in the children -- probably we are # recovering from a session failure and our ephemeral # node was removed raise ForceRetryError() predecessor = self.predecessor(children, our_index) if not predecessor: raise gen.Return(True) # otherwise we are in the mix. watch predecessor and bide our time predecessor = self.path + "/" + predecessor self.client.add_listener(self._watch_session_listener) try: yield self.tornado_kazoo.get(predecessor, self._watch_predecessor) except NoNodeError: pass # predecessor has already been deleted else: try: yield self.wake_event.wait(timeout) except gen.TimeoutError: raise LockTimeout("Failed to acquire lock on %s after " "%s seconds" % (self.path, timeout)) finally: self.client.remove_listener(self._watch_session_listener)
def _get_lease(self, data=None): # Make sure the session is still valid if self._session_expired: raise ForceRetryError("Retry on session loss at top") # Make sure that the request hasn't been canceled if self.cancelled: raise CancelledError("Semaphore cancelled") # Get a list of the current potential lock holders. If they change, # notify our wake_event object. This is used to unblock a blocking # self._inner_acquire call. children = self.client.get_children(self.path, self._watch_lease_change) # If there are leases available, acquire one if len(children) < self.max_leases: self.client.create(self.create_path, self.data, ephemeral=True) # Check if our acquisition was successful or not. Update our state. if self.client.exists(self.create_path): self.is_acquired = True else: self.is_acquired = False # Return current state return self.is_acquired
def _inner_acquire(self): """Inner loop that runs from the top anytime a command hits a retryable Zookeeper exception.""" self._session_expired = False self.client.add_listener(self._watch_session) if not self.assured_path: self.client.ensure_path(self.path) # Do we already have a lease? if self.client.exists(self.create_path): return True with self.client.Lock(self.lock_path, self.data): while True: self.wake_event.clear() if self._session_expired: raise ForceRetryError("Retry on session loss at top") if self.cancelled: raise CancelledError("Semaphore cancelled") # Is there a lease free? children = self.client.get_children(self.path, self._watch_lease_change) if len(children) < self.max_leases: self.client.create(self.create_path, self.data, ephemeral=True) return True else: self.wake_event.wait()
def _inner_acquire(self, blocking, timeout): # wait until it's our chance to get it.. if self.is_acquired: if not blocking: return False raise ForceRetryError() # make sure our election parent node exists if not self.assured_path: self._ensure_path() node = None if self.create_tried: node = self._find_node() else: self.create_tried = True if not node: node = self.client.create(self.create_path, self.data, ephemeral=True, sequence=True) # strip off path to node node = node[len(self.path) + 1:] self.node = node while True: self.wake_event.clear() # bail out with an exception if cancellation has been requested if self.cancelled: raise CancelledError() children = self._get_sorted_children() try: our_index = children.index(node) except ValueError: # pragma: nocover # somehow we aren't in the children -- probably we are # recovering from a session failure and our ephemeral # node was removed raise ForceRetryError() if self.acquired_lock(children, our_index): return True if not blocking: return False # otherwise we are in the mix. watch predecessor and bide our time predecessor = self.path + "/" + children[our_index - 1] self.client.add_listener(self._watch_session) try: if self.client.exists(predecessor, self._watch_predecessor): self.wake_event.wait(timeout) if not self.wake_event.isSet(): raise LockTimeout("Failed to acquire lock on %s after " "%s seconds" % (self.path, timeout)) finally: self.client.remove_listener(self._watch_session)
def _inner_acquire(self, blocking, timeout, ephemeral=True): # wait until it's our chance to get it.. if self.is_acquired: if not blocking: return False raise ForceRetryError() # make sure our election parent node exists if not self.assured_path: self._ensure_path() node = None if self.create_tried: node = self._find_node() else: self.create_tried = True if not node: node = self.client.create(self.create_path, self.data, ephemeral=ephemeral, sequence=True) # strip off path to node node = node[len(self.path) + 1:] self.node = node while True: self.wake_event.clear() # bail out with an exception if cancellation has been requested if self.cancelled: raise CancelledError() predecessor = self._get_predecessor(node) if predecessor is None: return True if not blocking: return False # otherwise we are in the mix. watch predecessor and bide our time predecessor = self.path + "/" + predecessor self.client.add_listener(self._watch_session) try: self.client.get(predecessor, self._watch_predecessor) except NoNodeError: pass # predecessor has already been deleted else: self.wake_event.wait(timeout) if not self.wake_event.isSet(): raise LockTimeout( "Failed to acquire lock on %s after %s seconds" % (self.path, timeout)) finally: self.client.remove_listener(self._watch_session)
def _inner_acquire(self): # make sure our election parent node exists if not self.assured_path: self.client.ensure_path(self.path) node = None if self.create_tried: node = self._find_node() else: self.create_tried = True if not node: node = self.client.create(self.create_path, self.data, ephemeral=True, sequence=True) # strip off path to node node = node[len(self.path)+1:] self.node = node while True: # bail out with an exception if cancellation has been requested if self.cancelled: raise CancelledError() children = self._get_sorted_children() try: our_index = children.index(node) except ValueError: # somehow we aren't in the children -- probably we are # recovering from a session failure and our ephemeral # node was removed raise ForceRetryError() #noinspection PySimplifyBooleanCheck if our_index == 0: # we have the lock return True # otherwise we are in the mix. watch predecessor and bide our time predecessor = self.path + "/" + children[our_index-1] with self.condition: if self.client.exists(predecessor, self._watch_predecessor): self.condition.wait()
def _inner_acquire(self): """ Create contender node(s) and wait until the lock is acquired. """ # Make sure the group lock node exists. self._ensure_path() nodes = [None for _ in self.paths] if self.create_tried: nodes = self._find_nodes() else: self.create_tried = True for index, node in enumerate(nodes): if node is not None: continue # The entity group lock root may have been deleted, so try a few times. try_num = 0 while True: try: node = self.client.create(self.create_paths[index], self.data, sequence=True) break except NoNodeError: self.client.ensure_path(self.paths[index]) if try_num > 3: raise ForceRetryError() try_num += 1 # Strip off path to node. node = node[len(self.paths[index]) + 1:] nodes[index] = node self.nodes = nodes while True: self.wake_event.clear() # Bail out with an exception if cancellation has been requested. if self.cancelled: raise CancelledError() children_list = self._get_sorted_children() predecessors = [] for index, children in enumerate(children_list): try: our_index = children.index(nodes[index]) except ValueError: raise ForceRetryError() # If the lock for this group hasn't been acquired, get the predecessor. if our_index != 0: predecessors.append(self.paths[index] + "/" + children[our_index - 1]) if not predecessors: return True if len(nodes) > 1: self._resolve_deadlocks(children_list) # Wait for predecessor to be removed. # TODO: Listen for all at the same time. for index, predecessor in enumerate(predecessors): self.client.add_listener(self._watch_session) try: if self.client.exists(predecessor, self._watch_predecessor): self.wake_event.wait(LOCK_TIMEOUT) if not self.wake_event.isSet(): error = 'Failed to acquire lock on {} after {} '\ 'seconds'.format(self.paths, LOCK_TIMEOUT * (index + 1)) raise LockTimeout(error) finally: self.client.remove_listener(self._watch_session)