~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/medium.py

  • Committer: Vincent Ladeuil
  • Date: 2010-04-23 08:51:52 UTC
  • mfrom: (5131.2.6 support_OO_flag)
  • mto: This revision was merged to the branch mainline in revision 5179.
  • Revision ID: v.ladeuil+lp@free.fr-20100423085152-uoewc1vnkwqhw0pj
Manually assign docstrings to command objects, so that they work with python -OO

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 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
24
24
bzrlib/transport/smart/__init__.py.
25
25
"""
26
26
 
27
 
import errno
28
27
import os
29
 
import socket
30
28
import sys
31
29
import urllib
32
30
 
33
31
from bzrlib.lazy_import import lazy_import
34
32
lazy_import(globals(), """
35
33
import atexit
 
34
import socket
 
35
import thread
36
36
import weakref
 
37
 
37
38
from bzrlib import (
38
39
    debug,
39
40
    errors,
40
 
    osutils,
41
41
    symbol_versioning,
42
42
    trace,
43
43
    ui,
44
44
    urlutils,
45
45
    )
46
 
from bzrlib.smart import client, protocol
 
46
from bzrlib.smart import client, protocol, request, vfs
47
47
from bzrlib.transport import ssh
48
48
""")
49
 
 
50
 
 
51
 
# We must not read any more than 64k at a time so we don't risk "no buffer
52
 
# space available" errors on some platforms.  Windows in particular is likely
53
 
# to give error 10053 or 10055 if we read more than 64k from a socket.
54
 
_MAX_READ_SIZE = 64 * 1024
55
 
 
 
49
from bzrlib import osutils
 
50
 
 
51
# Throughout this module buffer size parameters are either limited to be at
 
52
# most _MAX_READ_SIZE, or are ignored and _MAX_READ_SIZE is used instead.
 
53
# For this module's purposes, MAX_SOCKET_CHUNK is a reasonable size for reads
 
54
# from non-sockets as well.
 
55
_MAX_READ_SIZE = osutils.MAX_SOCKET_CHUNK
56
56
 
57
57
def _get_protocol_factory_for_bytes(bytes):
58
58
    """Determine the right protocol factory for 'bytes'.
274
274
    def _serve_one_request_unguarded(self, protocol):
275
275
        while protocol.next_read_size():
276
276
            # We can safely try to read large chunks.  If there is less data
277
 
            # than _MAX_READ_SIZE ready, the socket wil just return a short
278
 
            # read immediately rather than block.
279
 
            bytes = self.read_bytes(_MAX_READ_SIZE)
 
277
            # than MAX_SOCKET_CHUNK ready, the socket will just return a
 
278
            # short read immediately rather than block.
 
279
            bytes = self.read_bytes(osutils.MAX_SOCKET_CHUNK)
280
280
            if bytes == '':
281
281
                self.finished = True
282
282
                return
285
285
        self._push_back(protocol.unused_data)
286
286
 
287
287
    def _read_bytes(self, desired_count):
288
 
        # We ignore the desired_count because on sockets it's more efficient to
289
 
        # read large chunks (of _MAX_READ_SIZE bytes) at a time.
290
 
        bytes = osutils.until_no_eintr(self.socket.recv, _MAX_READ_SIZE)
291
 
        self._report_activity(len(bytes), 'read')
292
 
        return bytes
 
288
        return osutils.read_bytes_from_socket(
 
289
            self.socket, self._report_activity)
293
290
 
294
291
    def terminate_due_to_error(self):
295
292
        # TODO: This should log to a server log file, but no such thing
298
295
        self.finished = True
299
296
 
300
297
    def _write_out(self, bytes):
 
298
        tstart = osutils.timer_func()
301
299
        osutils.send_all(self.socket, bytes, self._report_activity)
 
300
        if 'hpss' in debug.debug_flags:
 
301
            thread_id = thread.get_ident()
 
302
            trace.mutter('%12s: [%s] %d bytes to the socket in %.3fs'
 
303
                         % ('wrote', thread_id, len(bytes),
 
304
                            osutils.timer_func() - tstart))
302
305
 
303
306
 
304
307
class SmartServerPipeStreamMedium(SmartServerStreamMedium):
381
384
    def accept_bytes(self, bytes):
382
385
        """Accept bytes for inclusion in this request.
383
386
 
384
 
        This method may not be be called after finished_writing() has been
 
387
        This method may not be called after finished_writing() has been
385
388
        called.  It depends upon the Medium whether or not the bytes will be
386
389
        immediately transmitted. Message based Mediums will tend to buffer the
387
390
        bytes until finished_writing() is called.
475
478
        if not line.endswith('\n'):
476
479
            # end of file encountered reading from server
477
480
            raise errors.ConnectionReset(
478
 
                "please check connectivity and permissions")
 
481
                "Unexpected end of message. Please check connectivity "
 
482
                "and permissions, and report a bug if problems persist.")
479
483
        return line
480
484
 
481
485
    def _read_line(self):
509
513
        """
510
514
        medium_repr = repr(medium)
511
515
        # Add this medium to the WeakKeyDictionary
512
 
        self.counts[medium] = [0, medium_repr]
 
516
        self.counts[medium] = dict(count=0, vfs_count=0,
 
517
                                   medium_repr=medium_repr)
513
518
        # Weakref callbacks are fired in reverse order of their association
514
519
        # with the referenced object.  So we add a weakref *after* adding to
515
520
        # the WeakKeyDict so that we can report the value from it before the
519
524
    def increment_call_count(self, params):
520
525
        # Increment the count in the WeakKeyDictionary
521
526
        value = self.counts[params.medium]
522
 
        value[0] += 1
 
527
        value['count'] += 1
 
528
        try:
 
529
            request_method = request.request_handlers.get(params.method)
 
530
        except KeyError:
 
531
            # A method we don't know about doesn't count as a VFS method.
 
532
            return
 
533
        if issubclass(request_method, vfs.VfsRequest):
 
534
            value['vfs_count'] += 1
523
535
 
524
536
    def done(self, ref):
525
537
        value = self.counts[ref]
526
 
        count, medium_repr = value
 
538
        count, vfs_count, medium_repr = (
 
539
            value['count'], value['vfs_count'], value['medium_repr'])
527
540
        # In case this callback is invoked for the same ref twice (by the
528
541
        # weakref callback and by the atexit function), set the call count back
529
542
        # to 0 so this item won't be reported twice.
530
 
        value[0] = 0
 
543
        value['count'] = 0
 
544
        value['vfs_count'] = 0
531
545
        if count != 0:
532
 
            trace.note('HPSS calls: %d %s', count, medium_repr)
 
546
            trace.note('HPSS calls: %d (%d vfs) %s',
 
547
                       count, vfs_count, medium_repr)
533
548
 
534
549
    def flush_all(self):
535
550
        for ref in list(self.counts.keys()):
694
709
    """A client medium using simple pipes.
695
710
 
696
711
    This client does not manage the pipes: it assumes they will always be open.
 
712
 
 
713
    Note that if readable_pipe.read might raise IOError or OSError with errno
 
714
    of EINTR, it must be safe to retry the read.  Plain CPython fileobjects
 
715
    (such as used for sys.stdin) are safe.
697
716
    """
698
717
 
699
718
    def __init__(self, readable_pipe, writeable_pipe, base):
712
731
 
713
732
    def _read_bytes(self, count):
714
733
        """See SmartClientStreamMedium._read_bytes."""
715
 
        bytes = self._readable_pipe.read(count)
 
734
        bytes = osutils.until_no_eintr(self._readable_pipe.read, count)
716
735
        self._report_activity(len(bytes), 'read')
717
736
        return bytes
718
737
 
732
751
        self._password = password
733
752
        self._port = port
734
753
        self._username = username
 
754
        # for the benefit of progress making a short description of this
 
755
        # transport
 
756
        self._scheme = 'bzr+ssh'
735
757
        # SmartClientStreamMedium stores the repr of this object in its
736
758
        # _DebugCounter so we have to store all the values used in our repr
737
759
        # method before calling the super init.
741
763
        self._vendor = vendor
742
764
        self._write_to = None
743
765
        self._bzr_remote_path = bzr_remote_path
744
 
        # for the benefit of progress making a short description of this
745
 
        # transport
746
 
        self._scheme = 'bzr+ssh'
747
766
 
748
767
    def __repr__(self):
749
 
        return "%s(connected=%r, username=%r, host=%r, port=%r)" % (
 
768
        if self._port is None:
 
769
            maybe_port = ''
 
770
        else:
 
771
            maybe_port = ':%s' % self._port
 
772
        return "%s(%s://%s@%s%s/)" % (
750
773
            self.__class__.__name__,
751
 
            self._connected,
 
774
            self._scheme,
752
775
            self._username,
753
776
            self._host,
754
 
            self._port)
 
777
            maybe_port)
755
778
 
756
779
    def _accept_bytes(self, bytes):
757
780
        """See SmartClientStreamMedium.accept_bytes."""
877
900
        """See SmartClientMedium.read_bytes."""
878
901
        if not self._connected:
879
902
            raise errors.MediumNotConnected(self)
880
 
        # We ignore the desired_count because on sockets it's more efficient to
881
 
        # read large chunks (of _MAX_READ_SIZE bytes) at a time.
882
 
        try:
883
 
            bytes = osutils.until_no_eintr(self._socket.recv, _MAX_READ_SIZE)
884
 
        except socket.error, e:
885
 
            if len(e.args) and e.args[0] == errno.ECONNRESET:
886
 
                # Callers expect an empty string in that case
887
 
                return ''
888
 
            else:
889
 
                raise
890
 
        else:
891
 
            self._report_activity(len(bytes), 'read')
892
 
            return bytes
 
903
        return osutils.read_bytes_from_socket(
 
904
            self._socket, self._report_activity)
893
905
 
894
906
 
895
907
class SmartClientStreamMediumRequest(SmartClientMediumRequest):
931
943
        """
932
944
        self._medium._flush()
933
945
 
 
946