~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/request.py

  • Committer: Vincent Ladeuil
  • Date: 2010-02-09 20:33:43 UTC
  • mto: (5029.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 5030.
  • Revision ID: v.ladeuil+lp@free.fr-20100209203343-ktxx7t0xvptvjnt1
Move TestingPathFilteringServer to bzrlib.tests.test_server

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
 
33
33
 
34
34
import tempfile
 
35
import thread
35
36
import threading
36
37
 
37
38
from bzrlib import (
38
39
    bzrdir,
 
40
    debug,
39
41
    errors,
 
42
    osutils,
40
43
    registry,
41
44
    revision,
42
45
    trace,
86
89
    # XXX: rename this class to BaseSmartServerRequestHandler ?  A request
87
90
    # *handler* is a different concept to the request.
88
91
 
89
 
    def __init__(self, backing_transport, root_client_path='/'):
 
92
    def __init__(self, backing_transport, root_client_path='/', jail_root=None):
90
93
        """Constructor.
91
94
 
92
95
        :param backing_transport: the base transport to be used when performing
96
99
            from the client.  Clients will not be able to refer to paths above
97
100
            this root.  If root_client_path is None, then no translation will
98
101
            be performed on client paths.  Default is '/'.
 
102
        :param jail_root: if specified, the root of the BzrDir.open jail to use
 
103
            instead of backing_transport.
99
104
        """
100
105
        self._backing_transport = backing_transport
 
106
        if jail_root is None:
 
107
            jail_root = backing_transport
 
108
        self._jail_root = jail_root
101
109
        if root_client_path is not None:
102
110
            if not root_client_path.startswith('/'):
103
111
                root_client_path = '/' + root_client_path
155
163
        return self.do_body(body_bytes)
156
164
 
157
165
    def setup_jail(self):
158
 
        jail_info.transports = [self._backing_transport]
 
166
        jail_info.transports = [self._jail_root]
159
167
 
160
168
    def teardown_jail(self):
161
169
        jail_info.transports = None
183
191
            relpath = urlutils.joinpath('/', path)
184
192
            if not relpath.startswith('/'):
185
193
                raise ValueError(relpath)
186
 
            return '.' + relpath
 
194
            return urlutils.escape('.' + relpath)
187
195
        else:
188
196
            raise errors.PathNotChild(client_path, self._root_client_path)
189
197
 
265
273
    # TODO: Better way of representing the body for commands that take it,
266
274
    # and allow it to be streamed into the server.
267
275
 
268
 
    def __init__(self, backing_transport, commands, root_client_path):
 
276
    def __init__(self, backing_transport, commands, root_client_path,
 
277
        jail_root=None):
269
278
        """Constructor.
270
279
 
271
280
        :param backing_transport: a Transport to handle requests for.
275
284
        self._backing_transport = backing_transport
276
285
        self._root_client_path = root_client_path
277
286
        self._commands = commands
 
287
        if jail_root is None:
 
288
            jail_root = backing_transport
 
289
        self._jail_root = jail_root
278
290
        self.response = None
279
291
        self.finished_reading = False
280
292
        self._command = None
 
293
        if 'hpss' in debug.debug_flags:
 
294
            self._request_start_time = osutils.timer_func()
 
295
            self._thread_id = thread.get_ident()
 
296
 
 
297
    def _trace(self, action, message, extra_bytes=None, include_time=False):
 
298
        # It is a bit of a shame that this functionality overlaps with that of 
 
299
        # ProtocolThreeRequester._trace. However, there is enough difference
 
300
        # that just putting it in a helper doesn't help a lot. And some state
 
301
        # is taken from the instance.
 
302
        if include_time:
 
303
            t = '%5.3fs ' % (osutils.timer_func() - self._request_start_time)
 
304
        else:
 
305
            t = ''
 
306
        if extra_bytes is None:
 
307
            extra = ''
 
308
        else:
 
309
            extra = ' ' + repr(extra_bytes[:40])
 
310
            if len(extra) > 33:
 
311
                extra = extra[:29] + extra[-1] + '...'
 
312
        trace.mutter('%12s: [%s] %s%s%s'
 
313
                     % (action, self._thread_id, t, message, extra))
281
314
 
282
315
    def accept_body(self, bytes):
283
316
        """Accept body data."""
285
318
            # no active command object, so ignore the event.
286
319
            return
287
320
        self._run_handler_code(self._command.do_chunk, (bytes,), {})
 
321
        if 'hpss' in debug.debug_flags:
 
322
            self._trace('accept body',
 
323
                        '%d bytes' % (len(bytes),), bytes)
288
324
 
289
325
    def end_of_body(self):
290
326
        """No more body data will be received."""
291
327
        self._run_handler_code(self._command.do_end, (), {})
292
328
        # cannot read after this.
293
329
        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, {})
 
330
        if 'hpss' in debug.debug_flags:
 
331
            self._trace('end of body', '', include_time=True)
303
332
 
304
333
    def _run_handler_code(self, callable, args, kwargs):
305
334
        """Run some handler specific code 'callable'.
334
363
 
335
364
    def headers_received(self, headers):
336
365
        # Just a no-op at the moment.
337
 
        pass
 
366
        if 'hpss' in debug.debug_flags:
 
367
            self._trace('headers', repr(headers))
338
368
 
339
369
    def args_received(self, args):
340
370
        cmd = args[0]
342
372
        try:
343
373
            command = self._commands.get(cmd)
344
374
        except LookupError:
 
375
            if 'hpss' in debug.debug_flags:
 
376
                self._trace('hpss unknown request', 
 
377
                            cmd, repr(args)[1:-1])
345
378
            raise errors.UnknownSmartMethod(cmd)
346
 
        self._command = command(self._backing_transport)
 
379
        if 'hpss' in debug.debug_flags:
 
380
            from bzrlib.smart import vfs
 
381
            if issubclass(command, vfs.VfsRequest):
 
382
                action = 'hpss vfs req'
 
383
            else:
 
384
                action = 'hpss request'
 
385
            self._trace(action, 
 
386
                        '%s %s' % (cmd, repr(args)[1:-1]))
 
387
        self._command = command(
 
388
            self._backing_transport, self._root_client_path, self._jail_root)
347
389
        self._run_handler_code(self._command.execute, args, {})
348
390
 
349
391
    def end_received(self):
351
393
            # no active command object, so ignore the event.
352
394
            return
353
395
        self._run_handler_code(self._command.do_end, (), {})
 
396
        if 'hpss' in debug.debug_flags:
 
397
            self._trace('end', '', include_time=True)
354
398
 
355
399
    def post_body_error_received(self, error_args):
356
400
        # Just a no-op at the moment.
364
408
        return ('FileExists', err.path)
365
409
    elif isinstance(err, errors.DirectoryNotEmpty):
366
410
        return ('DirectoryNotEmpty', err.path)
 
411
    elif isinstance(err, errors.IncompatibleRepositories):
 
412
        return ('IncompatibleRepositories', str(err.source), str(err.target),
 
413
            str(err.details))
367
414
    elif isinstance(err, errors.ShortReadvError):
368
415
        return ('ShortReadvError', err.path, str(err.offset), str(err.length),
369
416
                str(err.actual))
506
553
request_handlers.register_lazy(
507
554
    'BzrDir.open', 'bzrlib.smart.bzrdir', 'SmartServerRequestOpenBzrDir')
508
555
request_handlers.register_lazy(
 
556
    'BzrDir.open_2.1', 'bzrlib.smart.bzrdir', 'SmartServerRequestOpenBzrDir_2_1')
 
557
request_handlers.register_lazy(
509
558
    'BzrDir.open_branch', 'bzrlib.smart.bzrdir',
510
559
    'SmartServerRequestOpenBranch')
511
560
request_handlers.register_lazy(
512
561
    'BzrDir.open_branchV2', 'bzrlib.smart.bzrdir',
513
562
    'SmartServerRequestOpenBranchV2')
514
563
request_handlers.register_lazy(
 
564
    'BzrDir.open_branchV3', 'bzrlib.smart.bzrdir',
 
565
    'SmartServerRequestOpenBranchV3')
 
566
request_handlers.register_lazy(
515
567
    'delete', 'bzrlib.smart.vfs', 'DeleteRequest')
516
568
request_handlers.register_lazy(
517
569
    'get', 'bzrlib.smart.vfs', 'GetRequest')
553
605
request_handlers.register_lazy(
554
606
    'Repository.insert_stream', 'bzrlib.smart.repository', 'SmartServerRepositoryInsertStream')
555
607
request_handlers.register_lazy(
 
608
    'Repository.insert_stream_1.19', 'bzrlib.smart.repository', 'SmartServerRepositoryInsertStream_1_19')
 
609
request_handlers.register_lazy(
556
610
    'Repository.insert_stream_locked', 'bzrlib.smart.repository', 'SmartServerRepositoryInsertStreamLocked')
557
611
request_handlers.register_lazy(
558
612
    'Repository.is_shared', 'bzrlib.smart.repository', 'SmartServerRepositoryIsShared')
570
624
    'Repository.get_stream', 'bzrlib.smart.repository',
571
625
    'SmartServerRepositoryGetStream')
572
626
request_handlers.register_lazy(
 
627
    'Repository.get_stream_1.19', 'bzrlib.smart.repository',
 
628
    'SmartServerRepositoryGetStream_1_19')
 
629
request_handlers.register_lazy(
573
630
    'Repository.tarball', 'bzrlib.smart.repository',
574
631
    'SmartServerRepositoryTarball')
575
632
request_handlers.register_lazy(