Exemplo n.º 1
0
    def seek(self, key_prefix: bytes, direction="forward"
             ) -> Iterator[Tuple[storage.StorageKey, storage.StorageItem]]:
        """
        Find all data starting with a prefix.

        Args:
            key_prefix: the prefix the data must have
            direction: determines the database search order. Can be "forward" or "reverse"

        Returns:
            An iterator with the results

        See Also:
            * :func:`~neo3.storage.cache.CachedStorageAccess.find_range`

        """
        # always read only
        comperator = storage.NEOByteCompare(direction)

        cached: List[Tuple[storage.StorageKey, storage.StorageItem]] = []
        cached_keys: List[storage.StorageKey] = []
        for key, value in self._dictionary.items():
            if value.state != TrackState.DELETED and (
                    len(key_prefix) == 0 or comperator.compare(key.to_array(), key_prefix) >= 0):
                cached.append((key, value.item))
                cached_keys.append(key)

        if direction == "forward":
            cached_sorted = sorted(cached, key=lambda pair: pair[0].to_array())
        else:
            cached_sorted = sorted(cached, key=lambda pair: pair[0].to_array(), reverse=True)

        e1 = _Enumerator(iter(cached_sorted))
        e2 = _Enumerator(self._internal_seek(key_prefix, direction))

        c1 = e1.move_next()
        c2 = e2.move_next()

        i1 = e1.current()
        i2 = e2.current()

        comperator = storage.NEOByteCompare(direction)

        while c1 or c2:
            # filter out duplicates from internal if already found in cached
            if c2 and i2[0] in cached_keys:
                c2 = e2.move_next()
                i2 = e2.current()
            elif not c2 or (c1 and comperator.compare(i1[0].to_array(), i2[0].to_array()) < 0):
                # i1 values come from the cache by reference, make them "read-only"
                yield deepcopy(i1[0]), deepcopy(i1[1])
                c1 = e1.move_next()
                i1 = e1.current()
            else:
                # i2 values are new objects deserialized from storage (in the case of leveldb)
                yield i2[0], i2[1]
                c2 = e2.move_next()
                i2 = e2.current()
Exemplo n.º 2
0
    def seek(
        self,
        key_prefix: bytes,
        direction="forward"
    ) -> Iterator[Tuple[storage.StorageKey, storage.StorageItem]]:
        # always read only
        comperator = storage.NEOByteCompare(direction)

        cached: List[Tuple[storage.StorageKey, storage.StorageItem]] = []
        cached_keys: List[storage.StorageKey] = []
        for key, value in self._dictionary.items():
            if value.state != TrackState.DELETED and (
                    len(key_prefix) == 0
                    or comperator.compare(key.to_array(), key_prefix) >= 0):
                cached.append((key, value.item))
                cached_keys.append(key)

        if direction == "forward":
            cached_sorted = sorted(cached, key=lambda pair: pair[0].to_array())
        else:
            cached_sorted = sorted(cached,
                                   key=lambda pair: pair[0].to_array(),
                                   reverse=True)

        e1 = _Enumerator(iter(cached_sorted))
        e2 = _Enumerator(self._internal_seek(key_prefix, direction))

        c1 = e1.move_next()
        c2 = e2.move_next()

        i1 = e1.current()
        i2 = e2.current()

        comperator = storage.NEOByteCompare(direction)

        while c1 or c2:
            # filter out duplicates from internal if already found in cached
            if c2 and i2[0] in cached_keys:
                c2 = e2.move_next()
                i2 = e2.current()
            elif not c2 or (c1 and comperator.compare(i1[0].to_array(),
                                                      i2[0].to_array()) < 0):
                # i1 values come from the cache by reference, make them "read-only"
                yield deepcopy(i1[0]), deepcopy(i1[1])
                c1 = e1.move_next()
                i1 = e1.current()
            else:
                # i2 values are new objects deserialized from storage (in the case of leveldb)
                yield i2[0], i2[1]
                c2 = e2.move_next()
                i2 = e2.current()
Exemplo n.º 3
0
    def find_range(self,
                   start: bytes,
                   end: bytes,
                   direction: str = "forward"
                   ) -> Iterator[Tuple[storage.StorageKey, storage.StorageItem]]:
        """
        Find all data within a given range.

        Args:
            start: the data prefix to start from
            end: the post fix to end the search results at
            direction: determines the database search order. Can be "forward" or "reverse"

        Returns:
            An iterator with the results

        See Also:
            * :func:`~neo3.storage.cache.CachedStorageAccess.seek`
        """
        comperator = storage.NEOByteCompare(direction)
        for key, value in self.seek(start, direction):
            if comperator.compare(key.to_array(), end) < 0:
                yield key, value
            else:
                return None
Exemplo n.º 4
0
 def test_forward(self):
     comperator = storage.NEOByteCompare("forward")
     self.assertEqual(-1, comperator.compare(b'\x00', b'\x01'))
     self.assertEqual(0, comperator.compare(b'\x01', b'\x01'))
     self.assertEqual(1, comperator.compare(b'\x02', b'\x01'))
     self.assertEqual(-1, comperator.compare(b'\x01', b'\x02'))
     self.assertEqual(1, comperator.compare(b'\x01\x01', b'\x01'))
     self.assertEqual(1, comperator.compare(b'\xff', b'\x01'))
     self.assertEqual(-1, comperator.compare(b'\xf9', b'\xfb'))
     self.assertEqual(1, comperator.compare(b'\xf9\xff\xff\xff\x09', b'\x01\x00\x00\x00\x01'))
     self.assertEqual(1, comperator.compare(b'\x01\x00\x00\x00\x01\x02', b'\x01\x00\x00\x00\x01'))
Exemplo n.º 5
0
 def find_range(
     self,
     start: bytes,
     end: bytes,
     direction: str = "forward"
 ) -> Iterator[Tuple[storage.StorageKey, storage.StorageItem]]:
     comperator = storage.NEOByteCompare(direction)
     for key, value in self.seek(start, direction):
         if comperator.compare(key.to_array(), end) < 0:
             yield key, value
         else:
             return None