void Curl_conncache_remove_conn(struct connectdata *conn, bool lock) { struct Curl_easy *data = conn->data; struct connectbundle *bundle = conn->bundle; 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) { CONN_LOCK(data); } 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)); } if(lock) { CONN_UNLOCK(data); } } }
/* * 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(); CONN_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; if(!CONN_INUSE(conn)) { /* 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; 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! */ } CONN_UNLOCK(data); return conn_candidate; }
/* * 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; if(!CONN_INUSE(conn)) { /* 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; } 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; }
void Curl_conncache_remove_conn(struct conncache *connc, struct connectdata *conn) { struct connectbundle *bundle = conn->bundle; /* 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) { bundle_remove_conn(bundle, conn); if(bundle->num_connections == 0) { conncache_remove_bundle(connc, bundle); } if(connc) { connc->num_connections--; DEBUGF(infof(conn->data, "The cache now contains %" CURL_FORMAT_CURL_OFF_TU " members\n", (curl_off_t) connc->num_connections)); } } }