~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/medium.py

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil
  • Date: 2017-01-30 14:42:05 UTC
  • mfrom: (6620.1.1 trunk)
  • Revision ID: tarmac-20170130144205-r8fh2xpmiuxyozpv
Merge  2.7 into trunk including fix for bug #1657238 [r=vila]

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
bzrlib/transport/smart/__init__.py.
25
25
"""
26
26
 
 
27
from __future__ import absolute_import
 
28
 
27
29
import errno
28
30
import os
29
31
import sys
30
32
import time
31
 
import urllib
32
33
 
33
34
import bzrlib
34
35
from bzrlib.lazy_import import lazy_import
42
43
    debug,
43
44
    errors,
44
45
    trace,
 
46
    transport,
45
47
    ui,
46
48
    urlutils,
47
49
    )
230
232
        try:
231
233
            while not self.finished:
232
234
                server_protocol = self._build_protocol()
233
 
                # TODO: This seems inelegant:
234
 
                if server_protocol is None:
235
 
                    # We could 'continue' only to notice that self.finished is
236
 
                    # True...
237
 
                    break
238
235
                self._serve_one_request(server_protocol)
239
236
        except errors.ConnectionTimeout, e:
240
237
            trace.note('%s' % (e,))
326
323
 
327
324
        :param protocol: a SmartServerRequestProtocol.
328
325
        """
 
326
        if protocol is None:
 
327
            return
329
328
        try:
330
329
            self._serve_one_request_unguarded(protocol)
331
330
        except KeyboardInterrupt:
843
842
        """
844
843
        medium_base = urlutils.join(self.base, '/')
845
844
        rel_url = urlutils.relative_url(medium_base, transport.base)
846
 
        return urllib.unquote(rel_url)
 
845
        return urlutils.unquote(rel_url)
847
846
 
848
847
 
849
848
class SmartClientStreamMedium(SmartClientMedium):
884
883
        """
885
884
        return SmartClientStreamMediumRequest(self)
886
885
 
 
886
    def reset(self):
 
887
        """We have been disconnected, reset current state.
 
888
 
 
889
        This resets things like _current_request and connected state.
 
890
        """
 
891
        self.disconnect()
 
892
        self._current_request = None
 
893
 
887
894
 
888
895
class SmartSimplePipesClientMedium(SmartClientStreamMedium):
889
896
    """A client medium using simple pipes.
898
905
 
899
906
    def _accept_bytes(self, bytes):
900
907
        """See SmartClientStreamMedium.accept_bytes."""
901
 
        self._writeable_pipe.write(bytes)
 
908
        try:
 
909
            self._writeable_pipe.write(bytes)
 
910
        except IOError, e:
 
911
            if e.errno in (errno.EINVAL, errno.EPIPE):
 
912
                raise errors.ConnectionReset(
 
913
                    "Error trying to write to subprocess", e)
 
914
            raise
902
915
        self._report_activity(len(bytes), 'write')
903
916
 
904
917
    def _flush(self):
905
918
        """See SmartClientStreamMedium._flush()."""
 
919
        # Note: If flush were to fail, we'd like to raise ConnectionReset, etc.
 
920
        #       However, testing shows that even when the child process is
 
921
        #       gone, this doesn't error.
906
922
        self._writeable_pipe.flush()
907
923
 
908
924
    def _read_bytes(self, count):
927
943
 
928
944
class SmartSSHClientMedium(SmartClientStreamMedium):
929
945
    """A client medium using SSH.
930
 
    
931
 
    It delegates IO to a SmartClientSocketMedium or
 
946
 
 
947
    It delegates IO to a SmartSimplePipesClientMedium or
932
948
    SmartClientAlreadyConnectedSocketMedium (depending on platform).
933
949
    """
934
950
 
956
972
            maybe_port = ''
957
973
        else:
958
974
            maybe_port = ':%s' % self._ssh_params.port
959
 
        return "%s(%s://%s@%s%s/)" % (
 
975
        if self._ssh_params.username is None:
 
976
            maybe_user = ''
 
977
        else:
 
978
            maybe_user = '%s@' % self._ssh_params.username
 
979
        return "%s(%s://%s%s%s/)" % (
960
980
            self.__class__.__name__,
961
981
            self._scheme,
962
 
            self._ssh_params.username,
 
982
            maybe_user,
963
983
            self._ssh_params.host,
964
984
            maybe_port)
965
985
 
1002
1022
            raise AssertionError(
1003
1023
                "Unexpected io_kind %r from %r"
1004
1024
                % (io_kind, self._ssh_connection))
 
1025
        for hook in transport.Transport.hooks["post_connect"]:
 
1026
            hook(self)
1005
1027
 
1006
1028
    def _flush(self):
1007
1029
        """See SmartClientStreamMedium._flush()."""
1021
1043
 
1022
1044
class SmartClientSocketMedium(SmartClientStreamMedium):
1023
1045
    """A client medium using a socket.
1024
 
    
 
1046
 
1025
1047
    This class isn't usable directly.  Use one of its subclasses instead.
1026
1048
    """
1027
1049
 
1110
1132
            raise errors.ConnectionError("failed to connect to %s:%d: %s" %
1111
1133
                    (self._host, port, err_msg))
1112
1134
        self._connected = True
 
1135
        for hook in transport.Transport.hooks["post_connect"]:
 
1136
            hook(self)
1113
1137
 
1114
1138
 
1115
1139
class SmartClientAlreadyConnectedSocketMedium(SmartClientSocketMedium):
1167
1191
        This invokes self._medium._flush to ensure all bytes are transmitted.
1168
1192
        """
1169
1193
        self._medium._flush()
1170
 
 
1171