Loading debug/shared-conn.c 0 → 100644 +68 −0 Original line number Diff line number Diff line /*************************************************************************** * _ _ ____ _ * 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; } lib/conncache.c +133 −8 Original line number Diff line number Diff line Loading @@ -31,11 +31,21 @@ #include "multiif.h" #include "sendf.h" #include "conncache.h" #include "share.h" #include "sigpipe.h" #include "connect.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.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) { struct connectdata *data = element; Loading Loading @@ -109,8 +119,23 @@ static void free_bundle_hash_entry(void *freethis) int Curl_conncache_init(struct conncache *connc, int size) { return Curl_hash_init(&connc->hash, size, Curl_hash_str, int rc; /* 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) Loading Loading @@ -149,7 +174,9 @@ struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, if(connc) { char key[128]; hashkey(conn, key, sizeof(key)); CONN_LOCK(conn->data); bundle = Curl_hash_pick(&connc->hash, key, strlen(key)); CONN_UNLOCK(conn->data); } return bundle; Loading Loading @@ -206,7 +233,9 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, return result; hashkey(conn, key, sizeof(key)); CONN_LOCK(data); rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle); CONN_UNLOCK(data); if(!rc) { bundle_destroy(new_bundle); Loading @@ -215,12 +244,15 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, bundle = new_bundle; } CONN_LOCK(data); result = bundle_add_conn(bundle, conn); if(result) { if(new_bundle) conncache_remove_bundle(data->state.conn_cache, new_bundle); CONN_UNLOCK(data); return result; } CONN_UNLOCK(data); conn->connection_id = connc->next_connection_id++; connc->num_connections++; Loading @@ -240,11 +272,11 @@ void Curl_conncache_remove_conn(struct conncache *connc, /* The bundle pointer can be NULL, since this function can be called due to a failed connection attempt, before being added to a bundle */ if(bundle) { CONN_LOCK(conn->data); bundle_remove_conn(bundle, conn); if(bundle->num_connections == 0) { if(bundle->num_connections == 0) conncache_remove_bundle(connc, bundle); } CONN_UNLOCK(conn->data); if(connc) { connc->num_connections--; Loading @@ -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. */ void Curl_conncache_foreach(struct conncache *connc, void Curl_conncache_foreach(struct Curl_easy *data, struct conncache *connc, void *param, int (*func)(struct connectdata *conn, void *param)) { Loading @@ -272,6 +305,7 @@ void Curl_conncache_foreach(struct conncache *connc, if(!connc) return; CONN_LOCK(data); Curl_hash_start_iterate(&connc->hash, &iter); he = Curl_hash_next_element(&iter); Loading @@ -288,14 +322,21 @@ void Curl_conncache_foreach(struct conncache *connc, struct connectdata *conn = curr->ptr; curr = curr->next; if(1 == func(conn, param)) if(1 == func(conn, param)) { CONN_UNLOCK(data); return; } } } CONN_UNLOCK(data); } /* 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 * Curl_conncache_find_first_connection(struct conncache *connc) { Loading @@ -321,6 +362,90 @@ Curl_conncache_find_first_connection(struct conncache *connc) 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 /* Useful for debugging the connection cache */ Loading lib/conncache.h +8 −2 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ struct conncache { size_t num_connections; long next_connection_id; struct curltime last_cleanup; /* handle used for closing cached connections */ struct Curl_easy *closure_handle; }; #define BUNDLE_NO_MULTIUSE -1 Loading @@ -41,8 +43,8 @@ struct connectbundle { 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); void Curl_conncache_destroy(struct conncache *connc); /* return the correct bundle, to a host or a proxy */ Loading @@ -55,7 +57,8 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, void Curl_conncache_remove_conn(struct conncache *connc, struct connectdata *conn); void Curl_conncache_foreach(struct conncache *connc, void Curl_conncache_foreach(struct Curl_easy *data, struct conncache *connc, void *param, int (*func)(struct connectdata *conn, void *param)); Loading @@ -63,6 +66,9 @@ void Curl_conncache_foreach(struct conncache *connc, struct connectdata * 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); #endif /* HEADER_CURL_CONNCACHE_H */ lib/connect.c +1 −1 Original line number Diff line number Diff line Loading @@ -1224,7 +1224,7 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, find.tofind = data->state.lastconnect; find.found = FALSE; Curl_conncache_foreach(data->multi_easy? Curl_conncache_foreach(data, data->multi_easy? &data->multi_easy->conn_cache: &data->multi->conn_cache, &find, conn_is_conn); Loading lib/multi.c +9 −53 Original line number Diff line number Diff line Loading @@ -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->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; /* -1 means it not set by user, use the default value */ Loading @@ -345,8 +337,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ Curl_hash_destroy(&multi->sockhash); Curl_hash_destroy(&multi->hostcache); 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->pending, NULL); Loading Loading @@ -407,7 +397,10 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, data->dns.hostcachetype = HCACHE_MULTI; } /* Point to the multi's connection cache */ /* Point to the shared or multi handle connection 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 Loading Loading @@ -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 closure handle always has the same timeouts as the most recently added easy handle. */ multi->closure_handle->set.timeout = data->set.timeout; multi->closure_handle->set.server_response_timeout = data->state.conn_cache->closure_handle->set.timeout = data->set.timeout; data->state.conn_cache->closure_handle->set.server_response_timeout = data->set.server_response_timeout; update_timer(multi); Loading Loading @@ -504,7 +497,7 @@ ConnectionDone(struct Curl_easy *data, struct connectdata *conn) data->state.conn_cache->num_connections > maxconnects) { 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) { /* Set the connection's owner correctly */ Loading Loading @@ -2201,36 +2194,12 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles) 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) { struct Curl_easy *data; struct Curl_easy *nextdata; if(GOOD_MULTI_HANDLE(multi)) { bool restore_pipe = FALSE; SIGPIPE_VARIABLE(pipe_st); multi->type = 0; /* not good anymore */ /* Firsrt remove all remaining easy handles */ Loading @@ -2255,18 +2224,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) } /* Close all the connections in the connection cache */ close_all_connections(multi); 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_conncache_close_all_connections(&multi->conn_cache); Curl_hash_destroy(&multi->sockhash); Curl_conncache_destroy(&multi->conn_cache); Loading @@ -2280,8 +2238,6 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl); free(multi); if(restore_pipe) sigpipe_restore(&pipe_st); return CURLM_OK; } Loading Loading
debug/shared-conn.c 0 → 100644 +68 −0 Original line number Diff line number Diff line /*************************************************************************** * _ _ ____ _ * 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; }
lib/conncache.c +133 −8 Original line number Diff line number Diff line Loading @@ -31,11 +31,21 @@ #include "multiif.h" #include "sendf.h" #include "conncache.h" #include "share.h" #include "sigpipe.h" #include "connect.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.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) { struct connectdata *data = element; Loading Loading @@ -109,8 +119,23 @@ static void free_bundle_hash_entry(void *freethis) int Curl_conncache_init(struct conncache *connc, int size) { return Curl_hash_init(&connc->hash, size, Curl_hash_str, int rc; /* 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) Loading Loading @@ -149,7 +174,9 @@ struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, if(connc) { char key[128]; hashkey(conn, key, sizeof(key)); CONN_LOCK(conn->data); bundle = Curl_hash_pick(&connc->hash, key, strlen(key)); CONN_UNLOCK(conn->data); } return bundle; Loading Loading @@ -206,7 +233,9 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, return result; hashkey(conn, key, sizeof(key)); CONN_LOCK(data); rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle); CONN_UNLOCK(data); if(!rc) { bundle_destroy(new_bundle); Loading @@ -215,12 +244,15 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, bundle = new_bundle; } CONN_LOCK(data); result = bundle_add_conn(bundle, conn); if(result) { if(new_bundle) conncache_remove_bundle(data->state.conn_cache, new_bundle); CONN_UNLOCK(data); return result; } CONN_UNLOCK(data); conn->connection_id = connc->next_connection_id++; connc->num_connections++; Loading @@ -240,11 +272,11 @@ void Curl_conncache_remove_conn(struct conncache *connc, /* The bundle pointer can be NULL, since this function can be called due to a failed connection attempt, before being added to a bundle */ if(bundle) { CONN_LOCK(conn->data); bundle_remove_conn(bundle, conn); if(bundle->num_connections == 0) { if(bundle->num_connections == 0) conncache_remove_bundle(connc, bundle); } CONN_UNLOCK(conn->data); if(connc) { connc->num_connections--; Loading @@ -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. */ void Curl_conncache_foreach(struct conncache *connc, void Curl_conncache_foreach(struct Curl_easy *data, struct conncache *connc, void *param, int (*func)(struct connectdata *conn, void *param)) { Loading @@ -272,6 +305,7 @@ void Curl_conncache_foreach(struct conncache *connc, if(!connc) return; CONN_LOCK(data); Curl_hash_start_iterate(&connc->hash, &iter); he = Curl_hash_next_element(&iter); Loading @@ -288,14 +322,21 @@ void Curl_conncache_foreach(struct conncache *connc, struct connectdata *conn = curr->ptr; curr = curr->next; if(1 == func(conn, param)) if(1 == func(conn, param)) { CONN_UNLOCK(data); return; } } } CONN_UNLOCK(data); } /* 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 * Curl_conncache_find_first_connection(struct conncache *connc) { Loading @@ -321,6 +362,90 @@ Curl_conncache_find_first_connection(struct conncache *connc) 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 /* Useful for debugging the connection cache */ Loading
lib/conncache.h +8 −2 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ struct conncache { size_t num_connections; long next_connection_id; struct curltime last_cleanup; /* handle used for closing cached connections */ struct Curl_easy *closure_handle; }; #define BUNDLE_NO_MULTIUSE -1 Loading @@ -41,8 +43,8 @@ struct connectbundle { 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); void Curl_conncache_destroy(struct conncache *connc); /* return the correct bundle, to a host or a proxy */ Loading @@ -55,7 +57,8 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, void Curl_conncache_remove_conn(struct conncache *connc, struct connectdata *conn); void Curl_conncache_foreach(struct conncache *connc, void Curl_conncache_foreach(struct Curl_easy *data, struct conncache *connc, void *param, int (*func)(struct connectdata *conn, void *param)); Loading @@ -63,6 +66,9 @@ void Curl_conncache_foreach(struct conncache *connc, struct connectdata * 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); #endif /* HEADER_CURL_CONNCACHE_H */
lib/connect.c +1 −1 Original line number Diff line number Diff line Loading @@ -1224,7 +1224,7 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, find.tofind = data->state.lastconnect; find.found = FALSE; Curl_conncache_foreach(data->multi_easy? Curl_conncache_foreach(data, data->multi_easy? &data->multi_easy->conn_cache: &data->multi->conn_cache, &find, conn_is_conn); Loading
lib/multi.c +9 −53 Original line number Diff line number Diff line Loading @@ -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->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; /* -1 means it not set by user, use the default value */ Loading @@ -345,8 +337,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ Curl_hash_destroy(&multi->sockhash); Curl_hash_destroy(&multi->hostcache); 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->pending, NULL); Loading Loading @@ -407,7 +397,10 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, data->dns.hostcachetype = HCACHE_MULTI; } /* Point to the multi's connection cache */ /* Point to the shared or multi handle connection 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 Loading Loading @@ -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 closure handle always has the same timeouts as the most recently added easy handle. */ multi->closure_handle->set.timeout = data->set.timeout; multi->closure_handle->set.server_response_timeout = data->state.conn_cache->closure_handle->set.timeout = data->set.timeout; data->state.conn_cache->closure_handle->set.server_response_timeout = data->set.server_response_timeout; update_timer(multi); Loading Loading @@ -504,7 +497,7 @@ ConnectionDone(struct Curl_easy *data, struct connectdata *conn) data->state.conn_cache->num_connections > maxconnects) { 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) { /* Set the connection's owner correctly */ Loading Loading @@ -2201,36 +2194,12 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles) 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) { struct Curl_easy *data; struct Curl_easy *nextdata; if(GOOD_MULTI_HANDLE(multi)) { bool restore_pipe = FALSE; SIGPIPE_VARIABLE(pipe_st); multi->type = 0; /* not good anymore */ /* Firsrt remove all remaining easy handles */ Loading @@ -2255,18 +2224,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) } /* Close all the connections in the connection cache */ close_all_connections(multi); 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_conncache_close_all_connections(&multi->conn_cache); Curl_hash_destroy(&multi->sockhash); Curl_conncache_destroy(&multi->conn_cache); Loading @@ -2280,8 +2238,6 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl); free(multi); if(restore_pipe) sigpipe_restore(&pipe_st); return CURLM_OK; } Loading