mirror of
https://github.com/curl/curl.git
synced 2026-08-26 04:13:31 +03:00
conncache: count shutdowns against host and max limits
Count connections to a host against a possibly configured destination limit. Trigger multi `connchange` when a connection has been shutdown, so pending transfers can try to get a connection once again. Reported-by: baranyaib90 on github Fixes #15857 Closes #15879
This commit is contained in:
parent
508861eb80
commit
bd3c027ac9
5 changed files with 102 additions and 21 deletions
|
|
@ -312,10 +312,11 @@ int main(int argc, char *argv[])
|
|||
struct curl_slist *host = NULL;
|
||||
char *resolve = NULL;
|
||||
size_t max_host_conns = 0;
|
||||
size_t max_total_conns = 0;
|
||||
int fresh_connect = 0;
|
||||
int result = 0;
|
||||
|
||||
while((ch = getopt(argc, argv, "aefhm:n:xA:F:M:P:r:V:")) != -1) {
|
||||
while((ch = getopt(argc, argv, "aefhm:n:xA:F:M:P:r:T:V:")) != -1) {
|
||||
switch(ch) {
|
||||
case 'h':
|
||||
usage(NULL);
|
||||
|
|
@ -355,6 +356,9 @@ int main(int argc, char *argv[])
|
|||
free(resolve);
|
||||
resolve = strdup(optarg);
|
||||
break;
|
||||
case 'T':
|
||||
max_total_conns = (size_t)strtol(optarg, NULL, 10);
|
||||
break;
|
||||
case 'V': {
|
||||
if(!strcmp("http/1.1", optarg))
|
||||
http_version = CURL_HTTP_VERSION_1_1;
|
||||
|
|
@ -413,6 +417,8 @@ int main(int argc, char *argv[])
|
|||
|
||||
multi_handle = curl_multi_init();
|
||||
curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
|
||||
curl_multi_setopt(multi_handle, CURLMOPT_MAX_TOTAL_CONNECTIONS,
|
||||
(long)max_total_conns);
|
||||
curl_multi_setopt(multi_handle, CURLMOPT_MAX_HOST_CONNECTIONS,
|
||||
(long)max_host_conns);
|
||||
|
||||
|
|
|
|||
|
|
@ -638,8 +638,8 @@ class TestDownload:
|
|||
def test_02_33_max_host_conns(self, env: Env, httpd, nghttpx, proto, max_host_conns):
|
||||
if proto == 'h3' and not env.have_h3():
|
||||
pytest.skip("h3 not supported")
|
||||
count = 100
|
||||
max_parallel = 100
|
||||
count = 50
|
||||
max_parallel = 50
|
||||
docname = 'data-10k'
|
||||
port = env.port_for(proto)
|
||||
url = f'https://{env.domain1}:{port}/{docname}'
|
||||
|
|
@ -657,3 +657,46 @@ class TestDownload:
|
|||
r.check_exit_code(0)
|
||||
srcfile = os.path.join(httpd.docs_dir, docname)
|
||||
self.check_downloads(client, srcfile, count)
|
||||
if max_host_conns > 0:
|
||||
matched_lines = 0
|
||||
for line in r.trace_lines:
|
||||
m = re.match(r'.*The cache now contains (\d+) members.*', line)
|
||||
if m:
|
||||
matched_lines += 1
|
||||
n = int(m.group(1))
|
||||
assert n <= max_host_conns
|
||||
assert matched_lines > 0
|
||||
|
||||
@pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
|
||||
@pytest.mark.parametrize("max_total_conns", [0, 1, 5])
|
||||
def test_02_34_max_total_conns(self, env: Env, httpd, nghttpx, proto, max_total_conns):
|
||||
if proto == 'h3' and not env.have_h3():
|
||||
pytest.skip("h3 not supported")
|
||||
count = 50
|
||||
max_parallel = 50
|
||||
docname = 'data-10k'
|
||||
port = env.port_for(proto)
|
||||
url = f'https://{env.domain1}:{port}/{docname}'
|
||||
client = LocalClient(name='hx-download', env=env)
|
||||
if not client.exists():
|
||||
pytest.skip(f'example client not built: {client.name}')
|
||||
r = client.run(args=[
|
||||
'-n', f'{count}',
|
||||
'-m', f'{max_parallel}',
|
||||
'-x', # always use a fresh connection
|
||||
'-T', str(max_total_conns), # limit total connections
|
||||
'-r', f'{env.domain1}:{port}:127.0.0.1',
|
||||
'-V', proto, url
|
||||
])
|
||||
r.check_exit_code(0)
|
||||
srcfile = os.path.join(httpd.docs_dir, docname)
|
||||
self.check_downloads(client, srcfile, count)
|
||||
if max_total_conns > 0:
|
||||
matched_lines = 0
|
||||
for line in r.trace_lines:
|
||||
m = re.match(r'.*The cache now contains (\d+) members.*', line)
|
||||
if m:
|
||||
matched_lines += 1
|
||||
n = int(m.group(1))
|
||||
assert n <= max_total_conns
|
||||
assert matched_lines > 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue