~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/message.py

  • Committer: Jelmer Vernooij
  • Date: 2012-01-27 19:05:43 UTC
  • mto: This revision was merged to the branch mainline in revision 6450.
  • Revision ID: jelmer@samba.org-20120127190543-vk350mv4a0c7aug2
Fix weave test.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
from __future__ import absolute_import
16
18
 
17
19
import collections
18
20
from cStringIO import StringIO
36
38
 
37
39
    def headers_received(self, headers):
38
40
        """Called when message headers are received.
39
 
        
 
41
 
40
42
        This default implementation just stores them in self.headers.
41
43
        """
42
44
        self.headers = headers
67
69
 
68
70
    def protocol_error(self, exception):
69
71
        """Called when there is a protocol decoding error.
70
 
        
 
72
 
71
73
        The default implementation just re-raises the exception.
72
74
        """
73
75
        raise
74
 
    
 
76
 
75
77
    def end_received(self):
76
78
        """Called when the end of the message is received."""
77
79
        # No-op by default.
84
86
    "Conventional" is used in the sense described in
85
87
    doc/developers/network-protocol.txt: a simple message with arguments and an
86
88
    optional body.
 
89
 
 
90
    Possible states:
 
91
     * args: expecting args
 
92
     * body: expecting body (terminated by receiving a post-body status)
 
93
     * error: expecting post-body error
 
94
     * end: expecting end of message
 
95
     * nothing: finished
87
96
    """
88
97
 
89
98
    def __init__(self, request_handler, responder):
90
99
        MessageHandler.__init__(self)
91
100
        self.request_handler = request_handler
92
101
        self.responder = responder
93
 
        self.args_received = False
 
102
        self.expecting = 'args'
 
103
        self._should_finish_body = False
 
104
        self._response_sent = False
94
105
 
95
106
    def protocol_error(self, exception):
96
107
        if self.responder.response_sent:
100
111
        self.responder.send_error(exception)
101
112
 
102
113
    def byte_part_received(self, byte):
103
 
        raise errors.SmartProtocolError(
104
 
            'Unexpected message part: byte(%r)' % (byte,))
 
114
        if self.expecting == 'body':
 
115
            if byte == 'S':
 
116
                # Success.  Nothing more to come except the end of message.
 
117
                self.expecting = 'end'
 
118
            elif byte == 'E':
 
119
                # Error.  Expect an error structure.
 
120
                self.expecting = 'error'
 
121
            else:
 
122
                raise errors.SmartProtocolError(
 
123
                    'Non-success status byte in request body: %r' % (byte,))
 
124
        else:
 
125
            raise errors.SmartProtocolError(
 
126
                'Unexpected message part: byte(%r)' % (byte,))
105
127
 
106
128
    def structure_part_received(self, structure):
107
 
        if self.args_received:
 
129
        if self.expecting == 'args':
 
130
            self._args_received(structure)
 
131
        elif self.expecting == 'error':
 
132
            self._error_received(structure)
 
133
        else:
108
134
            raise errors.SmartProtocolError(
109
135
                'Unexpected message part: structure(%r)' % (structure,))
110
 
        self.args_received = True
111
 
        self.request_handler.dispatch_command(structure[0], structure[1:])
 
136
 
 
137
    def _args_received(self, args):
 
138
        self.expecting = 'body'
 
139
        self.request_handler.args_received(args)
112
140
        if self.request_handler.finished_reading:
 
141
            self._response_sent = True
113
142
            self.responder.send_response(self.request_handler.response)
 
143
            self.expecting = 'end'
 
144
 
 
145
    def _error_received(self, error_args):
 
146
        self.expecting = 'end'
 
147
        self.request_handler.post_body_error_received(error_args)
114
148
 
115
149
    def bytes_part_received(self, bytes):
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.
120
 
        self.request_handler.accept_body(bytes)
121
 
        self.request_handler.end_of_body()
 
150
        if self.expecting == 'body':
 
151
            self._should_finish_body = True
 
152
            self.request_handler.accept_body(bytes)
 
153
        else:
 
154
            raise errors.SmartProtocolError(
 
155
                'Unexpected message part: bytes(%r)' % (bytes,))
 
156
 
 
157
    def end_received(self):
 
158
        if self.expecting not in ['body', 'end']:
 
159
            raise errors.SmartProtocolError(
 
160
                'End of message received prematurely (while expecting %s)'
 
161
                % (self.expecting,))
 
162
        self.expecting = 'nothing'
 
163
        self.request_handler.end_received()
122
164
        if not self.request_handler.finished_reading:
123
 
            raise SmartProtocolError(
124
 
                "Conventional request body was received, but request handler "
125
 
                "has not finished reading.")
126
 
        self.responder.send_response(self.request_handler.response)
 
165
            raise errors.SmartProtocolError(
 
166
                "Complete conventional request was received, but request "
 
167
                "handler has not finished reading.")
 
168
        if not self._response_sent:
 
169
            self.responder.send_response(self.request_handler.response)
127
170
 
128
171
 
129
172
class ResponseHandler(object):
131
174
 
132
175
    def read_response_tuple(self, expect_body=False):
133
176
        """Reads and returns the response tuple for the current request.
134
 
        
 
177
 
135
178
        :keyword expect_body: a boolean indicating if a body is expected in the
136
179
            response.  Some protocol versions needs this information to know
137
180
            when a response is finished.  If False, read_body_bytes should
202
245
        self._bytes_parts.append(bytes)
203
246
 
204
247
    def structure_part_received(self, structure):
205
 
        if type(structure) is not list:
 
248
        if type(structure) is not tuple:
206
249
            raise errors.SmartProtocolError(
207
250
                'Args structure is not a sequence: %r' % (structure,))
208
 
        structure = tuple(structure)
209
251
        if not self._body_started:
210
252
            if self.args is not None:
211
253
                raise errors.SmartProtocolError(
237
279
        bytes = self._medium_request.read_bytes(next_read_size)
238
280
        if bytes == '':
239
281
            # end of file encountered reading from server
 
282
            if 'hpss' in debug.debug_flags:
 
283
                mutter(
 
284
                    'decoder state: buf[:10]=%r, state_accept=%s',
 
285
                    self._protocol_decoder._get_in_buffer()[:10],
 
286
                    self._protocol_decoder.state_accept.__name__)
240
287
            raise errors.ConnectionReset(
241
 
                "please check connectivity and permissions",
242
 
                "(and try -Dhpss if further diagnosis is required)")
 
288
                "Unexpected end of message. "
 
289
                "Please check connectivity and permissions, and report a bug "
 
290
                "if problems persist.")
243
291
        self._protocol_decoder.accept_bytes(bytes)
244
292
 
245
293
    def protocol_error(self, exception):
247
295
        self.finished_reading = True
248
296
        self._medium_request.finished_reading()
249
297
        raise
250
 
        
 
298
 
251
299
    def read_response_tuple(self, expect_body=False):
252
300
        """Read a response tuple from the wire."""
253
301
        self._wait_for_response_args()
257
305
            mutter('   result:   %r', self.args)
258
306
        if self.status == 'E':
259
307
            self._wait_for_response_end()
260
 
            _translate_error(self.args)
 
308
            _raise_smart_server_error(self.args)
261
309
        return tuple(self.args)
262
310
 
263
311
    def read_body_bytes(self, count=-1):
264
312
        """Read bytes from the body, decoding into a byte stream.
265
 
        
266
 
        We read all bytes at once to ensure we've checked the trailer for 
 
313
 
 
314
        We read all bytes at once to ensure we've checked the trailer for
267
315
        errors, and then feed the buffer back as read_body_bytes is called.
268
316
 
269
317
        Like the builtin file.read in Python, a count of -1 (the default) means
284
332
        while not self.finished_reading:
285
333
            while self._bytes_parts:
286
334
                bytes_part = self._bytes_parts.popleft()
287
 
                if 'hpss' in debug.debug_flags:
 
335
                if 'hpssdetail' in debug.debug_flags:
288
336
                    mutter('              %d byte part read', len(bytes_part))
289
337
                yield bytes_part
290
338
            self._read_more()
291
339
        if self._body_stream_status == 'E':
292
 
            _translate_error(self._body_error_args)
 
340
            _raise_smart_server_error(self._body_error_args)
293
341
 
294
342
    def cancel_read_body(self):
295
343
        self._wait_for_response_end()
296
344
 
297
345
 
298
 
def _translate_error(error_tuple):
299
 
    # Many exceptions need some state from the requestor to be properly
300
 
    # translated (e.g. they need a branch object).  So this only translates a
301
 
    # few errors, and the rest are turned into a generic ErrorFromSmartServer.
302
 
    error_name = error_tuple[0]
303
 
    error_args = error_tuple[1:]
304
 
    if error_name == 'UnknownMethod':
305
 
        raise errors.UnknownSmartMethod(error_args[0])
306
 
    if error_name == 'LockContention':
307
 
        raise errors.LockContention('(remote lock)')
308
 
    elif error_name == 'LockFailed':
309
 
        raise errors.LockFailed(*error_args[:2])
310
 
    else:
311
 
        raise errors.ErrorFromSmartServer(error_tuple)
 
346
def _raise_smart_server_error(error_tuple):
 
347
    """Raise exception based on tuple received from smart server
 
348
 
 
349
    Specific error translation is handled by bzrlib.remote._translate_error
 
350
    """
 
351
    if error_tuple[0] == 'UnknownMethod':
 
352
        raise errors.UnknownSmartMethod(error_tuple[1])
 
353
    raise errors.ErrorFromSmartServer(error_tuple)