Rev 5289: Start refactoring the smart server to control which thread it runs in. in file:///home/vila/src/bzr/experimental/leaking-tests/

Vincent Ladeuil v.ladeuil+lp at free.fr
Fri Jun 18 08:51:17 BST 2010


At file:///home/vila/src/bzr/experimental/leaking-tests/

------------------------------------------------------------
revno: 5289
revision-id: v.ladeuil+lp at free.fr-20100618075117-mtkr7hzyz34hht7i
parent: v.ladeuil+lp at free.fr-20100617145827-74r52t16sujwptv1
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: smart-server-leaks
timestamp: Fri 2010-06-18 09:51:17 +0200
message:
  Start refactoring the smart server to control which thread it runs in.
  
  * bzrlib/tests/test_server.py:
  (SmartTCPServer_for_testing.__init__): The server is run in a
  background thread but creates the server socket in the main
  thread.
  
  * bzrlib/tests/test_smart_transport.py:
  (TestSmartTCPServer.test_get_error_unexpected)
  (SmartTCPTests.start_server): The server is run in a background
  thread but creates the server socket in the main thread.
  
  * bzrlib/smart/server.py:
  (SmartTCPServer): Start separating the thread handling from the
  sockets handling to make it it fit with TestingTCPServerInAThread.
  (SmartTCPServer._create_server_socket): The server socket
  creation.
  (SmartTCPServer._backing_urls): What urls are served.
  (SmartTCPServer.run_server_started_hooks)
  (SmartTCPServer.run_server_stopped_hooks): The start/stop hooks.
  (BzrServerFactory._make_smart_server): The server is run in the
  main thread.
-------------- next part --------------
=== modified file 'bzrlib/smart/server.py'
--- a/bzrlib/smart/server.py	2010-05-24 01:05:14 +0000
+++ b/bzrlib/smart/server.py	2010-06-18 07:51:17 +0000
@@ -52,18 +52,24 @@
     hooks: An instance of SmartServerHooks.
     """
 
-    def __init__(self, backing_transport, host='127.0.0.1', port=0,
-                 root_client_path='/'):
+    def __init__(self, backing_transport, root_client_path='/'):
         """Construct a new server.
 
         To actually start it running, call either start_background_thread or
         serve.
 
         :param backing_transport: The transport to serve.
+        :param root_client_path: The client path that will correspond to root
+            of backing_transport.
+        """
+        self.backing_transport = backing_transport
+        self.root_client_path = root_client_path
+
+    def _create_server_socket(self, host, port):
+        """Create the server listening socket.
+
         :param host: Name of the interface to listen on.
         :param port: TCP port to listen on, or 0 to allocate a transient port.
-        :param root_client_path: The client path that will correspond to root
-            of backing_transport.
         """
         # let connections timeout so that we get a chance to terminate
         # Keep a reference to the exceptions we want to catch because the socket
@@ -90,15 +96,10 @@
         self.port = self._sockname[1]
         self._server_socket.listen(1)
         self._server_socket.settimeout(1)
-        self.backing_transport = backing_transport
         self._started = threading.Event()
         self._stopped = threading.Event()
-        self.root_client_path = root_client_path
 
-    def serve(self, thread_name_suffix=''):
-        self._should_terminate = False
-        # for hooks we are letting code know that a server has started (and
-        # later stopped).
+    def _backing_urls(self):
         # There are three interesting urls:
         # The URL the server can be contacted on. (e.g. bzr://host/)
         # The URL that a commit done on the same machine as the server will
@@ -114,15 +115,32 @@
         # The latter two urls are different aliases to the servers url,
         # so we group those in a list - as there might be more aliases
         # in the future.
-        backing_urls = [self.backing_transport.base]
+        urls = [self.backing_transport.base]
         try:
-            backing_urls.append(self.backing_transport.external_url())
+            urls.append(self.backing_transport.external_url())
         except errors.InProcessTransport:
             pass
+        return urls
+
+    def run_server_started_hooks(self, backing_urls=None):
+        if backing_urls is None:
+            backing_urls = self._backing_urls()
         for hook in SmartTCPServer.hooks['server_started']:
             hook(backing_urls, self.get_url())
         for hook in SmartTCPServer.hooks['server_started_ex']:
             hook(backing_urls, self)
+
+    def run_server_stopped_hooks(self, backing_urls=None):
+        if backing_urls is None:
+            backing_urls = self._backing_urls()
+        for hook in SmartTCPServer.hooks['server_stopped']:
+            hook(backing_urls, self.get_url())
+
+    def serve(self, thread_name_suffix=''):
+        self._should_terminate = False
+        # for hooks we are letting code know that a server has started (and
+        # later stopped).
+        self.run_server_started_hooks()
         self._started.set()
         try:
             try:
@@ -156,8 +174,7 @@
             except self._socket_error:
                 # ignore errors on close
                 pass
-            for hook in SmartTCPServer.hooks['server_stopped']:
-                hook(backing_urls, self.get_url())
+            self.run_server_stopped_hooks()
 
     def get_url(self):
         """Return the url of the server"""
@@ -326,7 +343,8 @@
                 host = medium.BZR_DEFAULT_INTERFACE
             if port is None:
                 port = medium.BZR_DEFAULT_PORT
-            smart_server = SmartTCPServer(self.transport, host=host, port=port)
+            smart_server = SmartTCPServer(self.transport)
+            smart_server._create_server_socket(host, port)
             trace.note('listening on port: %s' % smart_server.port)
         self.smart_server = smart_server
 

=== modified file 'bzrlib/tests/test_server.py'
--- a/bzrlib/tests/test_server.py	2010-06-12 15:10:35 +0000
+++ b/bzrlib/tests/test_server.py	2010-06-18 07:51:17 +0000
@@ -31,7 +31,10 @@
     chroot,
     pathfilter,
     )
-from bzrlib.smart import server
+from bzrlib.smart import (
+    medium,
+    server,
+    )
 
 
 def debug_threads():
@@ -650,6 +653,7 @@
         super(SmartTCPServer_for_testing, self).__init__(None)
         self.client_path_extra = None
         self.thread_name_suffix = thread_name_suffix
+        self._create_server_socket('127.0.0.1', 0)
         # We collect the sockets/threads used by the clients so we can
         # close/join them when shutting down
         self.clients = []

=== modified file 'bzrlib/tests/test_smart_transport.py'
--- a/bzrlib/tests/test_smart_transport.py	2010-06-16 05:47:02 +0000
+++ b/bzrlib/tests/test_smart_transport.py	2010-06-18 07:51:17 +0000
@@ -975,6 +975,7 @@
             def get_bytes(self, path):
                 raise Exception("some random exception from inside server")
         smart_server = server.SmartTCPServer(backing_transport=FlakyTransport())
+        smart_server._create_server_socket('127.0.0.1', 0)
         smart_server.start_background_thread('-' + self.id())
         try:
             transport = remote.RemoteTCPTransport(smart_server.get_url())
@@ -1017,6 +1018,7 @@
             self.backing_transport = transport.get_transport(
                 "readonly+" + self.backing_transport.abspath('.'))
         self.server = server.SmartTCPServer(self.backing_transport)
+        self.server._create_server_socket('127.0.0.1', 0)
         self.server.start_background_thread('-' + self.id())
         self.transport = remote.RemoteTCPTransport(self.server.get_url())
         self.addCleanup(self.tearDownServer)



More information about the bazaar-commits mailing list