667
668
for value in key_dict.itervalues():
669
yield (self, ) + value
671
yield (self, ) + key_dict
672
673
def validate(self):
673
674
"""In memory index's have no known corruption at the moment."""
677
class GraphIndexPrefixAdapter(object):
678
"""An adapter between GraphIndex with different key lengths.
680
Queries against this will emit queries against the adapted Graph with the
681
prefix added, queries for all items use iter_entries_prefix. The returned
682
nodes will have their keys and node references adjusted to remove the
683
prefix. Finally, an add_nodes_callback can be supplied - when called the
684
nodes and references being added will have prefix prepended.
687
def __init__(self, adapted, prefix, missing_key_length, add_nodes_callback=None):
688
"""Construct an adapter against adapted with prefix."""
689
self.adapted = adapted
690
self.prefix = prefix + (None,)*missing_key_length
691
self.prefix_key = prefix
692
self.prefix_len = len(prefix)
693
self.add_nodes_callback = add_nodes_callback
695
def add_nodes(self, nodes):
696
"""Add nodes to the index.
698
:param nodes: An iterable of (key, node_refs, value) entries to add.
700
# save nodes in case its an iterator
702
translated_nodes = []
704
for (key, value, node_refs) in nodes:
705
adjusted_references = (
706
tuple(tuple(self.prefix_key + ref_node for ref_node in ref_list)
707
for ref_list in node_refs))
708
translated_nodes.append((self.prefix_key + key, value,
709
adjusted_references))
711
# XXX: TODO add an explicit interface for getting the reference list
712
# status, to handle this bit of user-friendliness in the API more
714
for (key, value) in nodes:
715
translated_nodes.append((self.prefix_key + key, value))
716
self.add_nodes_callback(translated_nodes)
718
def add_node(self, key, value, references=()):
719
"""Add a node to the index.
721
:param key: The key. keys are non-empty tuples containing
722
as many whitespace-free utf8 bytestrings as the key length
723
defined for this index.
724
:param references: An iterable of iterables of keys. Each is a
725
reference to another key.
726
:param value: The value to associate with the key. It may be any
727
bytes as long as it does not contain \0 or \n.
729
self.add_nodes(((key, value, references), ))
731
def _strip_prefix(self, an_iter):
732
"""Strip prefix data from nodes and return it."""
735
if node[1][:self.prefix_len] != self.prefix_key:
736
raise errors.BadIndexData(self)
737
for ref_list in node[3]:
738
for ref_node in ref_list:
739
if ref_node[:self.prefix_len] != self.prefix_key:
740
raise errors.BadIndexData(self)
741
yield node[0], node[1][self.prefix_len:], node[2], (
742
tuple(tuple(ref_node[self.prefix_len:] for ref_node in ref_list)
743
for ref_list in node[3]))
745
def iter_all_entries(self):
746
"""Iterate over all keys within the index
748
iter_all_entries is implemented against the adapted index using
751
:return: An iterable of (key, reference_lists, value). There is no
752
defined order for the result iteration - it will be in the most
753
efficient order for the index (in this case dictionary hash order).
755
return self._strip_prefix(self.adapted.iter_entries_prefix([self.prefix]))
757
def iter_entries(self, keys):
758
"""Iterate over keys within the index.
760
:param keys: An iterable providing the keys to be retrieved.
761
:return: An iterable of (key, reference_lists, value). There is no
762
defined order for the result iteration - it will be in the most
763
efficient order for the index (keys iteration order in this case).
765
return self._strip_prefix(self.adapted.iter_entries(
766
self.prefix_key + key for key in keys))
768
def iter_entries_prefix(self, keys):
769
"""Iterate over keys within the index using prefix matching.
771
Prefix matching is applied within the tuple of a key, not to within
772
the bytestring of each key element. e.g. if you have the keys ('foo',
773
'bar'), ('foobar', 'gam') and do a prefix search for ('foo', None) then
774
only the former key is returned.
776
:param keys: An iterable providing the key prefixes to be retrieved.
777
Each key prefix takes the form of a tuple the length of a key, but
778
with the last N elements 'None' rather than a regular bytestring.
779
The first element cannot be 'None'.
780
:return: An iterable as per iter_all_entries, but restricted to the
781
keys with a matching prefix to those supplied. No additional keys
782
will be returned, and every match that is in the index will be
785
return self._strip_prefix(self.adapted.iter_entries_prefix(
786
self.prefix_key + key for key in keys))
789
"""Call the adapted's validate."""
790
self.adapted.validate()