Rev 3378: Create a StackedKnitAccess object to permit combining access objects for knits. in http://people.ubuntu.com/~robertc/baz2.0/shallow-branch
Robert Collins
robertc at robertcollins.net
Tue Jun 17 04:56:15 BST 2008
At http://people.ubuntu.com/~robertc/baz2.0/shallow-branch
------------------------------------------------------------
revno: 3378
revision-id: robertc at robertcollins.net-20080617035603-2s1yg68n3jrgglxp
parent: robertc at robertcollins.net-20080612032525-hp52uf3wa7546c4u
committer: Robert Collins <robertc at robertcollins.net>
branch nick: stacking-knits
timestamp: Tue 2008-06-17 13:56:03 +1000
message:
Create a StackedKnitAccess object to permit combining access objects for knits.
modified:
bzrlib/knit.py knit.py-20051212171256-f056ac8f0fbe1bd9
bzrlib/tests/test_knit.py test_knit.py-20051212171302-95d4c00dd5f11f2b
=== modified file 'bzrlib/knit.py'
--- a/bzrlib/knit.py 2008-06-11 07:22:00 +0000
+++ b/bzrlib/knit.py 2008-06-17 03:56:03 +0000
@@ -2264,6 +2264,81 @@
self._write_index = index
+class StackedAccess(object):
+ """Access to records in multiple access objects."""
+
+ def __init__(self, backends):
+ """Create a StackedAccess object.
+
+ :param backends: A dict of backends to query. This is referenced as
+ self.backends after construction and may be updated as needed.
+ Each key in backends should be the Index object that generates
+ access_memo's to read from, and the value should be the access
+ object to pass such queries too.
+ """
+ self.backends = backends
+ self.writer = None
+
+ def add_raw_records(self, key_sizes, raw_data):
+ """Add raw knit bytes to.
+
+ The data is sent to the current writer's add_raw_records method
+ verbatim.
+
+ The result's are adapted in the manner expected by get_raw_records so
+ that they can be immediately requested again if desired.
+
+ :param sizes: An iterable of tuples containing the key and size of each
+ raw data segment.
+ :param raw_data: A bytestring containing the data.
+ :return: A list of memos to retrieve the record later. Each memo is an
+ opaque index memo. For StackedAccess the memo is:
+ ((backend, original_memo), pos, size).
+ """
+ if type(raw_data) != str:
+ raise AssertionError(
+ 'data must be plain bytes was %s' % type(raw_data))
+ result = []
+ writer = self.writer
+ for memo in self.backends[writer].add_raw_records(key_sizes, raw_data):
+ result.append(((writer, memo), memo[1], memo[2]))
+ return result
+
+ def get_raw_records(self, memos_for_retrieval):
+ """Get the raw bytes for a records.
+
+ :param memos_for_retrieval: An iterable containing the access memos for
+ retrieving the bytes.
+ :return: An iterator over the bytes of the records.
+ """
+ # Group into same-backend requests (without losing order), and then
+ # dispatch:
+ request_lists = []
+ current_index = None
+ for (index, original_memo), _, _ in memos_for_retrieval:
+ if current_index == index:
+ current_list.append(original_memo)
+ else:
+ if current_index is not None:
+ request_lists.append((current_index, current_list))
+ current_index = index
+ current_list = [original_memo]
+ # handle the last entry
+ if current_index is not None:
+ request_lists.append((current_index, current_list))
+ for index, memos in request_lists:
+ for result in self.backends[index].get_raw_records(memos):
+ yield result
+
+ def set_writer(self, index):
+ """Select which backend from self.backends to write new records to.
+
+ :param index: An index listed in self.backends that new writes should
+ be directed to.
+ """
+ self.writer = index
+
+
# Deprecated, use PatienceSequenceMatcher instead
KnitSequenceMatcher = patiencediff.PatienceSequenceMatcher
=== modified file 'bzrlib/tests/test_knit.py'
--- a/bzrlib/tests/test_knit.py 2008-06-11 04:20:16 +0000
+++ b/bzrlib/tests/test_knit.py 2008-06-17 03:56:03 +0000
@@ -46,6 +46,7 @@
_KnitGraphIndex,
_KnitKeyAccess,
make_file_factory,
+ StackedAccess,
)
from bzrlib.osutils import split_lines
from bzrlib.symbol_versioning import one_four
@@ -359,6 +360,62 @@
self.assertEqual(['1234567890'], list(access.get_raw_records(memos)))
+class TestStackedKnitAccess(TestCaseWithMemoryTransport):
+ """Tests for the stacking access logic."""
+
+ def get_access(self):
+ return self._get_access()[0]
+
+ def _get_access(self, packname='packfile', index='FOO'):
+ transport = self.get_transport()
+ def write_data(bytes):
+ transport.append_bytes(packname, bytes)
+ writer = pack.ContainerWriter(write_data)
+ writer.begin()
+ access = _DirectPackAccess({})
+ access.set_writer(writer, index, (transport, packname))
+ return access, writer
+
+ def get_backend(self, name):
+ """Get a .knit style access instance for use as a backend."""
+ mapper = ConstantMapper(name)
+ access = _KnitKeyAccess(self.get_transport(), mapper)
+ return access
+
+ def test_read_from_two_backends(self):
+ backend1 = self.get_backend('1')
+ memos1 = backend1.add_raw_records([(('key1',), 10)], '1234567890')
+ backend2 = self.get_backend('2')
+ memos2 = backend2.add_raw_records([(('key2',), 10)], '0987654321')
+ backends = {"1":backend1, "2":backend2}
+ access = StackedAccess(backends)
+ # StackedIndex will decorate access_memos with the index returning
+ # each memo:
+ memos = [(("1", memos1[0]), 0, 10),(("2", memos2[0]), 0, 10)]
+ self.assertEqual(['1234567890', '0987654321'],
+ list(access.get_raw_records(memos)))
+
+ def test_set_writer(self):
+ """The writer should be settable post construction."""
+ backend1 = self.get_backend('1')
+ backend2 = self.get_backend('2')
+ backends = {"1":backend1, "2":backend2}
+ access = StackedAccess(backends)
+ # We test by writing data, changing the writer, writing again,
+ # Then reading both.
+ access.set_writer("1")
+ memos1 = access.add_raw_records([(('key1',), 10)], '1234567890')
+ # the returned memo should be decorated with the writer index
+ # and preserve the position and size fields:
+ self.assertEqual([(("1", (('key1',), 0, 10)), 0, 10)], memos1)
+ access.set_writer("2")
+ memos2 = access.add_raw_records([(('key2',), 10)], '0987654321')
+ self.assertEqual([(("2", (('key2',), 0, 10)), 0, 10)], memos2)
+ memos = [memos1[0], memos2[0]]
+ self.assertEqual(['1234567890', '0987654321'],
+ list(access.get_raw_records(memos)))
+
+
class LowLevelKnitDataTests(TestCase):
def create_gz_content(self, text):
More information about the bazaar-commits
mailing list