Rev 2515: Implement reliable connection sharing. in file:///v/home/vila/src/experimental/reuse.transports/

Vincent Ladeuil v.ladeuil+lp at free.fr
Sat Jun 2 17:54:30 BST 2007


At file:///v/home/vila/src/experimental/reuse.transports/

------------------------------------------------------------
revno: 2515
revision-id: v.ladeuil+lp at free.fr-20070602165428-sgwamqtdhksglmlu
parent: v.ladeuil+lp at free.fr-20070602161853-miwtge8q1fjjjhvu
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: reuse.transports
timestamp: Sat 2007-06-02 18:54:28 +0200
message:
  Implement reliable connection sharing.
  
  * bzrlib/transport/__init__.py:
  (ConnectedTransport.__init__): Use a list to contain the
  connection to ensure proper sharing when transports needs to
  reconnect or if transport is cloned before creating the
  connection.
  
  * bzrlib/tests/test_transport.py:
  (TestConnectedTransport.test_connection_sharing): New tests.
modified:
  bzrlib/tests/test_transport.py testtransport.py-20050718175618-e5cdb99f4555ddce
  bzrlib/transport/__init__.py   transport.py-20050711165921-4978aa7ce1285ad5
-------------- next part --------------
=== modified file 'bzrlib/tests/test_transport.py'
--- a/bzrlib/tests/test_transport.py	2007-05-31 18:01:11 +0000
+++ b/bzrlib/tests/test_transport.py	2007-06-02 16:54:28 +0000
@@ -643,6 +643,26 @@
         t = ConnectedTransport('sftp://host.com/dev/%path')
         self.assertEquals(t.relpath('sftp://host.com/dev/%path/sub'), 'sub')
 
+    def test_connection_sharing(self):
+        t = ConnectedTransport('foo://user@host.com/abs/path')
+        self.assertEquals(None, t.get_connection())
+
+        c = t.clone('subdir')
+        self.assertEquals(None, c.get_connection())
+
+        # But as soon as one transport connects, the other get
+        # the connection too
+        connection = object()
+        t.set_connection(connection)
+        self.assertIs(connection, t.get_connection())
+        self.assertIs(connection, c.get_connection())
+
+        # Temporary failure, we need to create a new connection
+        new_connection = object()
+        t.set_connection(new_connection)
+        self.assertIs(new_connection, t.get_connection())
+        self.assertIs(new_connection, c.get_connection())
+
 
 class TestReusedTransports(TestCase):
     """Tests for transport reuse"""

=== modified file 'bzrlib/transport/__init__.py'
--- a/bzrlib/transport/__init__.py	2007-06-02 16:18:53 +0000
+++ b/bzrlib/transport/__init__.py	2007-06-02 16:54:28 +0000
@@ -1064,11 +1064,16 @@
                                  self._path)
 
         super(ConnectedTransport, self).__init__(base)
-        if from_transport is not None:
-            connection = from_transport.get_connection()
+        if from_transport is None:
+            # We use a list as a container for the connection so that the
+            # connection will be shared even if a transport is cloned before
+            # the first effective connection (generally the first request
+            # made). It also guarantees that the connection will still be
+            # shared if a transport needs to reconnect after a temporary
+            # failure.
+            self._connection = [None]
         else:
-            connection = None
-        self.set_connection(connection)
+            self._connection = from_transport._connection
 
     def clone(self, offset=None):
         """Return a new transport with root at self.base + offset
@@ -1207,18 +1212,20 @@
         remote_path = self._combine_paths(self._path, relative)
         return remote_path
 
-    def get_connection(self):
-        """Returns the transport specific connection object"""
-        return self._connection
-
     def set_connection(self, connection):
         """Set the transport specific connection object.
 
-        Note: daughter classes should ensure that the connection is still
-        shared if the connection is reset during the transport lifetime (using
-        a list containing the single connection can help avoid aliasing bugs).
+        Note: To ensure that connection is still shared after a temporary
+        failure and a new one needs to be created, daughter classes should
+        always call this method to set the connection. No assumptions are made
+        about the object type of the connection object.
         """
-        self._connection = connection
+        self._connection[0] = connection
+
+    def get_connection(self):
+        """Returns the transport specific connection object."""
+        return self._connection[0]
+
 
 
 # jam 20060426 For compatibility we copy the functions here



More information about the bazaar-commits mailing list