~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/request.py

  • Committer: Vincent Ladeuil
  • Date: 2011-09-09 13:30:12 UTC
  • mfrom: (5609.48.11 2.3)
  • mto: (6015.33.3 2.4)
  • mto: This revision was merged to the branch mainline in revision 6134.
  • Revision ID: v.ladeuil+lp@free.fr-20110909133012-jc1d1zyqgak57123
Merge 2.3 into 2.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2006-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
31
31
# of a SmartServerRequest subclass.
32
32
 
33
33
 
34
 
import tempfile
35
34
import threading
36
35
 
37
36
from bzrlib import (
38
37
    bzrdir,
 
38
    debug,
39
39
    errors,
 
40
    osutils,
40
41
    registry,
41
42
    revision,
42
43
    trace,
45
46
from bzrlib.lazy_import import lazy_import
46
47
lazy_import(globals(), """
47
48
from bzrlib.bundle import serializer
 
49
 
 
50
import tempfile
 
51
import thread
48
52
""")
49
53
 
50
54
 
86
90
    # XXX: rename this class to BaseSmartServerRequestHandler ?  A request
87
91
    # *handler* is a different concept to the request.
88
92
 
89
 
    def __init__(self, backing_transport, root_client_path='/'):
 
93
    def __init__(self, backing_transport, root_client_path='/', jail_root=None):
90
94
        """Constructor.
91
95
 
92
96
        :param backing_transport: the base transport to be used when performing
96
100
            from the client.  Clients will not be able to refer to paths above
97
101
            this root.  If root_client_path is None, then no translation will
98
102
            be performed on client paths.  Default is '/'.
 
103
        :param jail_root: if specified, the root of the BzrDir.open jail to use
 
104
            instead of backing_transport.
99
105
        """
100
106
        self._backing_transport = backing_transport
 
107
        if jail_root is None:
 
108
            jail_root = backing_transport
 
109
        self._jail_root = jail_root
101
110
        if root_client_path is not None:
102
111
            if not root_client_path.startswith('/'):
103
112
                root_client_path = '/' + root_client_path
126
135
        It will return a SmartServerResponse if the command does not expect a
127
136
        body.
128
137
 
129
 
        :param *args: the arguments of the request.
 
138
        :param args: the arguments of the request.
130
139
        """
131
140
        self._check_enabled()
132
141
        return self.do(*args)
155
164
        return self.do_body(body_bytes)
156
165
 
157
166
    def setup_jail(self):
158
 
        jail_info.transports = [self._backing_transport]
 
167
        jail_info.transports = [self._jail_root]
159
168
 
160
169
    def teardown_jail(self):
161
170
        jail_info.transports = None
183
192
            relpath = urlutils.joinpath('/', path)
184
193
            if not relpath.startswith('/'):
185
194
                raise ValueError(relpath)
186
 
            return '.' + relpath
 
195
            return urlutils.escape('.' + relpath)
187
196
        else:
188
197
            raise errors.PathNotChild(client_path, self._root_client_path)
189
198
 
265
274
    # TODO: Better way of representing the body for commands that take it,
266
275
    # and allow it to be streamed into the server.
267
276
 
268
 
    def __init__(self, backing_transport, commands, root_client_path):
 
277
    def __init__(self, backing_transport, commands, root_client_path,
 
278
        jail_root=None):
269
279
        """Constructor.
270
280
 
271
281
        :param backing_transport: a Transport to handle requests for.
275
285
        self._backing_transport = backing_transport
276
286
        self._root_client_path = root_client_path
277
287
        self._commands = commands
 
288
        if jail_root is None:
 
289
            jail_root = backing_transport
 
290
        self._jail_root = jail_root
278
291
        self.response = None
279
292
        self.finished_reading = False
280
293
        self._command = None
 
294
        if 'hpss' in debug.debug_flags:
 
295
            self._request_start_time = osutils.timer_func()
 
296
            self._thread_id = thread.get_ident()
 
297
 
 
298
    def _trace(self, action, message, extra_bytes=None, include_time=False):
 
299
        # It is a bit of a shame that this functionality overlaps with that of 
 
300
        # ProtocolThreeRequester._trace. However, there is enough difference
 
301
        # that just putting it in a helper doesn't help a lot. And some state
 
302
        # is taken from the instance.
 
303
        if include_time:
 
304
            t = '%5.3fs ' % (osutils.timer_func() - self._request_start_time)
 
305
        else:
 
306
            t = ''
 
307
        if extra_bytes is None:
 
308
            extra = ''
 
309
        else:
 
310
            extra = ' ' + repr(extra_bytes[:40])
 
311
            if len(extra) > 33:
 
312
                extra = extra[:29] + extra[-1] + '...'
 
313
        trace.mutter('%12s: [%s] %s%s%s'
 
314
                     % (action, self._thread_id, t, message, extra))
281
315
 
282
316
    def accept_body(self, bytes):
283
317
        """Accept body data."""
285
319
            # no active command object, so ignore the event.
286
320
            return
287
321
        self._run_handler_code(self._command.do_chunk, (bytes,), {})
 
322
        if 'hpss' in debug.debug_flags:
 
323
            self._trace('accept body',
 
324
                        '%d bytes' % (len(bytes),), bytes)
288
325
 
289
326
    def end_of_body(self):
290
327
        """No more body data will be received."""
291
328
        self._run_handler_code(self._command.do_end, (), {})
292
329
        # cannot read after this.
293
330
        self.finished_reading = True
294
 
 
295
 
    def dispatch_command(self, cmd, args):
296
 
        """Deprecated compatibility method.""" # XXX XXX
297
 
        try:
298
 
            command = self._commands.get(cmd)
299
 
        except LookupError:
300
 
            raise errors.UnknownSmartMethod(cmd)
301
 
        self._command = command(self._backing_transport, self._root_client_path)
302
 
        self._run_handler_code(self._command.execute, args, {})
 
331
        if 'hpss' in debug.debug_flags:
 
332
            self._trace('end of body', '', include_time=True)
303
333
 
304
334
    def _run_handler_code(self, callable, args, kwargs):
305
335
        """Run some handler specific code 'callable'.
334
364
 
335
365
    def headers_received(self, headers):
336
366
        # Just a no-op at the moment.
337
 
        pass
 
367
        if 'hpss' in debug.debug_flags:
 
368
            self._trace('headers', repr(headers))
338
369
 
339
370
    def args_received(self, args):
340
371
        cmd = args[0]
342
373
        try:
343
374
            command = self._commands.get(cmd)
344
375
        except LookupError:
 
376
            if 'hpss' in debug.debug_flags:
 
377
                self._trace('hpss unknown request', 
 
378
                            cmd, repr(args)[1:-1])
345
379
            raise errors.UnknownSmartMethod(cmd)
346
 
        self._command = command(self._backing_transport)
 
380
        if 'hpss' in debug.debug_flags:
 
381
            from bzrlib.smart import vfs
 
382
            if issubclass(command, vfs.VfsRequest):
 
383
                action = 'hpss vfs req'
 
384
            else:
 
385
                action = 'hpss request'
 
386
            self._trace(action, 
 
387
                        '%s %s' % (cmd, repr(args)[1:-1]))
 
388
        self._command = command(
 
389
            self._backing_transport, self._root_client_path, self._jail_root)
347
390
        self._run_handler_code(self._command.execute, args, {})
348
391
 
349
392
    def end_received(self):
351
394
            # no active command object, so ignore the event.
352
395
            return
353
396
        self._run_handler_code(self._command.do_end, (), {})
 
397
        if 'hpss' in debug.debug_flags:
 
398
            self._trace('end', '', include_time=True)
354
399
 
355
400
    def post_body_error_received(self, error_args):
356
401
        # Just a no-op at the moment.
364
409
        return ('FileExists', err.path)
365
410
    elif isinstance(err, errors.DirectoryNotEmpty):
366
411
        return ('DirectoryNotEmpty', err.path)
 
412
    elif isinstance(err, errors.IncompatibleRepositories):
 
413
        return ('IncompatibleRepositories', str(err.source), str(err.target),
 
414
            str(err.details))
367
415
    elif isinstance(err, errors.ShortReadvError):
368
416
        return ('ShortReadvError', err.path, str(err.offset), str(err.length),
369
417
                str(err.actual))
399
447
        return ('TokenMismatch', err.given_token, err.lock_token)
400
448
    elif isinstance(err, errors.LockContention):
401
449
        return ('LockContention',)
 
450
    elif isinstance(err, MemoryError):
 
451
        # GZ 2011-02-24: Copy bzrlib.trace -Dmem_dump functionality here?
 
452
        return ('MemoryError',)
402
453
    # Unserialisable error.  Log it, and return a generic error
403
454
    trace.log_exception_quietly()
404
 
    return ('error', str(err))
 
455
    return ('error', trace._qualified_exception_name(err.__class__, True),
 
456
        str(err))
405
457
 
406
458
 
407
459
class HelloRequest(SmartServerRequest):
454
506
    'Branch.set_tags_bytes', 'bzrlib.smart.branch',
455
507
    'SmartServerBranchSetTagsBytes')
456
508
request_handlers.register_lazy(
 
509
    'Branch.heads_to_fetch', 'bzrlib.smart.branch',
 
510
    'SmartServerBranchHeadsToFetch')
 
511
request_handlers.register_lazy(
457
512
    'Branch.get_stacked_on_url', 'bzrlib.smart.branch', 'SmartServerBranchRequestGetStackedOnURL')
458
513
request_handlers.register_lazy(
459
514
    'Branch.last_revision_info', 'bzrlib.smart.branch', 'SmartServerBranchRequestLastRevisionInfo')
463
518
    'bzrlib.smart.branch', 'SmartServerRequestRevisionHistory')
464
519
request_handlers.register_lazy( 'Branch.set_config_option',
465
520
    'bzrlib.smart.branch', 'SmartServerBranchRequestSetConfigOption')
 
521
request_handlers.register_lazy( 'Branch.set_config_option_dict',
 
522
    'bzrlib.smart.branch', 'SmartServerBranchRequestSetConfigOptionDict')
466
523
request_handlers.register_lazy( 'Branch.set_last_revision',
467
524
    'bzrlib.smart.branch', 'SmartServerBranchRequestSetLastRevision')
468
525
request_handlers.register_lazy(
506
563
request_handlers.register_lazy(
507
564
    'BzrDir.open', 'bzrlib.smart.bzrdir', 'SmartServerRequestOpenBzrDir')
508
565
request_handlers.register_lazy(
 
566
    'BzrDir.open_2.1', 'bzrlib.smart.bzrdir', 'SmartServerRequestOpenBzrDir_2_1')
 
567
request_handlers.register_lazy(
509
568
    'BzrDir.open_branch', 'bzrlib.smart.bzrdir',
510
569
    'SmartServerRequestOpenBranch')
511
570
request_handlers.register_lazy(
512
571
    'BzrDir.open_branchV2', 'bzrlib.smart.bzrdir',
513
572
    'SmartServerRequestOpenBranchV2')
514
573
request_handlers.register_lazy(
 
574
    'BzrDir.open_branchV3', 'bzrlib.smart.bzrdir',
 
575
    'SmartServerRequestOpenBranchV3')
 
576
request_handlers.register_lazy(
515
577
    'delete', 'bzrlib.smart.vfs', 'DeleteRequest')
516
578
request_handlers.register_lazy(
517
579
    'get', 'bzrlib.smart.vfs', 'GetRequest')
553
615
request_handlers.register_lazy(
554
616
    'Repository.insert_stream', 'bzrlib.smart.repository', 'SmartServerRepositoryInsertStream')
555
617
request_handlers.register_lazy(
 
618
    'Repository.insert_stream_1.19', 'bzrlib.smart.repository', 'SmartServerRepositoryInsertStream_1_19')
 
619
request_handlers.register_lazy(
556
620
    'Repository.insert_stream_locked', 'bzrlib.smart.repository', 'SmartServerRepositoryInsertStreamLocked')
557
621
request_handlers.register_lazy(
558
622
    'Repository.is_shared', 'bzrlib.smart.repository', 'SmartServerRepositoryIsShared')
570
634
    'Repository.get_stream', 'bzrlib.smart.repository',
571
635
    'SmartServerRepositoryGetStream')
572
636
request_handlers.register_lazy(
 
637
    'Repository.get_stream_1.19', 'bzrlib.smart.repository',
 
638
    'SmartServerRepositoryGetStream_1_19')
 
639
request_handlers.register_lazy(
573
640
    'Repository.tarball', 'bzrlib.smart.repository',
574
641
    'SmartServerRepositoryTarball')
575
642
request_handlers.register_lazy(