~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/server.py

Merge up bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
64
64
        if sys.platform != 'win32':
65
65
            self._server_socket.setsockopt(socket.SOL_SOCKET,
66
66
                socket.SO_REUSEADDR, 1)
67
 
        self._server_socket.bind((host, port))
 
67
        try:
 
68
            self._server_socket.bind((host, port))
 
69
        except self._socket_error, message:
 
70
            raise errors.CannotBindAddress(host, port, message)
68
71
        self._sockname = self._server_socket.getsockname()
69
72
        self.port = self._sockname[1]
70
73
        self._server_socket.listen(1)
74
77
        self._stopped = threading.Event()
75
78
        self.root_client_path = root_client_path
76
79
 
77
 
    def serve(self):
 
80
    def serve(self, thread_name_suffix=''):
78
81
        self._should_terminate = False
79
82
        # for hooks we are letting code know that a server has started (and
80
83
        # later stopped).
116
119
                        if e.args[0] != errno.EBADF:
117
120
                            trace.warning("listening socket error: %s", e)
118
121
                    else:
119
 
                        self.serve_conn(conn)
 
122
                        self.serve_conn(conn, thread_name_suffix)
120
123
            except KeyboardInterrupt:
121
124
                # dont log when CTRL-C'd.
122
125
                raise
139
142
        """Return the url of the server"""
140
143
        return "bzr://%s:%d/" % self._sockname
141
144
 
142
 
    def serve_conn(self, conn):
 
145
    def serve_conn(self, conn, thread_name_suffix):
143
146
        # For WIN32, where the timeout value from the listening socket
144
147
        # propogates to the newly accepted socket.
145
148
        conn.setblocking(True)
146
149
        conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
147
150
        handler = SmartServerSocketStreamMedium(
148
151
            conn, self.backing_transport, self.root_client_path)
149
 
        connection_thread = threading.Thread(None, handler.serve, name='smart-server-child')
 
152
        thread_name = 'smart-server-child' + thread_name_suffix
 
153
        connection_thread = threading.Thread(
 
154
            None, handler.serve, name=thread_name)
150
155
        connection_thread.setDaemon(True)
151
156
        connection_thread.start()
152
157
 
153
 
    def start_background_thread(self):
 
158
    def start_background_thread(self, thread_name_suffix=''):
154
159
        self._started.clear()
155
160
        self._server_thread = threading.Thread(None,
156
 
                self.serve,
 
161
                self.serve, args=(thread_name_suffix,),
157
162
                name='server-' + self.get_url())
158
163
        self._server_thread.setDaemon(True)
159
164
        self._server_thread.start()
213
218
    This server is backed by the process's cwd.
214
219
    """
215
220
 
216
 
    def __init__(self):
 
221
    def __init__(self, thread_name_suffix=''):
217
222
        SmartTCPServer.__init__(self, None)
218
223
        self.client_path_extra = None
 
224
        self.thread_name_suffix = thread_name_suffix
219
225
        
220
226
    def get_backing_transport(self, backing_transport_server):
221
227
        """Get a backing transport from a server we are decorating."""
235
241
            `bzr://127.0.0.1:nnnn/`.  Default value is `extra`, so that tests
236
242
            by default will fail unless they do the necessary path translation.
237
243
        """
238
 
        assert client_path_extra.startswith('/')
 
244
        if not client_path_extra.startswith('/'):
 
245
            raise ValueError(client_path_extra)
239
246
        from bzrlib.transport.chroot import ChrootServer
240
247
        if backing_transport_server is None:
241
248
            from bzrlib.transport.local import LocalURLServer
246
253
        self.backing_transport = transport.get_transport(
247
254
            self.chroot_server.get_url())
248
255
        self.root_client_path = self.client_path_extra = client_path_extra
249
 
        self.start_background_thread()
 
256
        self.start_background_thread(self.thread_name_suffix)
250
257
 
251
258
    def tearDown(self):
252
259
        self.stop_background_thread()
254
261
 
255
262
    def get_url(self):
256
263
        url = super(SmartTCPServer_for_testing, self).get_url()
257
 
        assert url.endswith('/')
258
264
        return url[:-1] + self.client_path_extra
259
265
 
260
266
    def get_bogus_url(self):
269
275
        """Get a backing transport from a server we are decorating."""
270
276
        url = 'readonly+' + backing_transport_server.get_url()
271
277
        return transport.get_transport(url)
272