~bzr-pqm/bzr/bzr.dev

3245.4.31 by Andrew Bennetts
Fix year in copyright statement of message.py
1
# Copyright (C) 2008 Canonical Ltd
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
3195.3.24 by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler.
17
import collections
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
18
from cStringIO import StringIO
19
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
20
from bzrlib import (
21
    debug,
22
    errors,
23
    )
24
from bzrlib.trace import mutter
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
25
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
26
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
27
class MessageHandler(object):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
28
    """Base class for handling messages received via the smart protocol.
29
30
    As parts of a message are received, the corresponding PART_received method
31
    will be called.
32
    """
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
33
34
    def __init__(self):
35
        self.headers = None
36
37
    def headers_received(self, headers):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
38
        """Called when message headers are received.
39
        
40
        This default implementation just stores them in self.headers.
41
        """
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
42
        self.headers = headers
43
44
    def byte_part_received(self, byte):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
45
        """Called when a 'byte' part is received.
46
47
        Note that a 'byte' part is a message part consisting of exactly one
48
        byte.
49
        """
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
50
        raise NotImplementedError(self.byte_received)
51
52
    def bytes_part_received(self, bytes):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
53
        """Called when a 'bytes' part is received.
54
55
        A 'bytes' message part can contain any number of bytes.  It should not
56
        be confused with a 'byte' part, which is always a single byte.
57
        """
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
58
        raise NotImplementedError(self.bytes_received)
59
60
    def structure_part_received(self, structure):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
61
        """Called when a 'structure' part is received.
62
63
        :param structure: some structured data, which will be some combination
64
            of list, dict, int, and str objects.
65
        """
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
66
        raise NotImplementedError(self.bytes_received)
67
68
    def protocol_error(self, exception):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
69
        """Called when there is a protocol decoding error.
70
        
71
        The default implementation just re-raises the exception.
72
        """
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
73
        raise
74
    
75
    def end_received(self):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
76
        """Called when the end of the message is received."""
3245.4.27 by Andrew Bennetts
Tidy some XXXs in bzrlib/smart/message.py.
77
        # No-op by default.
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
78
        pass
79
80
81
class ConventionalRequestHandler(MessageHandler):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
82
    """A message handler for "conventional" requests.
83
84
    "Conventional" is used in the sense described in
85
    doc/developers/network-protocol.txt: a simple message with arguments and an
86
    optional body.
87
    """
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
88
89
    def __init__(self, request_handler, responder):
90
        MessageHandler.__init__(self)
91
        self.request_handler = request_handler
92
        self.responder = responder
93
        self.args_received = False
94
95
    def protocol_error(self, exception):
3245.4.50 by Andrew Bennetts
Clarify the code a little.
96
        if self.responder.response_sent:
97
            # We can only send one response to a request, no matter how many
98
            # errors happen while processing it.
99
            return
100
        self.responder.send_error(exception)
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
101
102
    def byte_part_received(self, byte):
103
        raise errors.SmartProtocolError(
104
            'Unexpected message part: byte(%r)' % (byte,))
105
106
    def structure_part_received(self, structure):
107
        if self.args_received:
108
            raise errors.SmartProtocolError(
109
                'Unexpected message part: structure(%r)' % (structure,))
110
        self.args_received = True
111
        self.request_handler.dispatch_command(structure[0], structure[1:])
112
        if self.request_handler.finished_reading:
113
            self.responder.send_response(self.request_handler.response)
114
115
    def bytes_part_received(self, bytes):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
116
        # Note that there's no intrinsic way to distinguish a monolithic body
117
        # from a chunk stream.  A request handler knows which it is expecting
118
        # (once the args have been received), so it should be able to do the
119
        # right thing.
3195.3.18 by Andrew Bennetts
call_with_body_bytes now works with v3 (e.g. test_copy_content_remote_to_local passes). Lots of debugging cruft, though.
120
        self.request_handler.accept_body(bytes)
121
        self.request_handler.end_of_body()
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
122
        if not self.request_handler.finished_reading:
3695.1.1 by Andrew Bennetts
Remove some unused imports and fix a couple of trivially broken raise statements.
123
            raise errors.SmartProtocolError(
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
124
                "Conventional request body was received, but request handler "
125
                "has not finished reading.")
3195.3.18 by Andrew Bennetts
call_with_body_bytes now works with v3 (e.g. test_copy_content_remote_to_local passes). Lots of debugging cruft, though.
126
        self.responder.send_response(self.request_handler.response)
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
127
128
3245.4.26 by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers.
129
class ResponseHandler(object):
130
    """Abstract base class for an object that handles a smart response."""
131
132
    def read_response_tuple(self, expect_body=False):
133
        """Reads and returns the response tuple for the current request.
134
        
135
        :keyword expect_body: a boolean indicating if a body is expected in the
136
            response.  Some protocol versions needs this information to know
137
            when a response is finished.  If False, read_body_bytes should
138
            *not* be called afterwards.  Defaults to False.
139
        :returns: tuple of response arguments.
140
        """
141
        raise NotImplementedError(self.read_response_tuple)
142
143
    def read_body_bytes(self, count=-1):
144
        """Read and return some bytes from the body.
145
146
        :param count: if specified, read up to this many bytes.  By default,
147
            reads the entire body.
148
        :returns: str of bytes from the response body.
149
        """
150
        raise NotImplementedError(self.read_body_bytes)
151
152
    def read_streamed_body(self):
153
        """Returns an iterable that reads and returns a series of body chunks.
154
        """
155
        raise NotImplementedError(self.read_streamed_body)
156
157
    def cancel_read_body(self):
158
        """Stop expecting a body for this response.
159
160
        If expect_body was passed to read_response_tuple, this cancels that
161
        expectation (and thus finishes reading the response, allowing a new
162
        request to be issued).  This is useful if a response turns out to be an
163
        error rather than a normal result with a body.
164
        """
165
        raise NotImplementedError(self.cancel_read_body)
166
167
168
class ConventionalResponseHandler(MessageHandler, ResponseHandler):
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
169
170
    def __init__(self):
171
        MessageHandler.__init__(self)
172
        self.status = None
173
        self.args = None
3195.3.24 by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler.
174
        self._bytes_parts = collections.deque()
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
175
        self._body_started = False
176
        self._body_stream_status = None
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
177
        self._body = None
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
178
        self._body_error_args = None
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
179
        self.finished_reading = False
180
3245.4.26 by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers.
181
    def setProtoAndMediumRequest(self, protocol_decoder, medium_request):
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
182
        self._protocol_decoder = protocol_decoder
3245.4.26 by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers.
183
        self._medium_request = medium_request
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
184
185
    def byte_part_received(self, byte):
186
        if byte not in ['E', 'S']:
187
            raise errors.SmartProtocolError(
188
                'Unknown response status: %r' % (byte,))
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
189
        if self._body_started:
190
            if self._body_stream_status is not None:
191
                raise errors.SmartProtocolError(
192
                    'Unexpected byte part received: %r' % (byte,))
193
            self._body_stream_status = byte
194
        else:
195
            if self.status is not None:
196
                raise errors.SmartProtocolError(
197
                    'Unexpected byte part received: %r' % (byte,))
198
            self.status = byte
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
199
200
    def bytes_part_received(self, bytes):
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
201
        self._body_started = True
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
202
        self._bytes_parts.append(bytes)
203
204
    def structure_part_received(self, structure):
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
205
        if type(structure) is not list:
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
206
            raise errors.SmartProtocolError(
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
207
                'Args structure is not a sequence: %r' % (structure,))
208
        structure = tuple(structure)
209
        if not self._body_started:
210
            if self.args is not None:
211
                raise errors.SmartProtocolError(
212
                    'Unexpected structure received: %r (already got %r)'
213
                    % (structure, self.args))
214
            self.args = structure
215
        else:
216
            if self._body_stream_status != 'E':
217
                raise errors.SmartProtocolError(
218
                    'Unexpected structure received after body: %r'
219
                    % (structure,))
220
            self._body_error_args = structure
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
221
222
    def _wait_for_response_args(self):
223
        while self.args is None and not self.finished_reading:
224
            self._read_more()
225
226
    def _wait_for_response_end(self):
227
        while not self.finished_reading:
228
            self._read_more()
229
230
    def _read_more(self):
231
        next_read_size = self._protocol_decoder.next_read_size()
232
        if next_read_size == 0:
233
            # a complete request has been read.
234
            self.finished_reading = True
3245.4.26 by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers.
235
            self._medium_request.finished_reading()
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
236
            return
3750.1.2 by Vincent Ladeuil
Fixed as per Andrew's review.
237
        bytes = self._medium_request.read_bytes(next_read_size)
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
238
        if bytes == '':
239
            # end of file encountered reading from server
3461.2.1 by Andrew Bennetts
Avoid unnecessary reconnections to old servers when the first HPSS is an error in the right protocol version.
240
            if 'hpss' in debug.debug_flags:
241
                mutter(
242
                    'decoder state: buf[:10]=%r, state_accept=%s',
3702.2.1 by Andrew Bennetts
Fix '_in_buffer' AttributeError when using the -Dhpss debug flag.
243
                    self._protocol_decoder._get_in_buffer()[:10],
3461.2.2 by Andrew Bennetts
Tweak suggested by John.
244
                    self._protocol_decoder.state_accept.__name__)
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
245
            raise errors.ConnectionReset(
246
                "please check connectivity and permissions",
247
                "(and try -Dhpss if further diagnosis is required)")
248
        self._protocol_decoder.accept_bytes(bytes)
249
3245.4.47 by Andrew Bennetts
Don't automatically send 'hello' requests from RemoteBzrDirFormat.probe_transport unless we have to (i.e. the transport is HTTP).
250
    def protocol_error(self, exception):
251
        # Whatever the error is, we're done with this request.
252
        self.finished_reading = True
253
        self._medium_request.finished_reading()
254
        raise
255
        
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
256
    def read_response_tuple(self, expect_body=False):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
257
        """Read a response tuple from the wire."""
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
258
        self._wait_for_response_args()
3195.3.18 by Andrew Bennetts
call_with_body_bytes now works with v3 (e.g. test_copy_content_remote_to_local passes). Lots of debugging cruft, though.
259
        if not expect_body:
260
            self._wait_for_response_end()
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
261
        if 'hpss' in debug.debug_flags:
262
            mutter('   result:   %r', self.args)
263
        if self.status == 'E':
264
            self._wait_for_response_end()
265
            _translate_error(self.args)
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
266
        return tuple(self.args)
267
268
    def read_body_bytes(self, count=-1):
269
        """Read bytes from the body, decoding into a byte stream.
270
        
271
        We read all bytes at once to ensure we've checked the trailer for 
272
        errors, and then feed the buffer back as read_body_bytes is called.
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
273
274
        Like the builtin file.read in Python, a count of -1 (the default) means
275
        read the entire body.
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
276
        """
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
277
        # TODO: we don't necessarily need to buffer the full request if count
278
        # != -1.  (2008/04/30, Andrew Bennetts)
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
279
        if self._body is None:
3195.3.18 by Andrew Bennetts
call_with_body_bytes now works with v3 (e.g. test_copy_content_remote_to_local passes). Lots of debugging cruft, though.
280
            self._wait_for_response_end()
3245.4.25 by Andrew Bennetts
Add some -Dhpss mutters to the protocol v3 code, so that it gives comparable debug logging to earlier protocols.
281
            body_bytes = ''.join(self._bytes_parts)
282
            if 'hpss' in debug.debug_flags:
283
                mutter('              %d body bytes read', len(body_bytes))
284
            self._body = StringIO(body_bytes)
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
285
            self._bytes_parts = None
286
        return self._body.read(count)
287
3195.3.24 by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler.
288
    def read_streamed_body(self):
289
        while not self.finished_reading:
290
            while self._bytes_parts:
3245.4.25 by Andrew Bennetts
Add some -Dhpss mutters to the protocol v3 code, so that it gives comparable debug logging to earlier protocols.
291
                bytes_part = self._bytes_parts.popleft()
292
                if 'hpss' in debug.debug_flags:
293
                    mutter('              %d byte part read', len(bytes_part))
294
                yield bytes_part
3195.3.24 by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler.
295
            self._read_more()
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
296
        if self._body_stream_status == 'E':
297
            _translate_error(self._body_error_args)
3195.3.24 by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler.
298
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
299
    def cancel_read_body(self):
300
        self._wait_for_response_end()
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
301
302
303
def _translate_error(error_tuple):
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
304
    # Many exceptions need some state from the requestor to be properly
305
    # translated (e.g. they need a branch object).  So this only translates a
306
    # few errors, and the rest are turned into a generic ErrorFromSmartServer.
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
307
    error_name = error_tuple[0]
308
    error_args = error_tuple[1:]
3245.4.35 by Andrew Bennetts
Remove some commented out cruft, test (and fix) handling of an 'UnknownMethod' response.
309
    if error_name == 'UnknownMethod':
310
        raise errors.UnknownSmartMethod(error_args[0])
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
311
    if error_name == 'LockContention':
312
        raise errors.LockContention('(remote lock)')
313
    elif error_name == 'LockFailed':
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
314
        raise errors.LockFailed(*error_args[:2])
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
315
    else:
316
        raise errors.ErrorFromSmartServer(error_tuple)