~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/message.py

  • Committer: Vincent Ladeuil
  • Date: 2008-09-11 19:36:38 UTC
  • mfrom: (3703 +trunk)
  • mto: (3705.1.1 trunk2)
  • mto: This revision was merged to the branch mainline in revision 3708.
  • Revision ID: v.ladeuil+lp@free.fr-20080911193638-wtjyc1kcmacc6t1f
merge bzr.dev

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