~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/protocol.py

  • Committer: John Arbash Meinel
  • Date: 2007-04-28 15:04:17 UTC
  • mfrom: (2466 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2566.
  • Revision ID: john@arbash-meinel.com-20070428150417-trp3pi0pzd411pu4
[merge] bzr.dev 2466

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
from bzrlib.smart import request
26
26
 
27
27
 
 
28
# Protocol version strings.  These are sent as prefixes of bzr requests and
 
29
# responses to identify the protocol version being used. (There are no version
 
30
# one strings because that version doesn't send any).
 
31
REQUEST_VERSION_TWO = 'bzr request 2\n'
 
32
RESPONSE_VERSION_TWO = 'bzr response 2\n'
 
33
 
 
34
 
28
35
def _recv_tuple(from_file):
29
36
    req_line = from_file.readline()
30
37
    return _decode_tuple(req_line)
96
103
                    # trivial request
97
104
                    self.excess_buffer = self.in_buffer
98
105
                    self.in_buffer = ''
99
 
                    self._send_response(self.request.response.args,
100
 
                        self.request.response.body)
 
106
                    self._send_response(self.request.response)
101
107
            except KeyboardInterrupt:
102
108
                raise
103
109
            except Exception, exception:
104
110
                # everything else: pass to client, flush, and quit
105
 
                self._send_response(('error', str(exception)))
 
111
                self._send_response(request.FailedSmartServerResponse(
 
112
                    ('error', str(exception))))
106
113
                return
107
114
 
108
115
        if self.has_dispatched:
123
130
                assert self.request.finished_reading, \
124
131
                    "no more body, request not finished"
125
132
            if self.request.response is not None:
126
 
                self._send_response(self.request.response.args,
127
 
                    self.request.response.body)
 
133
                self._send_response(self.request.response)
128
134
                self.excess_buffer = self.in_buffer
129
135
                self.in_buffer = ''
130
136
            else:
131
137
                assert not self.request.finished_reading, \
132
138
                    "no response and we have finished reading."
133
139
 
134
 
    def _send_response(self, args, body=None):
 
140
    def _send_response(self, response):
135
141
        """Send a smart server response down the output stream."""
136
142
        assert not self._finished, 'response already sent'
 
143
        args = response.args
 
144
        body = response.body
137
145
        self._finished = True
 
146
        self._write_protocol_version()
 
147
        self._write_success_or_failure_prefix(response)
138
148
        self._write_func(_encode_tuple(args))
139
149
        if body is not None:
140
150
            assert isinstance(body, str), 'body must be a str'
141
151
            bytes = self._encode_bulk_data(body)
142
152
            self._write_func(bytes)
143
153
 
 
154
    def _write_protocol_version(self):
 
155
        """Write any prefixes this protocol requires.
 
156
        
 
157
        Version one doesn't send protocol versions.
 
158
        """
 
159
 
 
160
    def _write_success_or_failure_prefix(self, response):
 
161
        """Write the protocol specific success/failure prefix.
 
162
 
 
163
        For SmartServerRequestProtocolOne this is omitted but we
 
164
        call is_successful to ensure that the response is valid.
 
165
        """
 
166
        response.is_successful()
 
167
 
144
168
    def next_read_size(self):
145
169
        if self._finished:
146
170
            return 0
150
174
            return self._body_decoder.next_read_size()
151
175
 
152
176
 
 
177
class SmartServerRequestProtocolTwo(SmartServerRequestProtocolOne):
 
178
    r"""Version two of the server side of the smart protocol.
 
179
   
 
180
    This prefixes responses with the value of RESPONSE_VERSION_TWO.
 
181
    """
 
182
 
 
183
    def _write_success_or_failure_prefix(self, response):
 
184
        """Write the protocol specific success/failure prefix."""
 
185
        if response.is_successful():
 
186
            self._write_func('success\n')
 
187
        else:
 
188
            self._write_func('failed\n')
 
189
 
 
190
    def _write_protocol_version(self):
 
191
        r"""Write any prefixes this protocol requires.
 
192
        
 
193
        Version two sends the value of RESPONSE_VERSION_TWO.
 
194
        """
 
195
        self._write_func(RESPONSE_VERSION_TWO)
 
196
 
 
197
 
153
198
class LengthPrefixedBodyDecoder(object):
154
199
    """Decodes the length-prefixed bulk data."""
155
200
    
254
299
        self._body_buffer = None
255
300
 
256
301
    def call(self, *args):
257
 
        bytes = _encode_tuple(args)
258
 
        self._request.accept_bytes(bytes)
 
302
        self._write_args(args)
259
303
        self._request.finished_writing()
260
304
 
261
305
    def call_with_body_bytes(self, args, body):
263
307
 
264
308
        After calling this, call read_response_tuple to find the result out.
265
309
        """
266
 
        bytes = _encode_tuple(args)
267
 
        self._request.accept_bytes(bytes)
 
310
        self._write_args(args)
268
311
        bytes = self._encode_bulk_data(body)
269
312
        self._request.accept_bytes(bytes)
270
313
        self._request.finished_writing()
275
318
        The body is encoded with one line per readv offset pair. The numbers in
276
319
        each pair are separated by a comma, and no trailing \n is emitted.
277
320
        """
278
 
        bytes = _encode_tuple(args)
279
 
        self._request.accept_bytes(bytes)
 
321
        self._write_args(args)
280
322
        readv_bytes = self._serialise_offsets(body)
281
323
        bytes = self._encode_bulk_data(readv_bytes)
282
324
        self._request.accept_bytes(bytes)
322
364
 
323
365
    def _recv_tuple(self):
324
366
        """Receive a tuple from the medium request."""
 
367
        return _decode_tuple(self._recv_line())
 
368
 
 
369
    def _recv_line(self):
 
370
        """Read an entire line from the medium request."""
325
371
        line = ''
326
372
        while not line or line[-1] != '\n':
327
373
            # TODO: this is inefficient - but tuples are short.
328
374
            new_char = self._request.read_bytes(1)
329
375
            line += new_char
330
376
            assert new_char != '', "end of file reading from server."
331
 
        return _decode_tuple(line)
 
377
        return line
332
378
 
333
379
    def query_version(self):
334
380
        """Return protocol version number of the server."""
336
382
        resp = self.read_response_tuple()
337
383
        if resp == ('ok', '1'):
338
384
            return 1
 
385
        elif resp == ('ok', '2'):
 
386
            return 2
339
387
        else:
340
388
            raise errors.SmartProtocolError("bad response %r" % (resp,))
341
389
 
342
 
 
 
390
    def _write_args(self, args):
 
391
        self._write_protocol_version()
 
392
        bytes = _encode_tuple(args)
 
393
        self._request.accept_bytes(bytes)
 
394
 
 
395
    def _write_protocol_version(self):
 
396
        """Write any prefixes this protocol requires.
 
397
        
 
398
        Version one doesn't send protocol versions.
 
399
        """
 
400
 
 
401
 
 
402
class SmartClientRequestProtocolTwo(SmartClientRequestProtocolOne):
 
403
    """Version two of the client side of the smart protocol.
 
404
    
 
405
    This prefixes the request with the value of REQUEST_VERSION_TWO.
 
406
    """
 
407
 
 
408
    def read_response_tuple(self, expect_body=False):
 
409
        """Read a response tuple from the wire.
 
410
 
 
411
        This should only be called once.
 
412
        """
 
413
        version = self._request.read_line()
 
414
        if version != RESPONSE_VERSION_TWO:
 
415
            raise errors.SmartProtocolError('bad protocol marker %r' % version)
 
416
        response_status = self._recv_line()
 
417
        if response_status not in ('success\n', 'failed\n'):
 
418
            raise errors.SmartProtocolError(
 
419
                'bad protocol status %r' % response_status)
 
420
        self.response_status = response_status == 'success\n'
 
421
        return SmartClientRequestProtocolOne.read_response_tuple(self, expect_body)
 
422
 
 
423
    def _write_protocol_version(self):
 
424
        r"""Write any prefixes this protocol requires.
 
425
        
 
426
        Version two sends the value of REQUEST_VERSION_TWO.
 
427
        """
 
428
        self._request.accept_bytes(REQUEST_VERSION_TWO)
343
429