~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/remote.py

  • Committer: Vincent Ladeuil
  • Date: 2007-06-08 08:52:27 UTC
  • mto: (2485.8.44 bzr.connection.sharing)
  • mto: This revision was merged to the branch mainline in revision 2646.
  • Revision ID: v.ladeuil+lp@free.fr-20070608085227-dkwzu18gxemnwwha
Finish (almost) remote refactoring. Test suite passing.

* bzrlib/transport/remote.py:
(RemoteTransport.__init__): Refactoring of connection
sharing. This is incomplete if we want to achieve connction
sharing across reconnections but enough to make the test suite
pass.
(RemoteTransport.clone): Deleted.
(RemoteTransport._build_medium): Default implementation (mainly
used for tests).
(RemoteTransport.get_smart_client,
RemoteTransport.get_smart_medium): Give back the shared medium
instead of the private one. This is incomplete but a step in the
right direction.
(RemoteTCPTransport._build_medium,
RemoteHTTPTransport._build_medium): Create and set the connection
if not cloning.

Show diffs side-by-side

added added

removed removed

Lines of Context:
74
74
    # RemoteTransport is an adapter from the Transport object model to the 
75
75
    # SmartClient model, not an encoder.
76
76
 
 
77
    # FIXME: the medium parameter should be private, only the tests requires
 
78
    # it. It may be even clearer to define a TestRemoteTransport that handles
 
79
    # the specific cases of providing a _client and/or a _medium, and leave
 
80
    # RemoteTransport as an abstract class.
77
81
    def __init__(self, url, from_transport=None, medium=None, _client=None):
78
82
        """Constructor.
79
83
 
89
93
            determined from the medium.
90
94
        """
91
95
        super(RemoteTransport, self).__init__(url, from_transport)
 
96
 
92
97
        if medium is None:
93
 
            self._build_medium(from_transport)
 
98
            medium = self._build_medium(from_transport)
94
99
        else:
95
 
            self._medium = medium
 
100
            self._set_connection(medium, None)
 
101
        self._medium = medium
96
102
        assert self._medium is not None
 
103
        # ConnectedTransport provides the connection sharing by requiring
 
104
        # daughter classes to always access the connection via _get_connection
 
105
        # and guarantee that the connection wil be shared across all transports
 
106
        # even if the server force a reconnection (i.e. the connection object
 
107
        # should be built again).
 
108
 
 
109
        # For RemoteTransport objects, the medium is the connection. But using
 
110
        # _get_connection is not enough because:
 
111
        # - self._client needs a medium to be built (and keep an internal
 
112
        #   copy).
 
113
        # - RemoteBzrDir RemoteRepository, RemoteRepositoryFormat RemoteBranch
 
114
        #   keep internal copies of _SmartClient objects.
 
115
 
 
116
        # Therefore, the needed refactoring (enhancing _SmartClient and its
 
117
        # users so that connection are still shared even in cases or
 
118
        # reconnections) is too much for this round -- vila20070607
 
119
 
 
120
        # On the other hand, except for the reconnection part, the sharing will
 
121
        # already reduce the number of connections.
97
122
        if _client is None:
98
123
            self._client = client._SmartClient(self._medium)
99
124
        else:
101
126
 
102
127
    def _build_medium(self, from_transport=None):
103
128
        """Create the medium if from_transport does not provide one.
104
 
        MUST be defined by daughter classes. The medium is
105
 
        analogous to the connection for ConnectedTransport: it
 
129
 
 
130
        The medium is analogous to the connection for ConnectedTransport: it
106
131
        allows connection sharing.
107
132
        
108
133
        :param from_transport: provide the medium to reuse if not None
109
134
        """
110
 
        raise NotImplementedError(self._build_medium)
111
 
 
112
 
    def clone(self, relative_url):
113
 
        """Make a new RemoteTransport related to me, sharing the same connection.
114
 
 
115
 
        This essentially opens a handle on a different remote directory.
116
 
        """
117
 
        if relative_url is None:
118
 
            return self.__class__(self.base, self, self._medium)
 
135
        if from_transport is not None:
 
136
            _medium = from_transport._medium
119
137
        else:
120
 
            return self.__class__(self.abspath(relative_url), self,
121
 
                                  self._medium)
 
138
            import pdb; pdb.set_trace()
 
139
            _medium = None
 
140
            # No credentials
 
141
            self._set_connection(_medium, None)
 
142
        return _medium
122
143
 
123
144
    def is_readonly(self):
124
145
        """Smart server transport can do read/write file operations."""
140
161
        assert False, 'weird response %r' % (resp,)
141
162
 
142
163
    def get_smart_client(self):
143
 
        return self._medium
 
164
        return self._get_connection()
144
165
 
145
166
    def get_smart_medium(self):
146
 
        return self._medium
 
167
        return self._get_connection()
147
168
 
148
169
    def _remote_path(self, relpath):
149
170
        """Returns the Unicode version of the absolute path for relpath."""
432
453
            _medium = from_transport._medium
433
454
        else:
434
455
            _medium = medium.SmartTCPClientMedium(self._host, self._port)
435
 
        self._medium = _medium
 
456
            self._set_connection(_medium, None)
 
457
        return _medium
436
458
 
437
459
 
438
460
class RemoteSSHTransport(RemoteTransport):
448
470
            _medium = from_transport._medium
449
471
        else:
450
472
            _medium = medium.SmartSSHClientMedium(self._host, self._port,
451
 
                                                 self._user, self._password)
452
 
        self._medium = _medium
 
473
                                                  self._user, self._password)
 
474
            # ssh will prompt the user for a password if needed and if none is
 
475
            # provided but it will not give it back, so no credentials can be
 
476
            # stored.
 
477
            self._set_connection(_medium, None)
 
478
        return _medium
453
479
 
454
480
 
455
481
class RemoteHTTPTransport(RemoteTransport):
478
504
            _medium = from_transport._medium
479
505
        else:
480
506
            _medium = self._http_transport.get_smart_medium()
481
 
        self._medium = _medium
 
507
            # We let http_transport take care of the credentials
 
508
            self._set_connection(_medium, None)
 
509
        return _medium
482
510
 
483
511
    def _remote_path(self, relpath):
484
512
        """After connecting, HTTP Transport only deals in relative URLs."""