~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/request.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-03-02 06:21:02 UTC
  • mfrom: (4064.1.4 streaming-body-error)
  • Revision ID: pqm@pqm.ubuntu.com-20090302062102-9hcytxohu3q8qxan
Improve error-handling while sending body_streams in HPSS requests
        and responses. (Andrew Bennetts)

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
    errors,
34
34
    registry,
35
35
    revision,
 
36
    trace,
36
37
    urlutils,
37
38
    )
38
39
from bzrlib.lazy_import import lazy_import
277
278
        # be in SmartServerVFSRequestHandler somewhere.
278
279
        try:
279
280
            return callable(*args, **kwargs)
280
 
        except errors.NoSuchFile, e:
281
 
            return FailedSmartServerResponse(('NoSuchFile', e.path))
282
 
        except errors.FileExists, e:
283
 
            return FailedSmartServerResponse(('FileExists', e.path))
284
 
        except errors.DirectoryNotEmpty, e:
285
 
            return FailedSmartServerResponse(('DirectoryNotEmpty', e.path))
286
 
        except errors.ShortReadvError, e:
287
 
            return FailedSmartServerResponse(('ShortReadvError',
288
 
                e.path, str(e.offset), str(e.length), str(e.actual)))
289
 
        except errors.UnstackableRepositoryFormat, e:
290
 
            return FailedSmartServerResponse(('UnstackableRepositoryFormat',
291
 
                str(e.format), e.url))
292
 
        except errors.UnstackableBranchFormat, e:
293
 
            return FailedSmartServerResponse(('UnstackableBranchFormat',
294
 
                str(e.format), e.url))
295
 
        except errors.NotStacked, e:
296
 
            return FailedSmartServerResponse(('NotStacked',))
297
 
        except UnicodeError, e:
298
 
            # If it is a DecodeError, than most likely we are starting
299
 
            # with a plain string
300
 
            str_or_unicode = e.object
301
 
            if isinstance(str_or_unicode, unicode):
302
 
                # XXX: UTF-8 might have \x01 (our protocol v1 and v2 seperator
303
 
                # byte) in it, so this encoding could cause broken responses.
304
 
                # Newer clients use protocol v3, so will be fine.
305
 
                val = 'u:' + str_or_unicode.encode('utf-8')
306
 
            else:
307
 
                val = 's:' + str_or_unicode.encode('base64')
308
 
            # This handles UnicodeEncodeError or UnicodeDecodeError
309
 
            return FailedSmartServerResponse((e.__class__.__name__,
310
 
                    e.encoding, val, str(e.start), str(e.end), e.reason))
311
 
        except errors.TransportNotPossible, e:
312
 
            if e.msg == "readonly transport":
313
 
                return FailedSmartServerResponse(('ReadOnlyError', ))
314
 
            else:
315
 
                raise
316
 
        except errors.ReadError, e:
317
 
            # cannot read the file
318
 
            return FailedSmartServerResponse(('ReadError', e.path))
319
 
        except errors.PermissionDenied, e:
320
 
            return FailedSmartServerResponse(
321
 
                ('PermissionDenied', e.path, e.extra))
 
281
        except (KeyboardInterrupt, SystemExit):
 
282
            raise
 
283
        except Exception, err:
 
284
            err_struct = _translate_error(err)
 
285
            return FailedSmartServerResponse(err_struct)
322
286
 
323
287
    def headers_received(self, headers):
324
288
        # Just a no-op at the moment.
342
306
        pass
343
307
 
344
308
 
 
309
def _translate_error(err):
 
310
    if isinstance(err, errors.NoSuchFile):
 
311
        return ('NoSuchFile', err.path)
 
312
    elif isinstance(err, errors.FileExists):
 
313
        return ('FileExists', err.path)
 
314
    elif isinstance(err, errors.DirectoryNotEmpty):
 
315
        return ('DirectoryNotEmpty', err.path)
 
316
    elif isinstance(err, errors.ShortReadvError):
 
317
        return ('ShortReadvError', err.path, str(err.offset), str(err.length),
 
318
                str(err.actual))
 
319
    elif isinstance(err, errors.UnstackableRepositoryFormat):
 
320
        return (('UnstackableRepositoryFormat', str(err.format), err.url))
 
321
    elif isinstance(err, errors.UnstackableBranchFormat):
 
322
        return ('UnstackableBranchFormat', str(err.format), err.url)
 
323
    elif isinstance(err, errors.NotStacked):
 
324
        return ('NotStacked',)
 
325
    elif isinstance(err, UnicodeError):
 
326
        # If it is a DecodeError, than most likely we are starting
 
327
        # with a plain string
 
328
        str_or_unicode = err.object
 
329
        if isinstance(str_or_unicode, unicode):
 
330
            # XXX: UTF-8 might have \x01 (our protocol v1 and v2 seperator
 
331
            # byte) in it, so this encoding could cause broken responses.
 
332
            # Newer clients use protocol v3, so will be fine.
 
333
            val = 'u:' + str_or_unicode.encode('utf-8')
 
334
        else:
 
335
            val = 's:' + str_or_unicode.encode('base64')
 
336
        # This handles UnicodeEncodeError or UnicodeDecodeError
 
337
        return (err.__class__.__name__, err.encoding, val, str(err.start),
 
338
                str(err.end), err.reason)
 
339
    elif isinstance(err, errors.TransportNotPossible):
 
340
        if err.msg == "readonly transport":
 
341
            return ('ReadOnlyError', )
 
342
    elif isinstance(err, errors.ReadError):
 
343
        # cannot read the file
 
344
        return ('ReadError', err.path)
 
345
    elif isinstance(err, errors.PermissionDenied):
 
346
        return ('PermissionDenied', err.path, err.extra)
 
347
    # Unserialisable error.  Log it, and return a generic error
 
348
    trace.log_exception_quietly()
 
349
    return ('error', str(err))
 
350
 
 
351
 
345
352
class HelloRequest(SmartServerRequest):
346
353
    """Answer a version request with the highest protocol version this server
347
354
    supports.