Esempio n. 1
0
  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)
Esempio n. 2
0
    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
Esempio n. 3
0
    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()
Esempio n. 4
0
    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)
Esempio n. 5
0
    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)
Esempio n. 6
0
    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()
Esempio n. 7
0
    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)