def test_bzr_serve_graceful_shutdown(self): big_contents = 'a' * 64 * 1024 self.build_tree_contents([('bigfile', big_contents)]) process, url = self.start_server_port(['--client-timeout=1.0']) t = transport.get_transport_from_url(url) m = t.get_smart_medium() c = client._SmartClient(m) # Start, but don't finish a response resp, response_handler = c.call_expecting_body('get', 'bigfile') self.assertEqual(('ok', ), resp) # Note: process.send_signal is a Python 2.6ism process.send_signal(signal.SIGHUP) # Wait for the server to notice the signal, and then read the actual # body of the response. That way we know that it is waiting for the # request to finish self.assertEqual('Requested to stop gracefully\n', process.stderr.readline()) self.assertEqual('Waiting for 1 client(s) to finish\n', process.stderr.readline()) body = response_handler.read_body_bytes() if body != big_contents: self.fail('Failed to properly read the contents of "bigfile"') # Now that our request is finished, the medium should notice it has # been disconnected. self.assertEqual('', m.read_bytes(1)) # And the server should be stopping self.assertEqual(0, process.wait())
def test_bzr_serve_graceful_shutdown(self): big_contents = 'a'*64*1024 self.build_tree_contents([('bigfile', big_contents)]) process, url = self.start_server_port(['--client-timeout=1.0']) t = transport.get_transport_from_url(url) m = t.get_smart_medium() c = client._SmartClient(m) # Start, but don't finish a response resp, response_handler = c.call_expecting_body('get', 'bigfile') self.assertEqual(('ok',), resp) # Note: process.send_signal is a Python 2.6ism process.send_signal(signal.SIGHUP) # Wait for the server to notice the signal, and then read the actual # body of the response. That way we know that it is waiting for the # request to finish self.assertEqual('Requested to stop gracefully\n', process.stderr.readline()) self.assertEqual('Waiting for 1 client(s) to finish\n', process.stderr.readline()) body = response_handler.read_body_bytes() if body != big_contents: self.fail('Failed to properly read the contents of "bigfile"') # Now that our request is finished, the medium should notice it has # been disconnected. self.assertEqual('', m.read_bytes(1)) # And the server should be stopping self.assertEqual(0, process.wait())
def test_inet_server_responds_to_sighup(self): t = transport.get_transport('memory:///') content = 'a'*1024*1024 t.put_bytes('bigfile', content) factory = server.BzrServerFactory() # Override stdin/stdout so that we can inject our own handles client_read, server_write = self.create_file_pipes() server_read, client_write = self.create_file_pipes() factory._get_stdin_stdout = lambda: (server_read, server_write) factory.set_up(t, None, None, inet=True, timeout=4.0) self.addCleanup(factory.tear_down) started = threading.Event() stopped = threading.Event() def serving(): started.set() factory.smart_server.serve() stopped.set() server_thread = threading.Thread(target=serving) server_thread.start() started.wait() client_medium = medium.SmartSimplePipesClientMedium(client_read, client_write, 'base') client_client = client._SmartClient(client_medium) resp, response_handler = client_client.call_expecting_body('get', 'bigfile') signals._sighup_handler(SIGHUP, None) self.assertTrue(factory.smart_server.finished) # We can still finish reading the file content, but more than that, and # the file is closed. v = response_handler.read_body_bytes() if v != content: self.fail('Got the wrong content back, expected 1M "a"') stopped.wait() server_thread.join()
def __init__(self, url, _from_transport=None, medium=None, _client=None): """Constructor. :param _from_transport: Another RemoteTransport instance that this one is being cloned from. Attributes such as the medium will be reused. :param medium: The medium to use for this RemoteTransport. If None, the medium from the _from_transport is shared. If both this and _from_transport are None, a new medium will be built. _from_transport and medium cannot both be specified. :param _client: Override the _SmartClient used by this transport. This should only be used for testing purposes; normally this is determined from the medium. """ super(RemoteTransport, self).__init__( url, _from_transport=_from_transport) # The medium is the connection, except when we need to share it with # other objects (RemoteBzrDir, RemoteRepository etc). In these cases # what we want to share is really the shared connection. if (_from_transport is not None and isinstance(_from_transport, RemoteTransport)): _client = _from_transport._client elif _from_transport is None: # If no _from_transport is specified, we need to intialize the # shared medium. credentials = None if medium is None: medium, credentials = self._build_medium() if 'hpss' in debug.debug_flags: trace.mutter('hpss: Built a new medium: %s', medium.__class__.__name__) self._shared_connection = transport._SharedConnection(medium, credentials, self.base) elif medium is None: # No medium was specified, so share the medium from the # _from_transport. medium = self._shared_connection.connection else: raise AssertionError( "Both _from_transport (%r) and medium (%r) passed to " "RemoteTransport.__init__, but these parameters are mutally " "exclusive." % (_from_transport, medium)) if _client is None: self._client = client._SmartClient(medium) else: self._client = _client
def when_server_started(self): # Connect to the TCP server and issue some requests and see what comes # back. client_medium = medium.SmartTCPClientMedium( '127.0.0.1', self.tcp_server.port, 'bzr://localhost:%d/' % (self.tcp_server.port,)) smart_client = client._SmartClient(client_medium) resp = smart_client.call('mkdir', 'foo', '') resp = smart_client.call('BzrDirFormat.initialize', 'foo/') try: resp = smart_client.call('BzrDir.find_repositoryV3', 'foo/') except errors.ErrorFromSmartServer, e: resp = e.error_tuple
def when_server_started(self): # Connect to the TCP server and issue some requests and see what comes # back. client_medium = medium.SmartTCPClientMedium( '127.0.0.1', self.tcp_server.port, 'bzr://localhost:%d/' % (self.tcp_server.port, )) smart_client = client._SmartClient(client_medium) resp = smart_client.call('mkdir', 'foo', '') resp = smart_client.call('BzrDirFormat.initialize', 'foo/') try: resp = smart_client.call('BzrDir.find_repositoryV3', 'foo/') except errors.ErrorFromSmartServer, e: resp = e.error_tuple
def test_inet_server_responds_to_sighup(self): t = transport.get_transport('memory:///') content = 'a' * 1024 * 1024 t.put_bytes('bigfile', content) factory = server.BzrServerFactory() # Override stdin/stdout so that we can inject our own handles client_read, server_write = self.create_file_pipes() server_read, client_write = self.create_file_pipes() factory._get_stdin_stdout = lambda: (server_read, server_write) factory.set_up(t, None, None, inet=True, timeout=4.0) self.addCleanup(factory.tear_down) started = threading.Event() stopped = threading.Event() def serving(): started.set() factory.smart_server.serve() stopped.set() server_thread = threading.Thread(target=serving) server_thread.start() started.wait() client_medium = medium.SmartSimplePipesClientMedium( client_read, client_write, 'base') client_client = client._SmartClient(client_medium) resp, response_handler = client_client.call_expecting_body( 'get', 'bigfile') signals._sighup_handler(SIGHUP, None) self.assertTrue(factory.smart_server.finished) # We can still finish reading the file content, but more than that, and # the file is closed. v = response_handler.read_body_bytes() if v != content: self.fail('Got the wrong content back, expected 1M "a"') stopped.wait() server_thread.join()