示例#1
0
class IndexIterator(object):
  """
  Returns pages of index entry results. It ignores Key-Values that do not apply
  to the given read_versionstamp. It converts usable Key-Values to IndexEntry
  objects.
  """
  def __init__(self, tr, tornado_fdb, index, key_slice, fetch_limit, reverse,
               read_versionstamp=None, snapshot=False):
    self.index = index
    self._result_iterator = ResultIterator(
      tr, tornado_fdb, key_slice, fetch_limit, reverse, snapshot=snapshot)
    self._read_versionstamp = read_versionstamp
    self._done = False

  @property
  def prop_names(self):
    return self.index.prop_names

  @property
  def start_key(self):
    return self._result_iterator.slice.start.key

  @gen.coroutine
  def next_page(self):
    if self._done:
      raise gen.Return(([], False))

    results, more_results = yield self._result_iterator.next_page()
    usable_entries = []
    for result in results:
      entry = self.index.decode(result)
      if not self._usable(entry):
        self._result_iterator.increase_limit()
        more_results = not self._result_iterator.done_with_range
        continue

      usable_entries.append(entry)

    if not more_results:
      self._done = True

    raise gen.Return((usable_entries, more_results))

  def _usable(self, entry):
    if self._read_versionstamp and entry.deleted_versionstamp:
      return (entry.commit_versionstamp < self._read_versionstamp <
              entry.deleted_versionstamp)
    elif self._read_versionstamp:
      return entry.commit_versionstamp < self._read_versionstamp
    else:
      return entry.deleted_versionstamp is None
示例#2
0
    def _groom_range(self, tr, index, byte_num, safe_versionstamp,
                     tx_deadline):
        iterator = ResultIterator(tr, self._tornado_fdb,
                                  index.get_slice(byte_num, safe_versionstamp))
        deleted = 0
        while True:
            results, more = yield iterator.next_page()
            for result in results:
                index_entry = index.decode(result)
                version_entry = yield self._data_manager.get_version_from_path(
                    tr, index_entry.project_id, index_entry.namespace,
                    index_entry.path, index_entry.original_versionstamp)
                yield self._hard_delete(tr, version_entry,
                                        index_entry.deleted_versionstamp)
                deleted += 1

            if not more or monotonic.monotonic() > tx_deadline:
                break

        raise gen.Return(deleted)