[MERGE][#178353] Smart request to stream revisions without buffering

Andrew Bennetts andrew at canonical.com
Wed Jan 2 22:59:27 GMT 2008


This bundle adds a new smart request.  It behaves very similarly to the existing
request to fetch multiple revisions, except that it streams the results as they
are generated.  This should make it use much less memory, and also be faster
(because the client will start receiving data sooner).  It uses the new chunked
body support to do this, which didn't exist when the original
fetch multiple revisions method was merged.

I've changed the client to try this method, and then fallback directly to VFS
operations, rather than falling back to the old (buffered) method then VFS.  The
server still supports the buffered method, of course.

I think this will probably fix bug 178353, once both the client and servers
involved have been upgraded.

-Andrew.

-------------- next part --------------
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: andrew.bennetts at canonical.com-20080102080932-\
#   j6x7n1jfp84dhl1z
# target_branch: http://bazaar-vcs.org/bzr/bzr.dev
# testament_sha1: 281caf564fbb7136e68e2ccc4c30bf3477b00ed5
# timestamp: 2008-01-02 19:15:40 +1100
# source_branch: http://people.ubuntu.com/~andrew/bzr/chunked-\
#   body/streaming-smart-fetch
# base_revision_id: pqm at pqm.ubuntu.com-20071228175832-9kboqtkemnuzzlab
# 
# Begin patch
=== modified file 'NEWS'
--- NEWS	2007-12-26 21:13:53 +0000
+++ NEWS	2008-01-02 07:58:37 +0000
@@ -19,6 +19,11 @@
    * New option to use custom template-based formats in  ``bzr version-info``.
      (Luk?? Lalinsk?)
 
+   * New smart method, ``Repository.stream_revisions_chunked``, for fetching
+     revision data that streams revision data via a chunked encoding.  This
+     avoids buffering large amounts of revision data on the server and on the
+     client.  (Andrew Bennetts, #178353)
+
    * diff '--using' allows an external diff tool to be used for files.
      (Aaron Bentley)
 

=== modified file 'bzrlib/remote.py'
--- bzrlib/remote.py	2007-12-21 19:56:30 +0000
+++ bzrlib/remote.py	2008-01-02 07:58:37 +0000
@@ -26,18 +26,14 @@
     repository,
     revision,
 )
-from bzrlib.branch import Branch, BranchReferenceFormat
+from bzrlib.branch import BranchReferenceFormat
 from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
 from bzrlib.config import BranchConfig, TreeConfig
 from bzrlib.decorators import needs_read_lock, needs_write_lock
 from bzrlib.errors import NoSuchRevision
 from bzrlib.lockable_files import LockableFiles
-from bzrlib.pack import ContainerReader
+from bzrlib.pack import ContainerPushParser
 from bzrlib.smart import client, vfs
-from bzrlib.symbol_versioning import (
-    deprecated_method,
-    zero_ninetyone,
-    )
 from bzrlib.trace import note
 
 # Note: RemoteBzrDirFormat is in bzrdir.py
@@ -777,7 +773,6 @@
         from bzrlib import osutils
         import tarfile
         import tempfile
-        from StringIO import StringIO
         # TODO: Maybe a progress bar while streaming the tarball?
         note("Copying repository content as tarball...")
         tar_file = self._get_tarball('bz2')
@@ -850,15 +845,17 @@
         return self._real_repository.has_signature_for_revision_id(revision_id)
 
     def get_data_stream(self, revision_ids):
+        REQUEST_NAME = 'Repository.stream_revisions_chunked'
         path = self.bzrdir._path_for_remote_call(self._client)
         response, protocol = self._client.call_expecting_body(
-            'Repository.stream_knit_data_for_revisions', path, *revision_ids)
+            REQUEST_NAME, path, *revision_ids)
+
         if response == ('ok',):
             return self._deserialise_stream(protocol)
         elif (response == ('error', "Generic bzr smart protocol error: "
-                "bad request 'Repository.stream_knit_data_for_revisions'") or
+                "bad request '%s'" % REQUEST_NAME) or
               response == ('error', "Generic bzr smart protocol error: "
-                "bad request u'Repository.stream_knit_data_for_revisions'")):
+                "bad request u'%s'" % REQUEST_NAME)):
             protocol.cancel_read_body()
             self._ensure_real()
             return self._real_repository.get_data_stream(revision_ids)
@@ -866,18 +863,21 @@
             raise errors.UnexpectedSmartServerResponse(response)
 
     def _deserialise_stream(self, protocol):
-        buffer = StringIO(protocol.read_body_bytes())
-        reader = ContainerReader(buffer)
-        for record_names, read_bytes in reader.iter_records():
-            try:
-                # These records should have only one name, and that name
-                # should be a one-element tuple.
-                [name_tuple] = record_names
-            except ValueError:
-                raise errors.SmartProtocolError(
-                    'Repository data stream had invalid record name %r'
-                    % (record_names,))
-            yield name_tuple, read_bytes(None)
+        stream = protocol.read_streamed_body()
+        container_parser = ContainerPushParser()
+        for bytes in stream:
+            container_parser.accept_bytes(bytes)
+            records = container_parser.read_pending_records()
+            for record_names, record_bytes in records:
+                try:
+                    # These records should have only one name, and that name
+                    # should be a one-element tuple.
+                    [name_tuple] = record_names
+                except ValueError:
+                    raise errors.SmartProtocolError(
+                        'Repository data stream had invalid record name %r'
+                        % (record_names,))
+                yield name_tuple, record_bytes
 
     def insert_data_stream(self, stream):
         self._ensure_real()

=== modified file 'bzrlib/smart/client.py'
--- bzrlib/smart/client.py	2007-08-06 05:11:55 +0000
+++ bzrlib/smart/client.py	2007-08-30 14:56:51 +0000
@@ -43,7 +43,7 @@
             body = smart_protocol.read_body_bytes()
         """
         request = self.get_smart_medium().get_request()
-        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
+        smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
         smart_protocol.call(method, *args)
         return smart_protocol.read_response_tuple(expect_body=True), smart_protocol
 

=== modified file 'bzrlib/smart/repository.py'
--- bzrlib/smart/repository.py	2007-11-26 02:08:13 +0000
+++ bzrlib/smart/repository.py	2008-01-02 08:09:32 +0000
@@ -24,7 +24,7 @@
 
 from bzrlib import errors
 from bzrlib.bzrdir import BzrDir
-from bzrlib.pack import ContainerWriter
+from bzrlib.pack import ContainerSerialiser
 from bzrlib.smart.request import (
     FailedSmartServerResponse,
     SmartServerRequest,
@@ -258,14 +258,38 @@
 
     def _do_repository_request(self, repository, revision_ids):
         stream = repository.get_data_stream(revision_ids)
-        filelike = StringIO()
-        pack = ContainerWriter(filelike.write)
-        pack.begin()
+        buffer = StringIO()
+        pack = ContainerSerialiser()
+        buffer.write(pack.begin())
         try:
             for name_tuple, bytes in stream:
-                pack.add_bytes_record(bytes, [name_tuple])
+                buffer.write(pack.bytes_record(bytes, [name_tuple]))
         except errors.RevisionNotPresent, e:
             return FailedSmartServerResponse(('NoSuchRevision', e.revision_id))
+        buffer.write(pack.end())
+        return SuccessfulSmartServerResponse(('ok',), buffer.getvalue())
+
+
+class SmartServerRepositoryStreamRevisionsChunked(SmartServerRepositoryRequest):
+
+    def do_repository_request(self, repository, *revision_ids):
+        repository.lock_read()
+        try:
+            stream = repository.get_data_stream(revision_ids)
+        except Exception:
+            repository.unlock()
+            raise
+        return SuccessfulSmartServerResponse(('ok',),
+            body_stream=self.body_stream(stream, repository))
+
+    def body_stream(self, stream, repository):
+        pack = ContainerSerialiser()
+        yield pack.begin()
+        try:
+            for name_tuple, bytes in stream:
+                yield pack.bytes_record(bytes, [name_tuple])
+        except errors.RevisionNotPresent, e:
+            yield FailedSmartServerResponse(('NoSuchRevision', e.revision_id))
+        repository.unlock()
         pack.end()
-        return SuccessfulSmartServerResponse(('ok',), filelike.getvalue())
 

=== modified file 'bzrlib/smart/request.py'
--- bzrlib/smart/request.py	2007-10-19 05:38:36 +0000
+++ bzrlib/smart/request.py	2008-01-02 07:58:37 +0000
@@ -106,8 +106,8 @@
                 other.body_stream is self.body_stream)
 
     def __repr__(self):
-        return "<SmartServerResponse %r args=%r body=%r>" % (
-            self.is_successful(), self.args, self.body)
+        return ("<SmartServerResponse successful=%s args=%r body=%r>"
+                % (self.is_successful(), self.args, self.body))
 
 
 class FailedSmartServerResponse(SmartServerResponse):
@@ -319,7 +319,16 @@
                                'bzrlib.smart.repository',
                                'SmartServerRepositoryGatherStats')
 request_handlers.register_lazy(
-    'Repository.stream_knit_data_for_revisions', 'bzrlib.smart.repository',
+    'Repository.stream_knit_data_for_revisions',
+    'bzrlib.smart.repository',
+    'SmartServerRepositoryStreamKnitDataForRevisions')
+request_handlers.register_lazy(
+    'Repository.stream_revisions_chunked',
+    'bzrlib.smart.repository',
+    'SmartServerRepositoryStreamRevisionsChunked')
+request_handlers.register_lazy(
+    'Repository.chunked_stream_knit_data_for_revisions',
+    'bzrlib.smart.repository',
     'SmartServerRepositoryStreamKnitDataForRevisions')
 request_handlers.register_lazy(
     'Repository.get_revision_graph', 'bzrlib.smart.repository', 'SmartServerRepositoryGetRevisionGraph')

=== modified file 'bzrlib/tests/test_remote.py'
--- bzrlib/tests/test_remote.py	2007-10-12 06:24:42 +0000
+++ bzrlib/tests/test_remote.py	2008-01-02 07:58:37 +0000
@@ -108,10 +108,13 @@
     """Lookalike SmartClientRequestProtocolOne allowing body reading tests."""
 
     def __init__(self, body, fake_client):
-        self._body_buffer = StringIO(body)
+        self.body = body
+        self._body_buffer = None
         self._fake_client = fake_client
 
     def read_body_bytes(self, count=-1):
+        if self._body_buffer is None:
+            self._body_buffer = StringIO(self.body)
         bytes = self._body_buffer.read(count)
         if self._body_buffer.tell() == len(self._body_buffer.getvalue()):
             self._fake_client.expecting_body = False
@@ -120,6 +123,9 @@
     def cancel_read_body(self):
         self._fake_client.expecting_body = False
 
+    def read_streamed_body(self):
+        return self.body
+
 
 class FakeClient(_SmartClient):
     """Lookalike for _SmartClient allowing testing."""
@@ -775,6 +781,13 @@
         pack_file.seek(0)
         return pack_file
 
+    def make_pack_stream(self, records):
+        pack_serialiser = pack.ContainerSerialiser()
+        yield pack_serialiser.begin()
+        for bytes, names in records:
+            yield pack_serialiser.bytes_record(bytes, names)
+        yield pack_serialiser.end()
+
     def test_bad_pack_from_server(self):
         """A response with invalid data (e.g. it has a record with multiple
         names) triggers an exception.
@@ -783,8 +796,8 @@
         malformed data should be.
         """
         record = ('bytes', [('name1',), ('name2',)])
-        pack_file = self.make_pack_file([record])
-        responses = [(('ok',), pack_file.getvalue()), ]
+        pack_stream = self.make_pack_stream([record])
+        responses = [(('ok',), pack_stream), ]
         transport_path = 'quack'
         repo, client = self.setup_fake_client_and_repository(
             responses, transport_path)
@@ -795,7 +808,7 @@
         """If the server doesn't recognise this request, fallback to VFS."""
         error_msg = (
             "Generic bzr smart protocol error: "
-            "bad request 'Repository.stream_knit_data_for_revisions'")
+            "bad request 'Repository.stream_revisions_chunked'")
         responses = [
             (('error', error_msg), '')]
         repo, client = self.setup_fake_client_and_repository(

=== modified file 'bzrlib/tests/test_smart.py'
--- bzrlib/tests/test_smart.py	2007-11-26 03:36:30 +0000
+++ bzrlib/tests/test_smart.py	2008-01-02 07:58:37 +0000
@@ -29,7 +29,11 @@
 import tarfile
 
 from bzrlib import bzrdir, errors, pack, smart, tests
-from bzrlib.smart.request import SmartServerResponse
+from bzrlib.smart.request import (
+    FailedSmartServerResponse,
+    SmartServerResponse,
+    SuccessfulSmartServerResponse,
+    )
 import bzrlib.smart.bzrdir
 import bzrlib.smart.branch
 import bzrlib.smart.repository
@@ -814,6 +818,54 @@
             response)
 
 
+class TestSmartServerRepositoryStreamRevisionsChunked(tests.TestCaseWithTransport):
+
+    def test_fetch_revisions(self):
+        backing = self.get_transport()
+        request = smart.repository.SmartServerRepositoryStreamRevisionsChunked(
+            backing)
+        tree = self.make_branch_and_memory_tree('.')
+        tree.lock_write()
+        tree.add('')
+        rev_id1_utf8 = u'\xc8'.encode('utf-8')
+        rev_id2_utf8 = u'\xc9'.encode('utf-8')
+        r1 = tree.commit('1st commit', rev_id=rev_id1_utf8)
+        r1 = tree.commit('2nd commit', rev_id=rev_id2_utf8)
+        tree.unlock()
+
+        response = request.execute(backing.local_abspath(''), rev_id2_utf8)
+        self.assertEqual(('ok',), response.args)
+        from cStringIO import StringIO
+        parser = pack.ContainerPushParser()
+        names = []
+        for stream_bytes in response.body_stream:
+            parser.accept_bytes(stream_bytes)
+            for [name], record_bytes in parser.read_pending_records():
+                names.append(name)
+                # The bytes should be a valid bencoded string.
+                bencode.bdecode(record_bytes)
+                # XXX: assert that the bencoded knit records have the right
+                # contents?
+        
+    def test_no_such_revision_error(self):
+        backing = self.get_transport()
+        request = smart.repository.SmartServerRepositoryStreamRevisionsChunked(
+            backing)
+        repo = self.make_repository('.')
+        rev_id1_utf8 = u'\xc8'.encode('utf-8')
+        response = request.execute(backing.local_abspath(''), rev_id1_utf8)
+        # There's no error initially.
+        self.assertTrue(response.is_successful())
+        self.assertEqual(('ok',), response.args)
+        # We only get an error while streaming the body.
+        body = list(response.body_stream)
+        last_chunk = body[-1]
+        self.assertIsInstance(last_chunk, FailedSmartServerResponse)
+        self.assertEqual(
+            last_chunk,
+            FailedSmartServerResponse(('NoSuchRevision', rev_id1_utf8)))
+
+
 class TestSmartServerIsReadonly(tests.TestCaseWithTransport):
 
     def test_is_readonly_no(self):
@@ -881,7 +933,7 @@
             smart.repository.SmartServerRepositoryLockWrite)
         self.assertEqual(
             smart.request.request_handlers.get(
-                'Repository.stream_knit_data_for_revisions'),
+                'Repository.chunked_stream_knit_data_for_revisions'),
             smart.repository.SmartServerRepositoryStreamKnitDataForRevisions)
         self.assertEqual(
             smart.request.request_handlers.get('Repository.tarball'),

=== modified file 'bzrlib/tests/test_smart_transport.py'
--- bzrlib/tests/test_smart_transport.py	2007-11-09 20:49:54 +0000
+++ bzrlib/tests/test_smart_transport.py	2007-11-10 15:10:05 +0000
@@ -2277,6 +2277,8 @@
             ('foo', 'bar'), 'bytes')
         self.assertEqual(('foo', 'bar'), response.args)
         self.assertEqual('bytes', response.body)
+        # repr(response) doesn't trigger exceptions.
+        repr(response)
 
     def test_construct_with_body_stream(self):
         bytes_iterable = ['abc']
@@ -2306,6 +2308,8 @@
         response = request.FailedSmartServerResponse(('foo', 'bar'), 'bytes')
         self.assertEqual(('foo', 'bar'), response.args)
         self.assertEqual('bytes', response.body)
+        # repr(response) doesn't trigger exceptions.
+        repr(response)
 
     def test_is_successful(self):
         """is_successful should return False for FailedSmartServerResponse."""

=== modified file 'doc/developers/index.txt'
--- doc/developers/index.txt	2007-12-05 18:58:49 +0000
+++ doc/developers/index.txt	2008-01-02 03:08:59 +0000
@@ -34,7 +34,6 @@
 * `Network protocol <network-protocol.html>`_ |--| Custom network protocol.
 
 Data formats
-============
 
 * `Knit pack repositories <packrepo.html>`_ |--| KnitPack repositories 
   (new in Bazaar 0.92).

# Begin bundle
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
R6g=


More information about the bazaar mailing list