~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/message.py

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil
  • Date: 2017-01-30 14:42:05 UTC
  • mfrom: (6620.1.1 trunk)
  • Revision ID: tarmac-20170130144205-r8fh2xpmiuxyozpv
Merge  2.7 into trunk including fix for bug #1657238 [r=vila]

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
165
            raise errors.SmartProtocolError(
124
 
                "Conventional request body was received, but request handler "
125
 
                "has not finished reading.")
126
 
        self.responder.send_response(self.request_handler.response)
 
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(
243
285
                    self._protocol_decoder._get_in_buffer()[:10],
244
286
                    self._protocol_decoder.state_accept.__name__)
245
287
            raise errors.ConnectionReset(
246
 
                "please check connectivity and permissions",
247
 
                "(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.")
248
291
        self._protocol_decoder.accept_bytes(bytes)
249
292
 
250
293
    def protocol_error(self, exception):
252
295
        self.finished_reading = True
253
296
        self._medium_request.finished_reading()
254
297
        raise
255
 
        
 
298
 
256
299
    def read_response_tuple(self, expect_body=False):
257
300
        """Read a response tuple from the wire."""
258
301
        self._wait_for_response_args()
262
305
            mutter('   result:   %r', self.args)
263
306
        if self.status == 'E':
264
307
            self._wait_for_response_end()
265
 
            _translate_error(self.args)
 
308
            _raise_smart_server_error(self.args)
266
309
        return tuple(self.args)
267
310
 
268
311
    def read_body_bytes(self, count=-1):
269
312
        """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 
 
313
 
 
314
        We read all bytes at once to ensure we've checked the trailer for
272
315
        errors, and then feed the buffer back as read_body_bytes is called.
273
316
 
274
317
        Like the builtin file.read in Python, a count of -1 (the default) means
289
332
        while not self.finished_reading:
290
333
            while self._bytes_parts:
291
334
                bytes_part = self._bytes_parts.popleft()
292
 
                if 'hpss' in debug.debug_flags:
 
335
                if 'hpssdetail' in debug.debug_flags:
293
336
                    mutter('              %d byte part read', len(bytes_part))
294
337
                yield bytes_part
295
338
            self._read_more()
296
339
        if self._body_stream_status == 'E':
297
 
            _translate_error(self._body_error_args)
 
340
            _raise_smart_server_error(self._body_error_args)
298
341
 
299
342
    def cancel_read_body(self):
300
343
        self._wait_for_response_end()
301
344
 
302
345
 
303
 
def _translate_error(error_tuple):
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.
307
 
    error_name = error_tuple[0]
308
 
    error_args = error_tuple[1:]
309
 
    if error_name == 'UnknownMethod':
310
 
        raise errors.UnknownSmartMethod(error_args[0])
311
 
    if error_name == 'LockContention':
312
 
        raise errors.LockContention('(remote lock)')
313
 
    elif error_name == 'LockFailed':
314
 
        raise errors.LockFailed(*error_args[:2])
315
 
    else:
316
 
        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)