Rev 6148: Start working on exposing timeout as a configuration item. in http://bazaar.launchpad.net/~jameinel/bzr/drop-idle-connections-824797
John Arbash Meinel
john at arbash-meinel.com
Thu Sep 15 09:50:37 UTC 2011
At http://bazaar.launchpad.net/~jameinel/bzr/drop-idle-connections-824797
------------------------------------------------------------
revno: 6148
revision-id: john at arbash-meinel.com-20110915095023-wquhin2e0uh1nq1e
parent: john at arbash-meinel.com-20110915093339-v21h0ca9uu1yhfwj
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: drop-idle-connections-824797
timestamp: Thu 2011-09-15 11:50:23 +0200
message:
Start working on exposing timeout as a configuration item.
-------------- next part --------------
=== modified file 'bzrlib/config.py'
--- a/bzrlib/config.py 2011-09-09 14:17:34 +0000
+++ b/bzrlib/config.py 2011-09-15 09:50:23 +0000
@@ -2568,6 +2568,12 @@
lost if the machine crashes. See also dirstate.fdatasync.
'''))
+option_registry.register(
+ Option('serve.client_timeout',
+ default=300, from_unicode=int_from_store,
+ help="If we wait for a new request from a client for more than"
+ " X seconds, consider the client idle, and hangup."))
+
class Section(object):
"""A section defines a dict of option name => value.
=== modified file 'bzrlib/smart/medium.py'
--- a/bzrlib/smart/medium.py 2011-09-14 13:47:07 +0000
+++ b/bzrlib/smart/medium.py 2011-09-15 09:50:23 +0000
@@ -48,7 +48,7 @@
from bzrlib.smart import client, protocol, request, vfs
from bzrlib.transport import ssh
""")
-from bzrlib import osutils
+from bzrlib import config, osutils
# Throughout this module buffer size parameters are either limited to be at
# most _MAX_READ_SIZE, or are ignored and _MAX_READ_SIZE is used instead.
@@ -204,12 +204,10 @@
the stream. See also the _push_back method.
"""
- # Default timeout is 300s before closing the client connection
- _stream_medium_timeout = 300
- # Poll every X seconds to see if anything new has happened.
- _stream_medium_fast_timeout = 1.0
+ _DEFAULT_CLIENT_TIMEOUT = float(config.option_registry.get(
+ 'serve.client_timeout').default)
- def __init__(self, backing_transport, root_client_path='/'):
+ def __init__(self, backing_transport, root_client_path='/', timeout=None):
"""Construct new server.
:param backing_transport: Transport for the directory served.
@@ -218,6 +216,10 @@
self.backing_transport = backing_transport
self.root_client_path = root_client_path
self.finished = False
+ if timeout is None:
+ timeout = self._DEFAULT_CLIENT_TIMEOUT
+ self._client_timeout = timeout
+ self._client_poll_timeout = min(timeout / 10.0, 1.0)
SmartMedium.__init__(self)
def serve(self):
@@ -266,7 +268,7 @@
:returns: a SmartServerRequestProtocol.
"""
- if self._wait_for_bytes_with_timeout(self._stream_medium_timeout):
+ if self._wait_for_bytes_with_timeout(self._client_timeout):
# TODO: We would like to have a nicer message than this. However,
# we don't have any context available to us about who is
# connecting for us to give a more useful message. :(
@@ -274,7 +276,7 @@
# from)
raise errors.ConnectionTimeout(
'disconnecting client after %.1f seconds'
- % (self._stream_medium_timeout))
+ % (self._client_timeout))
bytes = self._get_line()
protocol_factory, unused_bytes = _get_protocol_factory_for_bytes(bytes)
protocol = protocol_factory(
@@ -287,7 +289,7 @@
# Use local variables to handle when the interpreter is shutting down
try:
if (timeout_seconds is None
- or timeout_seconds <= self._stream_medium_fast_timeout):
+ or timeout_seconds <= self._client_poll_timeout):
rs, _, _ = select.select([fd], [], [], timeout_seconds)
else:
# It looks like during the test suite, we close the server-side
@@ -303,7 +305,7 @@
rs = []
while not rs and time.time() < t_end:
rs, _, _ = select.select([fd], [], [],
- self._stream_medium_fast_timeout)
+ self._client_poll_timeout)
except (select.error, socket.error) as e:
err = getattr(e, 'errno', None)
if err is None:
@@ -347,14 +349,16 @@
class SmartServerSocketStreamMedium(SmartServerStreamMedium):
- def __init__(self, sock, backing_transport, root_client_path='/'):
+ def __init__(self, sock, backing_transport, root_client_path='/',
+ timeout=None):
"""Constructor.
:param sock: the socket the server will read from. It will be put
into blocking mode.
"""
SmartServerStreamMedium.__init__(
- self, backing_transport, root_client_path=root_client_path)
+ self, backing_transport, root_client_path=root_client_path,
+ timeout=timeout)
sock.setblocking(True)
self.socket = sock
@@ -409,14 +413,15 @@
class SmartServerPipeStreamMedium(SmartServerStreamMedium):
- def __init__(self, in_file, out_file, backing_transport):
+ def __init__(self, in_file, out_file, backing_transport, timeout=None):
"""Construct new server.
:param in_file: Python file from which requests can be read.
:param out_file: Python file to write responses.
:param backing_transport: Transport for the directory served.
"""
- SmartServerStreamMedium.__init__(self, backing_transport)
+ SmartServerStreamMedium.__init__(self, backing_transport,
+ timeout=timeout)
if sys.platform == 'win32':
# force binary mode for files
import msvcrt
=== modified file 'bzrlib/smart/server.py'
--- a/bzrlib/smart/server.py 2011-07-23 16:33:38 +0000
+++ b/bzrlib/smart/server.py 2011-09-15 09:50:23 +0000
@@ -32,6 +32,7 @@
lazy_import(globals(), """
from bzrlib.smart import medium
from bzrlib.transport import (
+ config,
chroot,
pathfilter,
)
@@ -341,6 +342,8 @@
self.transport = transport
def _make_smart_server(self, host, port, inet):
+ c = config.GlobalStack()
+ timeout = c.get('server.client_timeout')
if inet:
smart_server = medium.SmartServerPipeStreamMedium(
sys.stdin, sys.stdout, self.transport)
@@ -380,7 +383,7 @@
def serve_bzr(transport, host=None, port=None, inet=False):
"""This is the default implementation of 'bzr serve'.
-
+
It creates a TCP or pipe smart server on 'transport, and runs it. The
transport will be decorated with a chroot and pathfilter (using
os.path.expanduser).
=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py 2011-09-13 17:43:21 +0000
+++ b/bzrlib/tests/__init__.py 2011-09-15 09:50:23 +0000
@@ -2734,9 +2734,7 @@
self.__server = None
self.reduceLockdirTimeout()
self.overrideAttr(medium.SmartServerStreamMedium,
- '_stream_medium_timeout', 4.0)
- self.overrideAttr(medium.SmartServerStreamMedium,
- '_stream_medium_fast_timeout', 0.1)
+ '_DEFAULT_CLIENT_TIMEOUT', 4.0)
def setup_smart_server_with_call_log(self):
"""Sets up a smart server as the transport server with a call log."""
=== modified file 'bzrlib/tests/test_smart_transport.py'
--- a/bzrlib/tests/test_smart_transport.py 2011-09-15 09:30:07 +0000
+++ b/bzrlib/tests/test_smart_transport.py 2011-09-15 09:50:23 +0000
@@ -975,10 +975,9 @@
def test_socket_serve_timeout_closes_socket(self):
server_sock, client_sock = self.portable_socket_pair()
server = medium.SmartServerSocketStreamMedium(
- server_sock, None)
+ server_sock, None, timeout=0.1)
# This should timeout quickly, and then close the connection so that
# client_sock recv doesn't block.
- server._stream_medium_timeout = 0.1
server.serve()
self.assertEqual('', client_sock.recv(1))
More information about the bazaar-commits
mailing list