diff options
author | deshevoy <deshevoy@yandex-team.ru> | 2022-02-10 16:46:56 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:56 +0300 |
commit | e988f30484abe5fdeedcc7a5d3c226c01a21800c (patch) | |
tree | 0a217b173aabb57b7e51f8a169989b1a3e0309fe /contrib/libs/curl/lib/conncache.c | |
parent | 33ee501c05d3f24036ae89766a858930ae66c548 (diff) | |
download | ydb-e988f30484abe5fdeedcc7a5d3c226c01a21800c.tar.gz |
Restoring authorship annotation for <deshevoy@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/curl/lib/conncache.c')
-rw-r--r-- | contrib/libs/curl/lib/conncache.c | 626 |
1 files changed, 313 insertions, 313 deletions
diff --git a/contrib/libs/curl/lib/conncache.c b/contrib/libs/curl/lib/conncache.c index cb3170c480f..625bd7e96e4 100644 --- a/contrib/libs/curl/lib/conncache.c +++ b/contrib/libs/curl/lib/conncache.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se> + * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se> * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which @@ -31,174 +31,174 @@ #include "multiif.h" #include "sendf.h" #include "conncache.h" -#include "share.h" -#include "sigpipe.h" -#include "connect.h" +#include "share.h" +#include "sigpipe.h" +#include "connect.h" -/* The last 3 #include files should be in this order */ -#include "curl_printf.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" #include "curl_memory.h" #include "memdebug.h" #define HASHKEY_SIZE 128 -static void conn_llist_dtor(void *user, void *element) -{ - struct connectdata *conn = element; - (void)user; - conn->bundle = NULL; -} - +static void conn_llist_dtor(void *user, void *element) +{ + struct connectdata *conn = element; + (void)user; + conn->bundle = NULL; +} + static CURLcode bundle_create(struct connectbundle **bundlep) -{ +{ DEBUGASSERT(*bundlep == NULL); *bundlep = malloc(sizeof(struct connectbundle)); if(!*bundlep) - return CURLE_OUT_OF_MEMORY; - + return CURLE_OUT_OF_MEMORY; + (*bundlep)->num_connections = 0; (*bundlep)->multiuse = BUNDLE_UNKNOWN; - + Curl_llist_init(&(*bundlep)->conn_list, (Curl_llist_dtor) conn_llist_dtor); - return CURLE_OK; -} - + return CURLE_OK; +} + static void bundle_destroy(struct connectbundle *bundle) -{ +{ if(!bundle) - return; - + return; + Curl_llist_destroy(&bundle->conn_list, NULL); - + free(bundle); -} - -/* Add a connection to a bundle */ +} + +/* Add a connection to a bundle */ static void bundle_add_conn(struct connectbundle *bundle, - struct connectdata *conn) -{ + struct connectdata *conn) +{ Curl_llist_insert_next(&bundle->conn_list, bundle->conn_list.tail, conn, - &conn->bundle_node); + &conn->bundle_node); conn->bundle = bundle; bundle->num_connections++; -} - -/* Remove a connection from a bundle */ +} + +/* Remove a connection from a bundle */ static int bundle_remove_conn(struct connectbundle *bundle, - struct connectdata *conn) -{ + struct connectdata *conn) +{ struct Curl_llist_element *curr; - + curr = bundle->conn_list.head; - while(curr) { - if(curr->ptr == conn) { + while(curr) { + if(curr->ptr == conn) { Curl_llist_remove(&bundle->conn_list, curr, NULL); bundle->num_connections--; - conn->bundle = NULL; - return 1; /* we removed a handle */ - } - curr = curr->next; - } + conn->bundle = NULL; + return 1; /* we removed a handle */ + } + curr = curr->next; + } DEBUGASSERT(0); - return 0; -} - + return 0; +} + static void free_bundle_hash_entry(void *freethis) { struct connectbundle *b = (struct connectbundle *) freethis; - bundle_destroy(b); + bundle_destroy(b); } -int Curl_conncache_init(struct conncache *connc, int size) +int Curl_conncache_init(struct conncache *connc, int size) { - int rc; + 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 */ + /* 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); + 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); - else - connc->closure_handle->state.conn_cache = connc; + else + connc->closure_handle->state.conn_cache = connc; - return rc; + return rc; } void Curl_conncache_destroy(struct conncache *connc) { - if(connc) - Curl_hash_destroy(&connc->hash); + if(connc) + Curl_hash_destroy(&connc->hash); } -/* creates a key to find a bundle for this connection */ -static void hashkey(struct connectdata *conn, char *buf, +/* creates a key to find a bundle for this connection */ +static void hashkey(struct connectdata *conn, char *buf, size_t len, /* something like 128 is fine */ const char **hostp) { - const char *hostname; + const char *hostname; long port = conn->remote_port; - + #ifndef CURL_DISABLE_PROXY if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { - hostname = conn->http_proxy.host.name; + hostname = conn->http_proxy.host.name; port = conn->port; } - else + else #endif if(conn->bits.conn_to_host) hostname = conn->conn_to_host.name; else - hostname = conn->host.name; - + hostname = conn->host.name; + if(hostp) /* report back which name we used */ *hostp = hostname; - - /* put the number first so that the hostname gets cut off if too long */ + + /* put the number first so that the hostname gets cut off if too long */ msnprintf(buf, len, "%ld%s", port, hostname); -} - -/* Returns number of connections currently held in the connection cache. - Locks/unlocks the cache itself! -*/ -size_t Curl_conncache_size(struct Curl_easy *data) -{ - size_t num; +} + +/* Returns number of connections currently held in the connection cache. + Locks/unlocks the cache itself! +*/ +size_t Curl_conncache_size(struct Curl_easy *data) +{ + size_t num; CONNCACHE_LOCK(data); - num = data->state.conn_cache->num_conn; + num = data->state.conn_cache->num_conn; CONNCACHE_UNLOCK(data); - return num; -} - -/* Look up the bundle with all the connections to the same host this - connectdata struct is setup to use. - - **NOTE**: When it returns, it holds the connection cache lock! */ -struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, + return num; +} + +/* Look up the bundle with all the connections to the same host this + connectdata struct is setup to use. + + **NOTE**: When it returns, it holds the connection cache lock! */ +struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, struct conncache *connc, const char **hostp) -{ +{ struct connectbundle *bundle = NULL; CONNCACHE_LOCK(conn->data); - if(connc) { + if(connc) { char key[HASHKEY_SIZE]; hashkey(conn, key, sizeof(key), hostp); - bundle = Curl_hash_pick(&connc->hash, key, strlen(key)); - } + bundle = Curl_hash_pick(&connc->hash, key, strlen(key)); + } return bundle; } static bool conncache_add_bundle(struct conncache *connc, - char *key, + char *key, struct connectbundle *bundle) { - void *p = Curl_hash_add(&connc->hash, key, strlen(key), bundle); + void *p = Curl_hash_add(&connc->hash, key, strlen(key), bundle); return p?TRUE:FALSE; } @@ -212,14 +212,14 @@ static void conncache_remove_bundle(struct conncache *connc, if(!connc) return; - Curl_hash_start_iterate(&connc->hash, &iter); + Curl_hash_start_iterate(&connc->hash, &iter); he = Curl_hash_next_element(&iter); while(he) { if(he->ptr == bundle) { /* The bundle is destroyed by the hash destructor function, free_bundle_hash_entry() */ - Curl_hash_delete(&connc->hash, he->key, he->key_len); + Curl_hash_delete(&connc->hash, he->key, he->key_len); return; } @@ -230,43 +230,43 @@ static void conncache_remove_bundle(struct conncache *connc, CURLcode Curl_conncache_add_conn(struct conncache *connc, struct connectdata *conn) { - CURLcode result = CURLE_OK; + CURLcode result = CURLE_OK; struct connectbundle *bundle = NULL; - struct Curl_easy *data = conn->data; + struct Curl_easy *data = conn->data; - /* *find_bundle() locks the connection cache */ + /* *find_bundle() locks the connection cache */ bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache, NULL); if(!bundle) { - int rc; + int rc; char key[HASHKEY_SIZE]; result = bundle_create(&bundle); - if(result) { - goto unlock; + if(result) { + goto unlock; } - + hashkey(conn, key, sizeof(key), NULL); rc = conncache_add_bundle(data->state.conn_cache, key, bundle); - - if(!rc) { + + if(!rc) { bundle_destroy(bundle); - result = CURLE_OUT_OF_MEMORY; - goto unlock; - } + result = CURLE_OUT_OF_MEMORY; + goto unlock; + } } - bundle_add_conn(bundle, conn); - conn->connection_id = connc->next_connection_id++; - connc->num_conn++; + bundle_add_conn(bundle, conn); + conn->connection_id = connc->next_connection_id++; + connc->num_conn++; - DEBUGF(infof(conn->data, "Added connection %ld. " - "The cache now contains %zu members\n", - conn->connection_id, connc->num_conn)); + DEBUGF(infof(conn->data, "Added connection %ld. " + "The cache now contains %zu members\n", + conn->connection_id, connc->num_conn)); - unlock: + unlock: CONNCACHE_UNLOCK(data); - - return result; + + return result; } /* @@ -280,43 +280,43 @@ void Curl_conncache_remove_conn(struct Curl_easy *data, struct connectdata *conn, bool lock) { struct connectbundle *bundle = conn->bundle; - struct conncache *connc = data->state.conn_cache; + struct conncache *connc = data->state.conn_cache; /* 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) { - if(lock) { + if(lock) { CONNCACHE_LOCK(data); - } - bundle_remove_conn(bundle, conn); - if(bundle->num_connections == 0) + } + bundle_remove_conn(bundle, conn); + if(bundle->num_connections == 0) conncache_remove_bundle(connc, bundle); - conn->bundle = NULL; /* removed from it */ - if(connc) { - connc->num_conn--; - DEBUGF(infof(data, "The cache now contains %zu members\n", - connc->num_conn)); + conn->bundle = NULL; /* removed from it */ + if(connc) { + connc->num_conn--; + DEBUGF(infof(data, "The cache now contains %zu members\n", + connc->num_conn)); } - if(lock) { + if(lock) { CONNCACHE_UNLOCK(data); - } + } } } -/* This function iterates the entire connection cache and calls the function - func() with the connection pointer as the first argument and the supplied - 'param' argument as the other. - - The conncache lock is still held when the callback is called. It needs it, - so that it can safely continue traversing the lists once the callback - returns. - - Returns 1 if the loop was aborted due to the callback's return code. +/* This function iterates the entire connection cache and calls the function + func() with the connection pointer as the first argument and the supplied + 'param' argument as the other. + The conncache lock is still held when the callback is called. It needs it, + so that it can safely continue traversing the lists once the callback + returns. + + Returns 1 if the loop was aborted due to the callback's return code. + Return 0 from func() to continue the loop, return 1 to abort it. */ -bool Curl_conncache_foreach(struct Curl_easy *data, - struct conncache *connc, +bool Curl_conncache_foreach(struct Curl_easy *data, + struct conncache *connc, void *param, int (*func)(struct connectdata *conn, void *param)) { @@ -325,41 +325,41 @@ bool Curl_conncache_foreach(struct Curl_easy *data, struct Curl_hash_element *he; if(!connc) - return FALSE; + return FALSE; CONNCACHE_LOCK(data); - Curl_hash_start_iterate(&connc->hash, &iter); + Curl_hash_start_iterate(&connc->hash, &iter); he = Curl_hash_next_element(&iter); while(he) { struct connectbundle *bundle; bundle = he->ptr; - he = Curl_hash_next_element(&iter); + he = Curl_hash_next_element(&iter); - curr = bundle->conn_list.head; + curr = bundle->conn_list.head; while(curr) { /* Yes, we need to update curr before calling func(), because func() might decide to remove the connection */ - struct connectdata *conn = curr->ptr; + struct connectdata *conn = curr->ptr; curr = curr->next; - if(1 == func(conn, param)) { + if(1 == func(conn, param)) { CONNCACHE_UNLOCK(data); - return TRUE; - } + return TRUE; + } } } CONNCACHE_UNLOCK(data); - return FALSE; + return FALSE; } /* Return the first connection found in the cache. Used when closing all - connections. - - NOTE: no locking is done here as this is presumably only done when cleaning - up a cache! -*/ + connections. + + NOTE: no locking is done here as this is presumably only done when cleaning + up a cache! +*/ static struct connectdata * conncache_find_first_connection(struct conncache *connc) { @@ -367,14 +367,14 @@ conncache_find_first_connection(struct conncache *connc) struct Curl_hash_element *he; struct connectbundle *bundle; - Curl_hash_start_iterate(&connc->hash, &iter); + Curl_hash_start_iterate(&connc->hash, &iter); he = Curl_hash_next_element(&iter); while(he) { struct Curl_llist_element *curr; bundle = he->ptr; - curr = bundle->conn_list.head; + curr = bundle->conn_list.head; if(curr) { return curr->ptr; } @@ -385,188 +385,188 @@ conncache_find_first_connection(struct conncache *connc) return NULL; } -/* - * Give ownership of a connection back to the connection cache. Might - * disconnect the oldest existing in there to make space. - * - * Return TRUE if stored, FALSE if closed. - */ +/* + * Give ownership of a connection back to the connection cache. Might + * disconnect the oldest existing in there to make space. + * + * Return TRUE if stored, FALSE if closed. + */ bool Curl_conncache_return_conn(struct Curl_easy *data, struct connectdata *conn) -{ - /* data->multi->maxconnects can be negative, deal with it. */ - size_t maxconnects = - (data->multi->maxconnects < 0) ? data->multi->num_easy * 4: - data->multi->maxconnects; - struct connectdata *conn_candidate = NULL; - +{ + /* data->multi->maxconnects can be negative, deal with it. */ + size_t maxconnects = + (data->multi->maxconnects < 0) ? data->multi->num_easy * 4: + data->multi->maxconnects; + struct connectdata *conn_candidate = NULL; + conn->lastused = Curl_now(); /* it was used up until now */ - if(maxconnects > 0 && - Curl_conncache_size(data) > maxconnects) { - infof(data, "Connection cache is full, closing the oldest one.\n"); - - conn_candidate = Curl_conncache_extract_oldest(data); - if(conn_candidate) { - /* the winner gets the honour of being disconnected */ - (void)Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE); - } - } - - return (conn_candidate == conn) ? FALSE : TRUE; - -} - -/* - * This function finds the connection in the connection bundle that has been - * unused for the longest time. - * - * Does not lock the connection cache! - * - * Returns the pointer to the oldest idle connection, or NULL if none was - * found. - */ -struct connectdata * -Curl_conncache_extract_bundle(struct Curl_easy *data, - struct connectbundle *bundle) -{ + if(maxconnects > 0 && + Curl_conncache_size(data) > maxconnects) { + infof(data, "Connection cache is full, closing the oldest one.\n"); + + conn_candidate = Curl_conncache_extract_oldest(data); + if(conn_candidate) { + /* the winner gets the honour of being disconnected */ + (void)Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE); + } + } + + return (conn_candidate == conn) ? FALSE : TRUE; + +} + +/* + * This function finds the connection in the connection bundle that has been + * unused for the longest time. + * + * Does not lock the connection cache! + * + * Returns the pointer to the oldest idle connection, or NULL if none was + * found. + */ +struct connectdata * +Curl_conncache_extract_bundle(struct Curl_easy *data, + struct connectbundle *bundle) +{ struct Curl_llist_element *curr; - timediff_t highscore = -1; - timediff_t score; - struct curltime now; - struct connectdata *conn_candidate = NULL; - struct connectdata *conn; - - (void)data; - - now = Curl_now(); - - curr = bundle->conn_list.head; - while(curr) { - conn = curr->ptr; - + timediff_t highscore = -1; + timediff_t score; + struct curltime now; + struct connectdata *conn_candidate = NULL; + struct connectdata *conn; + + (void)data; + + now = Curl_now(); + + curr = bundle->conn_list.head; + while(curr) { + conn = curr->ptr; + if(!CONN_INUSE(conn) && !conn->data) { - /* Set higher score for the age passed since the connection was used */ + /* Set higher score for the age passed since the connection was used */ score = Curl_timediff(now, conn->lastused); - - if(score > highscore) { - highscore = score; - conn_candidate = conn; - } - } - curr = curr->next; - } - if(conn_candidate) { - /* remove it to prevent another thread from nicking it */ - bundle_remove_conn(bundle, conn_candidate); - data->state.conn_cache->num_conn--; - DEBUGF(infof(data, "The cache now contains %zu members\n", - data->state.conn_cache->num_conn)); - conn_candidate->data = data; /* associate! */ - } - - return conn_candidate; -} - -/* - * This function finds the connection in the connection cache that has been - * unused for the longest time and extracts that from the bundle. - * - * Returns the pointer to the connection, or NULL if none was found. - */ -struct connectdata * -Curl_conncache_extract_oldest(struct Curl_easy *data) -{ - struct conncache *connc = data->state.conn_cache; + + if(score > highscore) { + highscore = score; + conn_candidate = conn; + } + } + curr = curr->next; + } + if(conn_candidate) { + /* remove it to prevent another thread from nicking it */ + bundle_remove_conn(bundle, conn_candidate); + data->state.conn_cache->num_conn--; + DEBUGF(infof(data, "The cache now contains %zu members\n", + data->state.conn_cache->num_conn)); + conn_candidate->data = data; /* associate! */ + } + + return conn_candidate; +} + +/* + * This function finds the connection in the connection cache that has been + * unused for the longest time and extracts that from the bundle. + * + * Returns the pointer to the connection, or NULL if none was found. + */ +struct connectdata * +Curl_conncache_extract_oldest(struct Curl_easy *data) +{ + struct conncache *connc = 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; - struct connectbundle *bundle_candidate = NULL; - - now = Curl_now(); - + timediff_t highscore =- 1; + timediff_t score; + struct curltime now; + struct connectdata *conn_candidate = NULL; + struct connectbundle *bundle; + struct connectbundle *bundle_candidate = NULL; + + now = Curl_now(); + CONNCACHE_LOCK(data); - Curl_hash_start_iterate(&connc->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; - + Curl_hash_start_iterate(&connc->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(conn) && !conn->data && !conn->bits.close && !conn->bits.connect_only) { - /* Set higher score for the age passed since the connection was used */ + /* Set higher score for the age passed since the connection was used */ score = Curl_timediff(now, conn->lastused); - - if(score > highscore) { - highscore = score; - conn_candidate = conn; - bundle_candidate = bundle; - } - } - curr = curr->next; - } - - he = Curl_hash_next_element(&iter); - } - if(conn_candidate) { - /* remove it to prevent another thread from nicking it */ - bundle_remove_conn(bundle_candidate, conn_candidate); - connc->num_conn--; - DEBUGF(infof(data, "The cache now contains %zu members\n", - connc->num_conn)); - conn_candidate->data = data; /* associate! */ - } + + if(score > highscore) { + highscore = score; + conn_candidate = conn; + bundle_candidate = bundle; + } + } + curr = curr->next; + } + + he = Curl_hash_next_element(&iter); + } + if(conn_candidate) { + /* remove it to prevent another thread from nicking it */ + bundle_remove_conn(bundle_candidate, conn_candidate); + connc->num_conn--; + DEBUGF(infof(data, "The cache now contains %zu members\n", + connc->num_conn)); + conn_candidate->data = data; /* associate! */ + } CONNCACHE_UNLOCK(data); - - return conn_candidate; -} - -void Curl_conncache_close_all_connections(struct conncache *connc) -{ - struct connectdata *conn; + + return conn_candidate; +} + +void Curl_conncache_close_all_connections(struct conncache *connc) +{ + struct connectdata *conn; char buffer[READBUFFER_MIN + 1]; if(!connc->closure_handle) return; connc->closure_handle->state.buffer = buffer; connc->closure_handle->set.buffer_size = READBUFFER_MIN; - + conn = conncache_find_first_connection(connc); - while(conn) { - SIGPIPE_VARIABLE(pipe_st); - conn->data = connc->closure_handle; - - sigpipe_ignore(conn->data, &pipe_st); - /* This will remove the connection from the cache */ - connclose(conn, "kill all"); + while(conn) { + SIGPIPE_VARIABLE(pipe_st); + conn->data = connc->closure_handle; + + sigpipe_ignore(conn->data, &pipe_st); + /* This will remove the connection from the cache */ + connclose(conn, "kill all"); Curl_conncache_remove_conn(conn->data, conn, TRUE); - (void)Curl_disconnect(connc->closure_handle, conn, FALSE); - sigpipe_restore(&pipe_st); - + (void)Curl_disconnect(connc->closure_handle, conn, FALSE); + sigpipe_restore(&pipe_st); + conn = conncache_find_first_connection(connc); - } - + } + connc->closure_handle->state.buffer = NULL; - 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); + 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); - } -} - + sigpipe_restore(&pipe_st); + } +} + #if 0 /* Useful for debugging the connection cache */ void Curl_conncache_print(struct conncache *connc) |