Rev 12: Write a helper function that can turn 2 lists of keys into a position list. in http://bzr.arbash-meinel.com/plugins/index2
John Arbash Meinel
john at arbash-meinel.com
Wed Jul 2 00:12:12 BST 2008
At http://bzr.arbash-meinel.com/plugins/index2
------------------------------------------------------------
revno: 12
revision-id: john at arbash-meinel.com-20080701231134-73vr4qkr6dogf3h0
parent: john at arbash-meinel.com-20080701192734-9mbeqa4zszat3z1f
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: index2
timestamp: Tue 2008-07-01 18:11:34 -0500
message:
Write a helper function that can turn 2 lists of keys into a position list.
-------------- next part --------------
=== modified file 'btree_index.py'
--- a/btree_index.py 2008-07-01 19:27:34 +0000
+++ b/btree_index.py 2008-07-01 23:11:34 +0000
@@ -354,6 +354,57 @@
for key, (value, refs) in node.keys.items():
yield (self, key, value)
+ @staticmethod
+ def _positions_for_keys(in_keys, fixed_keys):
+ """Find the positions where each 'in_key' would fit in fixed_keys.
+
+ This is equivalent to doing "bisect_right" on each in_key into
+ fixed_keys
+
+ :param in_keys: A sorted list of keys to match with fixed_keys
+ :param fixed_keys: A sorted list of keys to match against
+ :return: A list of integer positions.
+ """
+ if not in_keys:
+ return []
+ if not fixed_keys:
+ raise AssertionError('we must have entries in fixed_keys')
+ in_keys_iter = iter(in_keys)
+ fixed_keys_iter = enumerate(fixed_keys)
+ cur_in_key = in_keys_iter.next()
+ cur_fixed_offset, cur_fixed_key = fixed_keys_iter.next()
+
+ class InputDone(Exception): pass
+ class FixedDone(Exception): pass
+
+ output = []
+
+ try:
+ while True:
+ if cur_in_key < cur_fixed_key:
+ output.append(cur_fixed_offset)
+ while cur_in_key < cur_fixed_key:
+ try:
+ cur_in_key = in_keys_iter.next()
+ except StopIteration:
+ raise InputDone
+ # At this point cur_in_key must be >= cur_fixed_key
+ # step the cur_fixed_key until we pass the cur key, or walk off
+ # the end
+ while cur_in_key >= cur_fixed_key:
+ try:
+ cur_fixed_offset, cur_fixed_key = fixed_keys_iter.next()
+ except StopIteration:
+ raise FixedDone
+ except InputDone:
+ # We consumed all of the input, nothing more to do
+ pass
+ except FixedDone:
+ # There was some input left, but we consumed all of fixed, so we
+ # have to add one more for the tail
+ output.append(len(fixed_keys))
+ return output
+
def iter_entries(self, keys):
"""Iterate over keys within the index.
@@ -369,6 +420,13 @@
self._cache_nodes([0])
if not self._key_count:
return
+ node = self._get_node(0)
+ for row_length in self._row_lengths:
+ next_nodes = []
+
+ # Split up the keys based on which nodes will work best next
+ # Both the node keys and are internal list are both sorted, so we
+ # just step both of them to find the right locations.
for key in keys:
# repeated single-bisection : 'make it work'
# FUTURE: look within the current node for the next key,
=== modified file 'tests/test_btree_index.py'
--- a/tests/test_btree_index.py 2008-07-01 09:51:16 +0000
+++ b/tests/test_btree_index.py 2008-07-01 23:11:34 +0000
@@ -19,6 +19,7 @@
import zlib
+from bzrlib import tests
from bzrlib.plugins import index2
from bzrlib.plugins.index2 import errors, btree_index
from bzrlib.tests import TestCaseWithTransport
@@ -1116,3 +1117,32 @@
('11', '44'): ('value:4', ((), (('11', 'ref00'),)))
}, node.keys)
+
+class TestPositionsForKeys(tests.TestCase):
+
+ def assertPositionsForKeys(self, offsets, search_keys, fixed_keys):
+ self.assertEqual(offsets,
+ btree_index.BTreeGraphIndex._positions_for_keys(
+ search_keys, fixed_keys))
+
+ def test_after(self):
+ self.assertPositionsForKeys([1], ['b'], ['a'])
+ self.assertPositionsForKeys([3], ['e', 'f', 'g'], ['a', 'b', 'c'])
+
+ def test_before(self):
+ self.assertPositionsForKeys([0], ['a'], ['b'])
+ self.assertPositionsForKeys([0], ['a', 'b', 'c', 'd'], ['e', 'f', 'g'])
+
+ def test_exact(self):
+ self.assertPositionsForKeys([1], ['a'], ['a'])
+ self.assertPositionsForKeys([1, 2], ['a', 'b'], ['a', 'b'])
+ self.assertPositionsForKeys([1, 3], ['a', 'c'], ['a', 'b', 'c'])
+
+ def test_inbetween(self):
+ self.assertPositionsForKeys([1], ['b'], ['a', 'c'])
+ self.assertPositionsForKeys([1, 2], ['b', 'c', 'd', 'f', 'g'],
+ ['a', 'e', 'h'])
+
+ def test_mixed(self):
+ self.assertPositionsForKeys([0, 2, 4], ['a', 'b', 'd', 'e', 'g', 'h'],
+ ['c', 'd', 'f', 'g'])
More information about the bazaar-commits
mailing list