1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-21 07:38:49 -05:00

share: add support for sharing the connection cache

This commit is contained in:
Daniel Stenberg 2017-11-01 23:37:45 +01:00
parent e871ab56ed
commit 67c55a26d5
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
10 changed files with 230 additions and 128 deletions

68
debug/shared-conn.c Normal file
View File

@ -0,0 +1,68 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
/* <DESC>
* Two HTTP GET using connection sharing with the share inteface
* </DESC>
*/
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
CURLSH *share;
int i;
share = curl_share_init();
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
/* Loop the transfer and cleanup the handle properly every lap. This will
still reuse connections since the pool is in the shared object! */
for(i = 0; i < 3; i++) {
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
/* example.com is redirected, so we tell libcurl to follow redirection */
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
/* use the connection pool in the share object */
curl_easy_setopt(curl, CURLOPT_SHARE, share);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
}
curl_share_cleanup(share);
return 0;
}

View File

@ -31,11 +31,21 @@
#include "multiif.h" #include "multiif.h"
#include "sendf.h" #include "sendf.h"
#include "conncache.h" #include "conncache.h"
#include "share.h"
#include "sigpipe.h"
#include "connect.h"
/* The last 3 #include files should be in this order */ /* The last 3 #include files should be in this order */
#include "curl_printf.h" #include "curl_printf.h"
#include "curl_memory.h" #include "curl_memory.h"
#include "memdebug.h" #include "memdebug.h"
#define CONN_LOCK(x) if((x)->share) \
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
#define CONN_UNLOCK(x) if((x)->share) \
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
static void conn_llist_dtor(void *user, void *element) static void conn_llist_dtor(void *user, void *element)
{ {
struct connectdata *data = element; struct connectdata *data = element;
@ -109,8 +119,23 @@ static void free_bundle_hash_entry(void *freethis)
int Curl_conncache_init(struct conncache *connc, int size) int Curl_conncache_init(struct conncache *connc, int size)
{ {
return Curl_hash_init(&connc->hash, size, Curl_hash_str, int rc;
Curl_str_key_compare, free_bundle_hash_entry);
/* allocate a new easy handle to use when closing cached connections */
connc->closure_handle = curl_easy_init();
if(!connc->closure_handle)
return 1; /* bad */
rc = Curl_hash_init(&connc->hash, size, Curl_hash_str,
Curl_str_key_compare, free_bundle_hash_entry);
if(rc) {
Curl_close(connc->closure_handle);
connc->closure_handle = NULL;
}
else
connc->closure_handle->state.conn_cache = connc;
return rc;
} }
void Curl_conncache_destroy(struct conncache *connc) void Curl_conncache_destroy(struct conncache *connc)
@ -149,7 +174,9 @@ struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
if(connc) { if(connc) {
char key[128]; char key[128];
hashkey(conn, key, sizeof(key)); hashkey(conn, key, sizeof(key));
CONN_LOCK(conn->data);
bundle = Curl_hash_pick(&connc->hash, key, strlen(key)); bundle = Curl_hash_pick(&connc->hash, key, strlen(key));
CONN_UNLOCK(conn->data);
} }
return bundle; return bundle;
@ -206,7 +233,9 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
return result; return result;
hashkey(conn, key, sizeof(key)); hashkey(conn, key, sizeof(key));
CONN_LOCK(data);
rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle); rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle);
CONN_UNLOCK(data);
if(!rc) { if(!rc) {
bundle_destroy(new_bundle); bundle_destroy(new_bundle);
@ -215,12 +244,15 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
bundle = new_bundle; bundle = new_bundle;
} }
CONN_LOCK(data);
result = bundle_add_conn(bundle, conn); result = bundle_add_conn(bundle, conn);
if(result) { if(result) {
if(new_bundle) if(new_bundle)
conncache_remove_bundle(data->state.conn_cache, new_bundle); conncache_remove_bundle(data->state.conn_cache, new_bundle);
CONN_UNLOCK(data);
return result; return result;
} }
CONN_UNLOCK(data);
conn->connection_id = connc->next_connection_id++; conn->connection_id = connc->next_connection_id++;
connc->num_connections++; connc->num_connections++;
@ -240,11 +272,11 @@ void Curl_conncache_remove_conn(struct conncache *connc,
/* The bundle pointer can be NULL, since this function can be called /* The bundle pointer can be NULL, since this function can be called
due to a failed connection attempt, before being added to a bundle */ due to a failed connection attempt, before being added to a bundle */
if(bundle) { if(bundle) {
CONN_LOCK(conn->data);
bundle_remove_conn(bundle, conn); bundle_remove_conn(bundle, conn);
if(bundle->num_connections == 0) { if(bundle->num_connections == 0)
conncache_remove_bundle(connc, bundle); conncache_remove_bundle(connc, bundle);
} CONN_UNLOCK(conn->data);
if(connc) { if(connc) {
connc->num_connections--; connc->num_connections--;
@ -261,7 +293,8 @@ void Curl_conncache_remove_conn(struct conncache *connc,
Return 0 from func() to continue the loop, return 1 to abort it. Return 0 from func() to continue the loop, return 1 to abort it.
*/ */
void Curl_conncache_foreach(struct conncache *connc, void Curl_conncache_foreach(struct Curl_easy *data,
struct conncache *connc,
void *param, void *param,
int (*func)(struct connectdata *conn, void *param)) int (*func)(struct connectdata *conn, void *param))
{ {
@ -272,6 +305,7 @@ void Curl_conncache_foreach(struct conncache *connc,
if(!connc) if(!connc)
return; return;
CONN_LOCK(data);
Curl_hash_start_iterate(&connc->hash, &iter); Curl_hash_start_iterate(&connc->hash, &iter);
he = Curl_hash_next_element(&iter); he = Curl_hash_next_element(&iter);
@ -288,14 +322,21 @@ void Curl_conncache_foreach(struct conncache *connc,
struct connectdata *conn = curr->ptr; struct connectdata *conn = curr->ptr;
curr = curr->next; curr = curr->next;
if(1 == func(conn, param)) if(1 == func(conn, param)) {
CONN_UNLOCK(data);
return; return;
}
} }
} }
CONN_UNLOCK(data);
} }
/* Return the first connection found in the cache. Used when closing all /* Return the first connection found in the cache. Used when closing all
connections */ connections.
NOTE: no locking is done here as this is presumably only done when cleaning
up a cache!
*/
struct connectdata * struct connectdata *
Curl_conncache_find_first_connection(struct conncache *connc) Curl_conncache_find_first_connection(struct conncache *connc)
{ {
@ -321,6 +362,90 @@ Curl_conncache_find_first_connection(struct conncache *connc)
return NULL; return NULL;
} }
/*
* This function finds the connection in the connection
* cache that has been unused for the longest time.
*
* Returns the pointer to the oldest idle connection, or NULL if none was
* found.
*/
struct connectdata *
Curl_conncache_oldest_idle(struct Curl_easy *data)
{
struct conncache *bc = data->state.conn_cache;
struct curl_hash_iterator iter;
struct curl_llist_element *curr;
struct curl_hash_element *he;
timediff_t highscore =- 1;
timediff_t score;
struct curltime now;
struct connectdata *conn_candidate = NULL;
struct connectbundle *bundle;
now = Curl_now();
CONN_LOCK(data);
Curl_hash_start_iterate(&bc->hash, &iter);
he = Curl_hash_next_element(&iter);
while(he) {
struct connectdata *conn;
bundle = he->ptr;
curr = bundle->conn_list.head;
while(curr) {
conn = curr->ptr;
if(!conn->inuse) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->now);
if(score > highscore) {
highscore = score;
conn_candidate = conn;
}
}
curr = curr->next;
}
he = Curl_hash_next_element(&iter);
}
CONN_UNLOCK(data);
return conn_candidate;
}
void Curl_conncache_close_all_connections(struct conncache *connc)
{
struct connectdata *conn;
conn = Curl_conncache_find_first_connection(connc);
while(conn) {
SIGPIPE_VARIABLE(pipe_st);
conn->data = connc->closure_handle;
sigpipe_ignore(conn->data, &pipe_st);
conn->data->easy_conn = NULL; /* clear the easy handle's connection
pointer */
/* This will remove the connection from the cache */
connclose(conn, "kill all");
(void)Curl_disconnect(conn, FALSE);
sigpipe_restore(&pipe_st);
conn = Curl_conncache_find_first_connection(connc);
}
if(connc->closure_handle) {
SIGPIPE_VARIABLE(pipe_st);
sigpipe_ignore(connc->closure_handle, &pipe_st);
Curl_hostcache_clean(connc->closure_handle,
connc->closure_handle->dns.hostcache);
Curl_close(connc->closure_handle);
sigpipe_restore(&pipe_st);
}
}
#if 0 #if 0
/* Useful for debugging the connection cache */ /* Useful for debugging the connection cache */

View File

@ -28,6 +28,8 @@ struct conncache {
size_t num_connections; size_t num_connections;
long next_connection_id; long next_connection_id;
struct curltime last_cleanup; struct curltime last_cleanup;
/* handle used for closing cached connections */
struct Curl_easy *closure_handle;
}; };
#define BUNDLE_NO_MULTIUSE -1 #define BUNDLE_NO_MULTIUSE -1
@ -41,8 +43,8 @@ struct connectbundle {
struct curl_llist conn_list; /* The connectdata members of the bundle */ struct curl_llist conn_list; /* The connectdata members of the bundle */
}; };
/* returns 1 on error, 0 is fine */
int Curl_conncache_init(struct conncache *, int size); int Curl_conncache_init(struct conncache *, int size);
void Curl_conncache_destroy(struct conncache *connc); void Curl_conncache_destroy(struct conncache *connc);
/* return the correct bundle, to a host or a proxy */ /* return the correct bundle, to a host or a proxy */
@ -55,7 +57,8 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
void Curl_conncache_remove_conn(struct conncache *connc, void Curl_conncache_remove_conn(struct conncache *connc,
struct connectdata *conn); struct connectdata *conn);
void Curl_conncache_foreach(struct conncache *connc, void Curl_conncache_foreach(struct Curl_easy *data,
struct conncache *connc,
void *param, void *param,
int (*func)(struct connectdata *conn, int (*func)(struct connectdata *conn,
void *param)); void *param));
@ -63,6 +66,9 @@ void Curl_conncache_foreach(struct conncache *connc,
struct connectdata * struct connectdata *
Curl_conncache_find_first_connection(struct conncache *connc); Curl_conncache_find_first_connection(struct conncache *connc);
struct connectdata *
Curl_conncache_oldest_idle(struct Curl_easy *data);
void Curl_conncache_close_all_connections(struct conncache *connc);
void Curl_conncache_print(struct conncache *connc); void Curl_conncache_print(struct conncache *connc);
#endif /* HEADER_CURL_CONNCACHE_H */ #endif /* HEADER_CURL_CONNCACHE_H */

View File

@ -1224,7 +1224,7 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
find.tofind = data->state.lastconnect; find.tofind = data->state.lastconnect;
find.found = FALSE; find.found = FALSE;
Curl_conncache_foreach(data->multi_easy? Curl_conncache_foreach(data, data->multi_easy?
&data->multi_easy->conn_cache: &data->multi_easy->conn_cache:
&data->multi->conn_cache, &find, conn_is_conn); &data->multi->conn_cache, &find, conn_is_conn);

View File

@ -326,14 +326,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
Curl_llist_init(&multi->msglist, multi_freeamsg); Curl_llist_init(&multi->msglist, multi_freeamsg);
Curl_llist_init(&multi->pending, multi_freeamsg); Curl_llist_init(&multi->pending, multi_freeamsg);
/* allocate a new easy handle to use when closing cached connections */
multi->closure_handle = curl_easy_init();
if(!multi->closure_handle)
goto error;
multi->closure_handle->multi = multi;
multi->closure_handle->state.conn_cache = &multi->conn_cache;
multi->max_pipeline_length = 5; multi->max_pipeline_length = 5;
/* -1 means it not set by user, use the default value */ /* -1 means it not set by user, use the default value */
@ -345,8 +337,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
Curl_hash_destroy(&multi->sockhash); Curl_hash_destroy(&multi->sockhash);
Curl_hash_destroy(&multi->hostcache); Curl_hash_destroy(&multi->hostcache);
Curl_conncache_destroy(&multi->conn_cache); Curl_conncache_destroy(&multi->conn_cache);
Curl_close(multi->closure_handle);
multi->closure_handle = NULL;
Curl_llist_destroy(&multi->msglist, NULL); Curl_llist_destroy(&multi->msglist, NULL);
Curl_llist_destroy(&multi->pending, NULL); Curl_llist_destroy(&multi->pending, NULL);
@ -407,8 +397,11 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
data->dns.hostcachetype = HCACHE_MULTI; data->dns.hostcachetype = HCACHE_MULTI;
} }
/* Point to the multi's connection cache */ /* Point to the shared or multi handle connection cache */
data->state.conn_cache = &multi->conn_cache; if(data->share && (data->share->specifier & (1<< CURL_LOCK_DATA_CONNECT)))
data->state.conn_cache = &data->share->conn_cache;
else
data->state.conn_cache = &multi->conn_cache;
/* This adds the new entry at the 'end' of the doubly-linked circular /* This adds the new entry at the 'end' of the doubly-linked circular
list of Curl_easy structs to try and maintain a FIFO queue so list of Curl_easy structs to try and maintain a FIFO queue so
@ -462,8 +455,8 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
state somewhat we clone the timeouts from each added handle so that the state somewhat we clone the timeouts from each added handle so that the
closure handle always has the same timeouts as the most recently added closure handle always has the same timeouts as the most recently added
easy handle. */ easy handle. */
multi->closure_handle->set.timeout = data->set.timeout; data->state.conn_cache->closure_handle->set.timeout = data->set.timeout;
multi->closure_handle->set.server_response_timeout = data->state.conn_cache->closure_handle->set.server_response_timeout =
data->set.server_response_timeout; data->set.server_response_timeout;
update_timer(multi); update_timer(multi);
@ -504,7 +497,7 @@ ConnectionDone(struct Curl_easy *data, struct connectdata *conn)
data->state.conn_cache->num_connections > maxconnects) { data->state.conn_cache->num_connections > maxconnects) {
infof(data, "Connection cache is full, closing the oldest one.\n"); infof(data, "Connection cache is full, closing the oldest one.\n");
conn_candidate = Curl_oldest_idle_connection(data); conn_candidate = Curl_conncache_oldest_idle(data);
if(conn_candidate) { if(conn_candidate) {
/* Set the connection's owner correctly */ /* Set the connection's owner correctly */
@ -2201,36 +2194,12 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
return returncode; return returncode;
} }
static void close_all_connections(struct Curl_multi *multi)
{
struct connectdata *conn;
conn = Curl_conncache_find_first_connection(&multi->conn_cache);
while(conn) {
SIGPIPE_VARIABLE(pipe_st);
conn->data = multi->closure_handle;
sigpipe_ignore(conn->data, &pipe_st);
conn->data->easy_conn = NULL; /* clear the easy handle's connection
pointer */
/* This will remove the connection from the cache */
connclose(conn, "kill all");
(void)Curl_disconnect(conn, FALSE);
sigpipe_restore(&pipe_st);
conn = Curl_conncache_find_first_connection(&multi->conn_cache);
}
}
CURLMcode curl_multi_cleanup(struct Curl_multi *multi) CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
{ {
struct Curl_easy *data; struct Curl_easy *data;
struct Curl_easy *nextdata; struct Curl_easy *nextdata;
if(GOOD_MULTI_HANDLE(multi)) { if(GOOD_MULTI_HANDLE(multi)) {
bool restore_pipe = FALSE;
SIGPIPE_VARIABLE(pipe_st);
multi->type = 0; /* not good anymore */ multi->type = 0; /* not good anymore */
/* Firsrt remove all remaining easy handles */ /* Firsrt remove all remaining easy handles */
@ -2255,18 +2224,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
} }
/* Close all the connections in the connection cache */ /* Close all the connections in the connection cache */
close_all_connections(multi); Curl_conncache_close_all_connections(&multi->conn_cache);
if(multi->closure_handle) {
sigpipe_ignore(multi->closure_handle, &pipe_st);
restore_pipe = TRUE;
multi->closure_handle->dns.hostcache = &multi->hostcache;
Curl_hostcache_clean(multi->closure_handle,
multi->closure_handle->dns.hostcache);
Curl_close(multi->closure_handle);
}
Curl_hash_destroy(&multi->sockhash); Curl_hash_destroy(&multi->sockhash);
Curl_conncache_destroy(&multi->conn_cache); Curl_conncache_destroy(&multi->conn_cache);
@ -2280,8 +2238,6 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl); Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl);
free(multi); free(multi);
if(restore_pipe)
sigpipe_restore(&pipe_st);
return CURLM_OK; return CURLM_OK;
} }

View File

@ -114,10 +114,6 @@ struct Curl_multi {
/* Shared connection cache (bundles)*/ /* Shared connection cache (bundles)*/
struct conncache conn_cache; struct conncache conn_cache;
/* This handle will be used for closing the cached connections in
curl_multi_cleanup() */
struct Curl_easy *closure_handle;
long maxconnects; /* if >0, a fixed limit of the maximum number of entries long maxconnects; /* if >0, a fixed limit of the maximum number of entries
we're allowed to grow the connection cache to */ we're allowed to grow the connection cache to */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -102,6 +102,8 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
break; break;
case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */ case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */
if(Curl_conncache_init(&share->conn_cache, 103))
return CURLSHE_NOMEM;
break; break;
default: default:
@ -186,6 +188,8 @@ curl_share_cleanup(struct Curl_share *share)
return CURLSHE_IN_USE; return CURLSHE_IN_USE;
} }
Curl_conncache_close_all_connections(&share->conn_cache);
Curl_conncache_destroy(&share->conn_cache);
Curl_hash_destroy(&share->hostcache); Curl_hash_destroy(&share->hostcache);
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -26,6 +26,7 @@
#include <curl/curl.h> #include <curl/curl.h>
#include "cookie.h" #include "cookie.h"
#include "urldata.h" #include "urldata.h"
#include "conncache.h"
/* SalfordC says "A structure member may not be volatile". Hence: /* SalfordC says "A structure member may not be volatile". Hence:
*/ */
@ -43,7 +44,7 @@ struct Curl_share {
curl_lock_function lockfunc; curl_lock_function lockfunc;
curl_unlock_function unlockfunc; curl_unlock_function unlockfunc;
void *clientdata; void *clientdata;
struct conncache conn_cache;
struct curl_hash hostcache; struct curl_hash hostcache;
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
struct CookieInfo *cookies; struct CookieInfo *cookies;

View File

@ -3448,58 +3448,6 @@ static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke)
} }
} }
/*
* This function finds the connection in the connection
* cache that has been unused for the longest time.
*
* Returns the pointer to the oldest idle connection, or NULL if none was
* found.
*/
struct connectdata *
Curl_oldest_idle_connection(struct Curl_easy *data)
{
struct conncache *bc = data->state.conn_cache;
struct curl_hash_iterator iter;
struct curl_llist_element *curr;
struct curl_hash_element *he;
timediff_t highscore =- 1;
timediff_t score;
struct curltime now;
struct connectdata *conn_candidate = NULL;
struct connectbundle *bundle;
now = Curl_now();
Curl_hash_start_iterate(&bc->hash, &iter);
he = Curl_hash_next_element(&iter);
while(he) {
struct connectdata *conn;
bundle = he->ptr;
curr = bundle->conn_list.head;
while(curr) {
conn = curr->ptr;
if(!conn->inuse) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->now);
if(score > highscore) {
highscore = score;
conn_candidate = conn;
}
}
curr = curr->next;
}
he = Curl_hash_next_element(&iter);
}
return conn_candidate;
}
static bool static bool
proxy_info_matches(const struct proxy_info* data, proxy_info_matches(const struct proxy_info* data,
const struct proxy_info* needle) const struct proxy_info* needle)
@ -3619,7 +3567,7 @@ static void prune_dead_connections(struct Curl_easy *data)
time_t elapsed = Curl_timediff(now, data->state.conn_cache->last_cleanup); time_t elapsed = Curl_timediff(now, data->state.conn_cache->last_cleanup);
if(elapsed >= 1000L) { if(elapsed >= 1000L) {
Curl_conncache_foreach(data->state.conn_cache, data, Curl_conncache_foreach(data, data->state.conn_cache, data,
call_disconnect_if_dead); call_disconnect_if_dead);
data->state.conn_cache->last_cleanup = now; data->state.conn_cache->last_cleanup = now;
} }
@ -6996,7 +6944,7 @@ static CURLcode create_conn(struct Curl_easy *data,
struct connectdata *conn_candidate; struct connectdata *conn_candidate;
/* The cache is full. Let's see if we can kill a connection. */ /* The cache is full. Let's see if we can kill a connection. */
conn_candidate = Curl_oldest_idle_connection(data); conn_candidate = Curl_conncache_oldest_idle(data);
if(conn_candidate) { if(conn_candidate) {
/* Set the connection's owner correctly, then kill it */ /* Set the connection's owner correctly, then kill it */

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -57,8 +57,6 @@ CURLcode Curl_addHandleToPipeline(struct Curl_easy *handle,
struct curl_llist *pipeline); struct curl_llist *pipeline);
int Curl_removeHandleFromPipeline(struct Curl_easy *handle, int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
struct curl_llist *pipeline); struct curl_llist *pipeline);
struct connectdata *
Curl_oldest_idle_connection(struct Curl_easy *data);
/* remove the specified connection from all (possible) pipelines and related /* remove the specified connection from all (possible) pipelines and related
queues */ queues */
void Curl_getoff_all_pipelines(struct Curl_easy *data, void Curl_getoff_all_pipelines(struct Curl_easy *data,