/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/smart/protocol.py

merge bzr.dev r4154

Show diffs side-by-side

added added

removed removed

Lines of Context:
1060
1060
    response_marker = request_marker = MESSAGE_VERSION_THREE
1061
1061
 
1062
1062
    def __init__(self, write_func):
1063
 
        self._buf = ''
 
1063
        self._buf = []
1064
1064
        self._real_write_func = write_func
1065
1065
 
1066
1066
    def _write_func(self, bytes):
1067
 
        self._buf += bytes
 
1067
        self._buf.append(bytes)
 
1068
        if len(self._buf) > 100:
 
1069
            self.flush()
1068
1070
 
1069
1071
    def flush(self):
1070
1072
        if self._buf:
1071
 
            self._real_write_func(self._buf)
1072
 
            self._buf = ''
 
1073
            self._real_write_func(''.join(self._buf))
 
1074
            del self._buf[:]
1073
1075
 
1074
1076
    def _serialise_offsets(self, offsets):
1075
1077
        """Serialise a readv offset list."""
1158
1160
        if response.body is not None:
1159
1161
            self._write_prefixed_body(response.body)
1160
1162
        elif response.body_stream is not None:
1161
 
            for chunk in response.body_stream:
1162
 
                self._write_prefixed_body(chunk)
1163
 
                self.flush()
 
1163
            for exc_info, chunk in _iter_with_errors(response.body_stream):
 
1164
                if exc_info is not None:
 
1165
                    self._write_error_status()
 
1166
                    error_struct = request._translate_error(exc_info[1])
 
1167
                    self._write_structure(error_struct)
 
1168
                    break
 
1169
                else:
 
1170
                    if isinstance(chunk, request.FailedSmartServerResponse):
 
1171
                        self._write_error_status()
 
1172
                        self._write_structure(chunk.args)
 
1173
                        break
 
1174
                    self._write_prefixed_body(chunk)
1164
1175
        self._write_end()
1165
1176
 
1166
1177
 
 
1178
def _iter_with_errors(iterable):
 
1179
    """Handle errors from iterable.next().
 
1180
 
 
1181
    Use like::
 
1182
 
 
1183
        for exc_info, value in _iter_with_errors(iterable):
 
1184
            ...
 
1185
 
 
1186
    This is a safer alternative to::
 
1187
 
 
1188
        try:
 
1189
            for value in iterable:
 
1190
               ...
 
1191
        except:
 
1192
            ...
 
1193
 
 
1194
    Because the latter will catch errors from the for-loop body, not just
 
1195
    iterable.next()
 
1196
 
 
1197
    If an error occurs, exc_info will be a exc_info tuple, and the generator
 
1198
    will terminate.  Otherwise exc_info will be None, and value will be the
 
1199
    value from iterable.next().  Note that KeyboardInterrupt and SystemExit
 
1200
    will not be itercepted.
 
1201
    """
 
1202
    iterator = iter(iterable)
 
1203
    while True:
 
1204
        try:
 
1205
            yield None, iterator.next()
 
1206
        except StopIteration:
 
1207
            return
 
1208
        except (KeyboardInterrupt, SystemExit):
 
1209
            raise
 
1210
        except Exception:
 
1211
            yield sys.exc_info(), None
 
1212
            return
 
1213
 
 
1214
 
1167
1215
class ProtocolThreeRequester(_ProtocolThreeEncoder, Requester):
1168
1216
 
1169
1217
    def __init__(self, medium_request):
1242
1290
        #       have finished sending the stream.  We would notice at the end
1243
1291
        #       anyway, but if the medium can deliver it early then it's good
1244
1292
        #       to short-circuit the whole request...
1245
 
        try:
1246
 
            for part in stream:
 
1293
        for exc_info, part in _iter_with_errors(stream):
 
1294
            if exc_info is not None:
 
1295
                # Iterating the stream failed.  Cleanly abort the request.
 
1296
                self._write_error_status()
 
1297
                # Currently the client unconditionally sends ('error',) as the
 
1298
                # error args.
 
1299
                self._write_structure(('error',))
 
1300
                self._write_end()
 
1301
                self._medium_request.finished_writing()
 
1302
                raise exc_info[0], exc_info[1], exc_info[2]
 
1303
            else:
1247
1304
                self._write_prefixed_body(part)
1248
1305
                self.flush()
1249
 
        except Exception:
1250
 
            exc_info = sys.exc_info()
1251
 
            # Iterating the stream failed.  Cleanly abort the request.
1252
 
            self._write_error_status()
1253
 
            # Currently the client unconditionally sends ('error',) as the
1254
 
            # error args.
1255
 
            self._write_structure(('error',))
1256
 
            self._write_end()
1257
 
            self._medium_request.finished_writing()
1258
 
            raise exc_info[0], exc_info[1], exc_info[2]
1259
1306
        self._write_end()
1260
1307
        self._medium_request.finished_writing()
1261
1308