bundles: store no/default/pipeline/multiplex
to allow code to act differently on the situation. Also added some more info message for the connection re-use function to make it clearer when connections are not re-used.
This commit is contained in:
@@ -56,7 +56,7 @@ static CURLcode bundle_create(struct SessionHandle *data,
|
|||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
(*cb_ptr)->num_connections = 0;
|
(*cb_ptr)->num_connections = 0;
|
||||||
(*cb_ptr)->server_supports_pipelining = FALSE;
|
(*cb_ptr)->multiuse = BUNDLE_UNKNOWN;
|
||||||
|
|
||||||
(*cb_ptr)->conn_list = Curl_llist_alloc((curl_llist_dtor) conn_llist_dtor);
|
(*cb_ptr)->conn_list = Curl_llist_alloc((curl_llist_dtor) conn_llist_dtor);
|
||||||
if(!(*cb_ptr)->conn_list) {
|
if(!(*cb_ptr)->conn_list) {
|
||||||
@@ -205,10 +205,8 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
key = hashkey(conn);
|
key = hashkey(conn);
|
||||||
if(!key) {
|
if(!key)
|
||||||
bundle_destroy(new_bundle);
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
|
||||||
|
|
||||||
rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle);
|
rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle);
|
||||||
free(key);
|
free(key);
|
||||||
|
@@ -30,9 +30,13 @@ struct conncache {
|
|||||||
struct timeval last_cleanup;
|
struct timeval last_cleanup;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BUNDLE_NO_MULTIUSE -1
|
||||||
|
#define BUNDLE_UNKNOWN 0 /* initial value */
|
||||||
|
#define BUNDLE_PIPELINING 1
|
||||||
|
#define BUNDLE_MULTIPLEX 2
|
||||||
|
|
||||||
struct connectbundle {
|
struct connectbundle {
|
||||||
bool server_supports_pipelining; /* TRUE if server supports pipelining,
|
int multiuse; /* supports multi-use */
|
||||||
set after first response */
|
|
||||||
size_t num_connections; /* Number of connections in the bundle */
|
size_t num_connections; /* Number of connections in the bundle */
|
||||||
struct curl_llist *conn_list; /* The connectdata members of the bundle */
|
struct curl_llist *conn_list; /* The connectdata members of the bundle */
|
||||||
};
|
};
|
||||||
|
@@ -3375,7 +3375,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
|
|||||||
|
|
||||||
/* HTTP/2 cannot blacklist multiplexing since it is a core
|
/* HTTP/2 cannot blacklist multiplexing since it is a core
|
||||||
functionality of the protocol */
|
functionality of the protocol */
|
||||||
conn->bundle->server_supports_pipelining = TRUE;
|
conn->bundle->multiuse = BUNDLE_MULTIPLEX;
|
||||||
}
|
}
|
||||||
else if(conn->httpversion >= 11 &&
|
else if(conn->httpversion >= 11 &&
|
||||||
!conn->bits.close) {
|
!conn->bits.close) {
|
||||||
@@ -3390,7 +3390,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
|
|||||||
cb_ptr = conn->bundle;
|
cb_ptr = conn->bundle;
|
||||||
if(cb_ptr) {
|
if(cb_ptr) {
|
||||||
if(!Curl_pipeline_site_blacklisted(data, conn))
|
if(!Curl_pipeline_site_blacklisted(data, conn))
|
||||||
cb_ptr->server_supports_pipelining = TRUE;
|
cb_ptr->multiuse = BUNDLE_PIPELINING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3474,9 +3474,9 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
|
|||||||
char *server_name = Curl_copy_header_value(k->p);
|
char *server_name = Curl_copy_header_value(k->p);
|
||||||
|
|
||||||
/* Turn off pipelining if the server version is blacklisted */
|
/* Turn off pipelining if the server version is blacklisted */
|
||||||
if(conn->bundle && conn->bundle->server_supports_pipelining) {
|
if(conn->bundle && (conn->bundle->multiuse == BUNDLE_PIPELINING)) {
|
||||||
if(Curl_pipeline_server_blacklisted(data, server_name))
|
if(Curl_pipeline_server_blacklisted(data, server_name))
|
||||||
conn->bundle->server_supports_pipelining = FALSE;
|
conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
|
||||||
}
|
}
|
||||||
free(server_name);
|
free(server_name);
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,7 @@
|
|||||||
#include "curl_base64.h"
|
#include "curl_base64.h"
|
||||||
#include "rawstr.h"
|
#include "rawstr.h"
|
||||||
#include "multiif.h"
|
#include "multiif.h"
|
||||||
#include "bundles.h"
|
#include "conncache.h"
|
||||||
|
|
||||||
/* The last #include files should be: */
|
/* The last #include files should be: */
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
@@ -1196,7 +1196,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
|
|||||||
|
|
||||||
conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
|
conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
|
||||||
conn->httpversion = 20;
|
conn->httpversion = 20;
|
||||||
conn->bundle->server_supports_pipelining = TRUE;
|
conn->bundle->multiuse = BUNDLE_MULTIPLEX;
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
@@ -2730,11 +2730,6 @@ size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
|
|||||||
return multi ? multi->max_total_connections : 0;
|
return multi ? multi->max_total_connections : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi)
|
|
||||||
{
|
|
||||||
return multi ? multi->max_pipeline_length : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
|
curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
|
||||||
{
|
{
|
||||||
return multi ? multi->content_length_penalty_size : 0;
|
return multi ? multi->content_length_penalty_size : 0;
|
||||||
|
@@ -59,9 +59,6 @@ void Curl_multi_process_pending_handles(struct Curl_multi *multi);
|
|||||||
/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
|
/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
|
||||||
size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
|
size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
|
||||||
|
|
||||||
/* Return the value of the CURLMOPT_MAX_PIPELINE_LENGTH option */
|
|
||||||
size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi);
|
|
||||||
|
|
||||||
/* Return the value of the CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE option */
|
/* Return the value of the CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE option */
|
||||||
curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi);
|
curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi);
|
||||||
|
|
||||||
|
47
lib/url.c
47
lib/url.c
@@ -3081,6 +3081,13 @@ static void prune_dead_connections(struct SessionHandle *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t max_pipeline_length(struct Curl_multi *multi)
|
||||||
|
{
|
||||||
|
return multi ? multi->max_pipeline_length : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Given one filled in connection struct (named needle), this function should
|
* Given one filled in connection struct (named needle), this function should
|
||||||
* detect if there already is one that has all the significant details
|
* detect if there already is one that has all the significant details
|
||||||
@@ -3120,7 +3127,7 @@ ConnectionExists(struct SessionHandle *data,
|
|||||||
particular host */
|
particular host */
|
||||||
bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache);
|
bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache);
|
||||||
if(bundle) {
|
if(bundle) {
|
||||||
size_t max_pipe_len = Curl_multi_max_pipeline_length(data->multi);
|
size_t max_pipe_len = max_pipeline_length(data->multi);
|
||||||
size_t best_pipe_len = max_pipe_len;
|
size_t best_pipe_len = max_pipe_len;
|
||||||
struct curl_llist_element *curr;
|
struct curl_llist_element *curr;
|
||||||
|
|
||||||
@@ -3128,7 +3135,7 @@ ConnectionExists(struct SessionHandle *data,
|
|||||||
needle->host.name, (void *)bundle);
|
needle->host.name, (void *)bundle);
|
||||||
|
|
||||||
/* We can't pipe if we don't know anything about the server */
|
/* We can't pipe if we don't know anything about the server */
|
||||||
if(canPipeline && !bundle->server_supports_pipelining) {
|
if(canPipeline && (bundle->multiuse <= BUNDLE_UNKNOWN)) {
|
||||||
infof(data, "Server doesn't support multi-use (yet)\n");
|
infof(data, "Server doesn't support multi-use (yet)\n");
|
||||||
canPipeline = FALSE;
|
canPipeline = FALSE;
|
||||||
}
|
}
|
||||||
@@ -3154,16 +3161,19 @@ ConnectionExists(struct SessionHandle *data,
|
|||||||
pipeLen = check->send_pipe->size + check->recv_pipe->size;
|
pipeLen = check->send_pipe->size + check->recv_pipe->size;
|
||||||
|
|
||||||
if(canPipeline) {
|
if(canPipeline) {
|
||||||
/* Make sure the pipe has only GET requests */
|
|
||||||
struct SessionHandle* sh = gethandleathead(check->send_pipe);
|
if(!check->bits.multiplex) {
|
||||||
struct SessionHandle* rh = gethandleathead(check->recv_pipe);
|
/* If not multiplexing, make sure the pipe has only GET requests */
|
||||||
if(sh) {
|
struct SessionHandle* sh = gethandleathead(check->send_pipe);
|
||||||
if(!IsPipeliningPossible(sh, check))
|
struct SessionHandle* rh = gethandleathead(check->recv_pipe);
|
||||||
continue;
|
if(sh) {
|
||||||
}
|
if(!IsPipeliningPossible(sh, check))
|
||||||
else if(rh) {
|
continue;
|
||||||
if(!IsPipeliningPossible(rh, check))
|
}
|
||||||
continue;
|
else if(rh) {
|
||||||
|
if(!IsPipeliningPossible(rh, check))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -3342,8 +3352,10 @@ ConnectionExists(struct SessionHandle *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We can't use the connection if the pipe is full */
|
/* We can't use the connection if the pipe is full */
|
||||||
if(pipeLen >= max_pipe_len)
|
if(pipeLen >= max_pipe_len) {
|
||||||
|
infof(data, "Pipe is full, skip (%d)\n", pipeLen);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* We can't use the connection if the pipe is penalized */
|
/* We can't use the connection if the pipe is penalized */
|
||||||
if(Curl_pipeline_penalized(data, check))
|
if(Curl_pipeline_penalized(data, check))
|
||||||
@@ -5715,8 +5727,11 @@ static CURLcode create_conn(struct SessionHandle *data,
|
|||||||
conn_candidate->data = data;
|
conn_candidate->data = data;
|
||||||
(void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
|
(void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
|
infof(data, "No more connections allowed to host: %d\n",
|
||||||
|
max_host_connections);
|
||||||
no_connections_available = TRUE;
|
no_connections_available = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(max_total_connections > 0 &&
|
if(max_total_connections > 0 &&
|
||||||
@@ -5731,8 +5746,10 @@ static CURLcode create_conn(struct SessionHandle *data,
|
|||||||
conn_candidate->data = data;
|
conn_candidate->data = data;
|
||||||
(void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
|
(void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
|
infof(data, "No connections available in cache\n");
|
||||||
no_connections_available = TRUE;
|
no_connections_available = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user