Rev 2742: (robertc) Index layer tweaks - -Dindex and a key_count method (only accurate on low level indices). (Robert Collins). in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Wed Aug 22 05:44:34 BST 2007
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 2742
revision-id: pqm at pqm.ubuntu.com-20070822044432-tfi063jpsr3vgnao
parent: pqm at pqm.ubuntu.com-20070822024917-nw7dh478y4d8cjeg
parent: robertc at robertcollins.net-20070822041335-kdxlx0fuj6qes2cy
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2007-08-22 05:44:32 +0100
message:
(robertc) Index layer tweaks - -Dindex and a key_count method (only accurate on low level indices). (Robert Collins).
modified:
bzrlib/debug.py debug.py-20061102062349-vdhrw9qdpck8cl35-1
bzrlib/index.py index.py-20070712131115-lolkarso50vjr64s-1
bzrlib/knit.py knit.py-20051212171256-f056ac8f0fbe1bd9
bzrlib/tests/test_index.py test_index.py-20070712131115-lolkarso50vjr64s-2
------------------------------------------------------------
revno: 2624.2.19
merged: robertc at robertcollins.net-20070822041335-kdxlx0fuj6qes2cy
parent: robertc at robertcollins.net-20070822000026-kvufiqhlreokb1en
committer: Robert Collins <robertc at robertcollins.net>
branch nick: index
timestamp: Wed 2007-08-22 14:13:35 +1000
message:
Why we should always test before committing.
------------------------------------------------------------
revno: 2624.2.18
merged: robertc at robertcollins.net-20070822000026-kvufiqhlreokb1en
parent: robertc at robertcollins.net-20070808044555-10k443n441f093dx
parent: pqm at pqm.ubuntu.com-20070821175054-6pcl32ipl9eopnqw
committer: Robert Collins <robertc at robertcollins.net>
branch nick: index
timestamp: Wed 2007-08-22 10:00:26 +1000
message:
Merge bzr.dev
------------------------------------------------------------
revno: 2624.2.17
merged: robertc at robertcollins.net-20070808044555-10k443n441f093dx
parent: robertc at robertcollins.net-20070807054430-65ige2n2869mp7t4
committer: Robert Collins <robertc at robertcollins.net>
branch nick: index
timestamp: Wed 2007-08-08 14:45:55 +1000
message:
Review feedback.
------------------------------------------------------------
revno: 2624.2.16
merged: robertc at robertcollins.net-20070807054430-65ige2n2869mp7t4
parent: robertc at robertcollins.net-20070803070942-1lrseqr6ligvrtrk
committer: Robert Collins <robertc at robertcollins.net>
branch nick: index
timestamp: Tue 2007-08-07 15:44:30 +1000
message:
Add a key_count method to GraphIndex and friends, allowing optimisation of length calculations by the index.
------------------------------------------------------------
revno: 2624.2.15
merged: robertc at robertcollins.net-20070803070942-1lrseqr6ligvrtrk
parent: robertc at robertcollins.net-20070801075314-2maihdqr02hah1t3
committer: Robert Collins <robertc at robertcollins.net>
branch nick: index
timestamp: Fri 2007-08-03 17:09:42 +1000
message:
Add useful -Dindex flag.
=== modified file 'bzrlib/debug.py'
--- a/bzrlib/debug.py 2007-08-20 03:43:40 +0000
+++ b/bzrlib/debug.py 2007-08-22 00:00:26 +0000
@@ -26,6 +26,7 @@
* error - show stack traces for all top level exceptions
* hooks
* hpss - trace smart protocol requests and responses
+ * index - trace major index operations
* lock - trace when lockdir locks are taken or released
"""
=== modified file 'bzrlib/index.py'
--- a/bzrlib/index.py 2007-08-01 07:53:14 +0000
+++ b/bzrlib/index.py 2007-08-22 04:13:35 +0000
@@ -27,9 +27,14 @@
from cStringIO import StringIO
import re
-from bzrlib import errors
+from bzrlib.lazy_import import lazy_import
+lazy_import(globals(), """
+from bzrlib.trace import mutter
+""")
+from bzrlib import debug, errors
_OPTION_KEY_ELEMENTS = "key_elements="
+_OPTION_LEN = "len="
_OPTION_NODE_REFS = "node_ref_lists="
_SIGNATURE = "Bazaar Graph Index 1\n"
@@ -65,6 +70,7 @@
:param key_elements: The number of bytestrings in each key.
"""
self.reference_lists = reference_lists
+ self._keys = set()
self._nodes = {}
self._nodes_by_key = {}
self._key_length = key_elements
@@ -105,6 +111,7 @@
if key in self._nodes and self._nodes[key][0] == '':
raise errors.BadIndexDuplicateKey(key, self)
self._nodes[key] = ('', tuple(node_refs), value)
+ self._keys.add(key)
if self._key_length > 1:
key_dict = self._nodes_by_key
if self.reference_lists:
@@ -123,6 +130,7 @@
lines = [_SIGNATURE]
lines.append(_OPTION_NODE_REFS + str(self.reference_lists) + '\n')
lines.append(_OPTION_KEY_ELEMENTS + str(self._key_length) + '\n')
+ lines.append(_OPTION_LEN + str(len(self._keys)) + '\n')
prefix_length = sum(len(x) for x in lines)
# references are byte offsets. To avoid having to do nasty
# polynomial work to resolve offsets (references to later in the
@@ -232,6 +240,7 @@
self._transport = transport
self._name = name
self._nodes = None
+ self._key_count = None
self._keys_by_offset = None
self._nodes_by_key = None
@@ -240,6 +249,8 @@
Mutates self._nodes and self.keys_by_offset.
"""
+ if 'index' in debug.debug_flags:
+ mutter('Reading entire index %s', self._transport.abspath(self._name))
stream = self._transport.get(self._name)
self._read_prefix(stream)
expected_elements = 3 + self._key_length
@@ -296,6 +307,7 @@
for subkey in key[:-1]:
key_dict = key_dict.setdefault(subkey, {})
key_dict[key[-1]] = key_value
+ # cache the keys for quick set intersections
self._keys = set(self._nodes)
if trailers != 1:
# there must be one line - the empty trailer line.
@@ -337,6 +349,13 @@
self._key_length = int(options_line[len(_OPTION_KEY_ELEMENTS):-1])
except ValueError:
raise errors.BadIndexOptions(self)
+ options_line = stream.readline()
+ if not options_line.startswith(_OPTION_LEN):
+ raise errors.BadIndexOptions(self)
+ try:
+ self._key_count = int(options_line[len(_OPTION_LEN):-1])
+ except ValueError:
+ raise errors.BadIndexOptions(self)
def iter_entries(self, keys):
"""Iterate over keys within the index.
@@ -432,6 +451,16 @@
# the last thing looked up was a terminal element
yield (self, ) + key_dict
+ def key_count(self):
+ """Return an estimate of the number of keys in this index.
+
+ For GraphIndex the estimate is exact.
+ """
+ if self._key_count is None:
+ # really this should just read the prefix
+ self._buffer_all()
+ return self._key_count
+
def _signature(self):
"""The file signature for this index type."""
return _SIGNATURE
@@ -538,6 +567,16 @@
seen_keys.add(node[1])
yield node
+ def key_count(self):
+ """Return an estimate of the number of keys in this index.
+
+ For CombinedGraphIndex this is approximated by the sum of the keys of
+ the child indices. As child indices may have duplicate keys this can
+ have a maximum error of the number of child indices * largest number of
+ keys in any index.
+ """
+ return sum((index.key_count() for index in self._indices), 0)
+
def validate(self):
"""Validate that everything in the index can be accessed."""
for index in self._indices:
@@ -590,12 +629,12 @@
"""
keys = set(keys)
if self.reference_lists:
- for key in keys.intersection(self._nodes):
+ for key in keys.intersection(self._keys):
node = self._nodes[key]
if not node[0]:
yield self, key, node[2], node[1]
else:
- for key in keys.intersection(self._nodes):
+ for key in keys.intersection(self._keys):
node = self._nodes[key]
if not node[0]:
yield self, key, node[2]
@@ -635,7 +674,7 @@
if self.reference_lists:
yield self, key, node[2], node[1]
else:
- yield self ,key, node[2]
+ yield self, key, node[2]
return
for key in keys:
# sanity check
@@ -670,6 +709,13 @@
else:
yield (self, ) + key_dict
+ def key_count(self):
+ """Return an estimate of the number of keys in this index.
+
+ For InMemoryGraphIndex the estimate is exact.
+ """
+ return len(self._keys)
+
def validate(self):
"""In memory index's have no known corruption at the moment."""
@@ -684,11 +730,12 @@
nodes and references being added will have prefix prepended.
"""
- def __init__(self, adapted, prefix, missing_key_length, add_nodes_callback=None):
+ def __init__(self, adapted, prefix, missing_key_length,
+ add_nodes_callback=None):
"""Construct an adapter against adapted with prefix."""
self.adapted = adapted
- self.prefix = prefix + (None,)*missing_key_length
- self.prefix_key = prefix
+ self.prefix_key = prefix + (None,)*missing_key_length
+ self.prefix = prefix
self.prefix_len = len(prefix)
self.add_nodes_callback = add_nodes_callback
@@ -701,18 +748,20 @@
nodes = tuple(nodes)
translated_nodes = []
try:
+ # Add prefix_key to each reference node_refs is a tuple of tuples,
+ # so split it apart, and add prefix_key to the internal reference
for (key, value, node_refs) in nodes:
adjusted_references = (
- tuple(tuple(self.prefix_key + ref_node for ref_node in ref_list)
+ tuple(tuple(self.prefix + ref_node for ref_node in ref_list)
for ref_list in node_refs))
- translated_nodes.append((self.prefix_key + key, value,
+ translated_nodes.append((self.prefix + key, value,
adjusted_references))
except ValueError:
# XXX: TODO add an explicit interface for getting the reference list
# status, to handle this bit of user-friendliness in the API more
# explicitly.
for (key, value) in nodes:
- translated_nodes.append((self.prefix_key + key, value))
+ translated_nodes.append((self.prefix + key, value))
self.add_nodes_callback(translated_nodes)
def add_node(self, key, value, references=()):
@@ -732,11 +781,11 @@
"""Strip prefix data from nodes and return it."""
for node in an_iter:
# cross checks
- if node[1][:self.prefix_len] != self.prefix_key:
+ if node[1][:self.prefix_len] != self.prefix:
raise errors.BadIndexData(self)
for ref_list in node[3]:
for ref_node in ref_list:
- if ref_node[:self.prefix_len] != self.prefix_key:
+ if ref_node[:self.prefix_len] != self.prefix:
raise errors.BadIndexData(self)
yield node[0], node[1][self.prefix_len:], node[2], (
tuple(tuple(ref_node[self.prefix_len:] for ref_node in ref_list)
@@ -752,7 +801,7 @@
defined order for the result iteration - it will be in the most
efficient order for the index (in this case dictionary hash order).
"""
- return self._strip_prefix(self.adapted.iter_entries_prefix([self.prefix]))
+ return self._strip_prefix(self.adapted.iter_entries_prefix([self.prefix_key]))
def iter_entries(self, keys):
"""Iterate over keys within the index.
@@ -763,7 +812,7 @@
efficient order for the index (keys iteration order in this case).
"""
return self._strip_prefix(self.adapted.iter_entries(
- self.prefix_key + key for key in keys))
+ self.prefix + key for key in keys))
def iter_entries_prefix(self, keys):
"""Iterate over keys within the index using prefix matching.
@@ -783,7 +832,15 @@
returned.
"""
return self._strip_prefix(self.adapted.iter_entries_prefix(
- self.prefix_key + key for key in keys))
+ self.prefix + key for key in keys))
+
+ def key_count(self):
+ """Return an estimate of the number of keys in this index.
+
+ For GraphIndexPrefixAdapter this is relatively expensive - key
+ iteration with the prefix is done.
+ """
+ return len(list(self.iter_all_entries()))
def validate(self):
"""Call the adapted's validate."""
=== modified file 'bzrlib/knit.py'
--- a/bzrlib/knit.py 2007-08-17 08:38:23 +0000
+++ b/bzrlib/knit.py 2007-08-22 00:00:26 +0000
@@ -97,7 +97,6 @@
RevisionAlreadyPresent,
)
from bzrlib.tuned_gzip import GzipFile
-from bzrlib.trace import mutter
from bzrlib.osutils import (
contains_whitespace,
contains_linebreaks,
=== modified file 'bzrlib/tests/test_index.py'
--- a/bzrlib/tests/test_index.py 2007-08-01 07:53:14 +0000
+++ b/bzrlib/tests/test_index.py 2007-08-08 04:45:55 +0000
@@ -27,32 +27,41 @@
builder = GraphIndexBuilder()
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\n\n", contents)
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=0\n\n",
+ contents)
def test_build_index_empty_two_element_keys(self):
builder = GraphIndexBuilder(key_elements=2)
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\n\n", contents)
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=0\n\n",
+ contents)
def test_build_index_one_reference_list_empty(self):
builder = GraphIndexBuilder(reference_lists=1)
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\n\n", contents)
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=0\n\n",
+ contents)
def test_build_index_two_reference_list_empty(self):
builder = GraphIndexBuilder(reference_lists=2)
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\n\n", contents)
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=0\n\n",
+ contents)
def test_build_index_one_node_no_refs(self):
builder = GraphIndexBuilder()
builder.add_node(('akey', ), 'data')
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
"akey\x00\x00\x00data\n\n", contents)
def test_build_index_one_node_no_refs_accepts_empty_reflist(self):
@@ -60,7 +69,8 @@
builder.add_node(('akey', ), 'data', ())
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
"akey\x00\x00\x00data\n\n", contents)
def test_build_index_one_node_2_element_keys(self):
@@ -71,7 +81,8 @@
builder.add_node(('akey', 'secondpart'), 'data')
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=1\n"
"akey\x00secondpart\x00\x00\x00data\n\n", contents)
def test_add_node_empty_value(self):
@@ -79,7 +90,8 @@
builder.add_node(('akey', ), '')
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
"akey\x00\x00\x00\n\n", contents)
def test_build_index_nodes_sorted(self):
@@ -93,7 +105,8 @@
builder.add_node(('2001', ), 'data')
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=3\n"
"2000\x00\x00\x00data\n"
"2001\x00\x00\x00data\n"
"2002\x00\x00\x00data\n"
@@ -116,7 +129,8 @@
builder.add_node(('2001', '2001'), 'data')
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=9\n"
"2000\x002000\x00\x00\x00data\n"
"2000\x002001\x00\x00\x00data\n"
"2000\x002002\x00\x00\x00data\n"
@@ -133,7 +147,8 @@
builder.add_node(('key', ), 'data', ([], ))
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
"key\x00\x00\x00data\n"
"\n", contents)
@@ -142,7 +157,8 @@
builder.add_node(('key', 'key2'), 'data', ([], ))
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=2\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=2\nlen=1\n"
"key\x00key2\x00\x00\x00data\n"
"\n", contents)
@@ -151,7 +167,8 @@
builder.add_node(('key', ), 'data', ([], []))
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=1\n"
"key\x00\x00\t\x00data\n"
"\n", contents)
@@ -161,8 +178,9 @@
builder.add_node(('key', ), 'data', ([('reference', )], ))
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\n"
- "key\x00\x0066\x00data\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=2\n"
+ "key\x00\x0072\x00data\n"
"reference\x00\x00\x00data\n"
"\n", contents)
@@ -173,8 +191,9 @@
builder.add_node(('key', ), 'data', ([('reference', ), ('reference2', )], ))
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\n"
- "key\x00\x00071\r088\x00data\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=3\n"
+ "key\x00\x00077\r094\x00data\n"
"reference\x00\x00\x00data\n"
"reference2\x00\x00\x00data\n"
"\n", contents)
@@ -185,9 +204,10 @@
builder.add_node(('rey', ), 'data', ([('keference', )], [('keference', )]))
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=2\n"
"keference\x00\x00\t\x00data\n"
- "rey\x00\x0053\t53\x00data\n"
+ "rey\x00\x0059\t59\x00data\n"
"\n", contents)
def test_add_node_referencing_missing_key_makes_absent(self):
@@ -195,10 +215,11 @@
builder.add_node(('rey', ), 'data', ([('beference', ), ('aeference2', )], ))
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
"aeference2\x00a\x00\x00\n"
"beference\x00a\x00\x00\n"
- "rey\x00\x0068\r53\x00data\n"
+ "rey\x00\x00074\r059\x00data\n"
"\n", contents)
def test_node_references_three_digits(self):
@@ -208,11 +229,12 @@
builder.add_node(('2-key', ), '', (references, ))
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
"0\x00a\x00\x00\n"
"1\x00a\x00\x00\n"
"2\x00a\x00\x00\n"
- "2-key\x00\x00145\r139\r133\r127\r121\r115\r065\r059\r053\x00\n"
+ "2-key\x00\x00151\r145\r139\r133\r127\r121\r071\r065\r059\x00\n"
"3\x00a\x00\x00\n"
"4\x00a\x00\x00\n"
"5\x00a\x00\x00\n"
@@ -228,9 +250,10 @@
builder.add_node(('parent', ), '', ([('aail', ), ('zther', )], []))
stream = builder.finish()
contents = stream.read()
- self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\n"
+ self.assertEqual(
+ "Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=1\n"
"aail\x00a\x00\x00\n"
- "parent\x00\x0053\r78\t\x00\n"
+ "parent\x00\x0059\r84\t\x00\n"
"zther\x00a\x00\x00\n"
"\n", contents)
@@ -331,8 +354,8 @@
def make_index(self, ref_lists=0, key_elements=1, nodes=[]):
builder = GraphIndexBuilder(ref_lists, key_elements=key_elements)
- for node, value, references in nodes:
- builder.add_node(node, value, references)
+ for key, value, references in nodes:
+ builder.add_node(key, value, references)
stream = builder.finish()
trans = self.get_transport()
trans.put_file('index', stream)
@@ -455,6 +478,19 @@
(index, ('name', 'fin2'), 'beta', ((), ))]),
set(index.iter_entries_prefix([('name', None)])))
+ def test_key_count_empty(self):
+ index = self.make_index()
+ self.assertEqual(0, index.key_count())
+
+ def test_key_count_one(self):
+ index = self.make_index(nodes=[(('name', ), '', ())])
+ self.assertEqual(1, index.key_count())
+
+ def test_key_count_two(self):
+ index = self.make_index(nodes=[
+ (('name', ), '', ()), (('foo', ), '', ())])
+ self.assertEqual(2, index.key_count())
+
def test_validate_bad_index_errors(self):
trans = self.get_transport()
trans.put_bytes('name', "not an index\n")
@@ -499,8 +535,8 @@
def make_index(self, name, ref_lists=0, key_elements=1, nodes=[]):
builder = GraphIndexBuilder(ref_lists, key_elements=key_elements)
- for node, value, references in nodes:
- builder.add_node(node, value, references)
+ for key, value, references in nodes:
+ builder.add_node(key, value, references)
stream = builder.finish()
trans = self.get_transport()
trans.put_file(name, stream)
@@ -624,6 +660,20 @@
self.assertEqual([(index1, ('key', ), '')],
list(index.iter_entries([('key', )])))
+ def test_key_count_empty(self):
+ index1 = self.make_index('1', nodes=[])
+ index2 = self.make_index('2', nodes=[])
+ index = CombinedGraphIndex([index1, index2])
+ self.assertEqual(0, index.key_count())
+
+ def test_key_count_sums_index_keys(self):
+ index1 = self.make_index('1', nodes=[
+ (('1',), '', ()),
+ (('2',), '', ())])
+ index2 = self.make_index('2', nodes=[(('1',), '', ())])
+ index = CombinedGraphIndex([index1, index2])
+ self.assertEqual(3, index.key_count())
+
def test_validate_bad_child_index_errors(self):
trans = self.get_transport()
trans.put_bytes('name', "not an index\n")
@@ -745,6 +795,18 @@
index = self.make_index()
self.assertEqual([], list(index.iter_entries(['a'])))
+ def test_key_count_empty(self):
+ index = self.make_index()
+ self.assertEqual(0, index.key_count())
+
+ def test_key_count_one(self):
+ index = self.make_index(nodes=[(('name', ), '')])
+ self.assertEqual(1, index.key_count())
+
+ def test_key_count_two(self):
+ index = self.make_index(nodes=[(('name', ), ''), (('foo', ), '')])
+ self.assertEqual(2, index.key_count())
+
def test_validate_empty(self):
index = self.make_index()
index.validate()
@@ -760,9 +822,9 @@
result = InMemoryGraphIndex(ref_lists, key_elements=key_elements)
result.add_nodes(nodes)
if add_callback:
- add_nodes_callback=result.add_nodes
+ add_nodes_callback = result.add_nodes
else:
- add_nodes_callback=None
+ add_nodes_callback = None
adapter = GraphIndexPrefixAdapter(result, ('prefix', ), key_elements - 1,
add_nodes_callback=add_nodes_callback)
return result, adapter
@@ -833,6 +895,18 @@
(index, ('prefix2', 'key2', ), 'data2', ((('prefix2', 'key1', ),),))]),
set(adapter.iter_entries_prefix([('prefix2', None)])))
+ def test_key_count_no_matching_keys(self):
+ index, adapter = self.make_index(nodes=[
+ (('notprefix', 'key1'), 'data', ((), ))])
+ self.assertEqual(0, adapter.key_count())
+
+ def test_key_count_some_keys(self):
+ index, adapter = self.make_index(nodes=[
+ (('notprefix', 'key1'), 'data', ((), )),
+ (('prefix', 'key1'), 'data1', ((), )),
+ (('prefix', 'key2'), 'data2', ((('prefix', 'key1'),),))])
+ self.assertEqual(2, adapter.key_count())
+
def test_validate(self):
index, adapter = self.make_index()
calls = []
More information about the bazaar-commits
mailing list