summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/conncache.c
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2015-08-12 19:43:52 (GMT)
committerBrad King <brad.king@kitware.com>2015-08-12 19:43:52 (GMT)
commit91e8d35ab8ec2d62478a42eff10af88713497fad (patch)
treeff8cd1bd1ce3c42ef56c76b5ab471831a80c4665 /Utilities/cmcurl/lib/conncache.c
parent602cdc06a01b7c5c0eb444111382b09040f677ee (diff)
parent706542615828488a5ad197d0ef3dd5e42eb739c4 (diff)
downloadCMake-91e8d35ab8ec2d62478a42eff10af88713497fad.zip
CMake-91e8d35ab8ec2d62478a42eff10af88713497fad.tar.gz
CMake-91e8d35ab8ec2d62478a42eff10af88713497fad.tar.bz2
Merge branch 'curl-upstream' into update-curl
Resolve conflicts by taking upstream side when possible and otherwise integrating the changes from both sides. Be carful in CMakeLists.txt where the OPENSSL code block that we modified previously has moved, and preserve our previous modifications in the new location.
Diffstat (limited to 'Utilities/cmcurl/lib/conncache.c')
-rw-r--r--Utilities/cmcurl/lib/conncache.c179
1 files changed, 130 insertions, 49 deletions
diff --git a/Utilities/cmcurl/lib/conncache.c b/Utilities/cmcurl/lib/conncache.c
index 5bbcf3c..c712ed7 100644
--- a/Utilities/cmcurl/lib/conncache.c
+++ b/Utilities/cmcurl/lib/conncache.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se>
- * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2015, 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
@@ -31,66 +31,134 @@
#include "multiif.h"
#include "sendf.h"
#include "rawstr.h"
-#include "bundles.h"
#include "conncache.h"
+#include "curl_printf.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
-static void free_bundle_hash_entry(void *freethis)
+static void conn_llist_dtor(void *user, void *element)
{
- struct connectbundle *b = (struct connectbundle *) freethis;
+ struct connectdata *data = element;
+ (void)user;
- Curl_bundle_destroy(b);
+ data->bundle = NULL;
}
-struct conncache *Curl_conncache_init(int size)
+static CURLcode bundle_create(struct SessionHandle *data,
+ struct connectbundle **cb_ptr)
{
- struct conncache *connc;
-
- connc = calloc(1, sizeof(struct conncache));
- if(!connc)
- return NULL;
+ (void)data;
+ DEBUGASSERT(*cb_ptr == NULL);
+ *cb_ptr = malloc(sizeof(struct connectbundle));
+ if(!*cb_ptr)
+ return CURLE_OUT_OF_MEMORY;
+
+ (*cb_ptr)->num_connections = 0;
+ (*cb_ptr)->multiuse = BUNDLE_UNKNOWN;
+
+ (*cb_ptr)->conn_list = Curl_llist_alloc((curl_llist_dtor) conn_llist_dtor);
+ if(!(*cb_ptr)->conn_list) {
+ Curl_safefree(*cb_ptr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ return CURLE_OK;
+}
- connc->hash = Curl_hash_alloc(size, Curl_hash_str,
- Curl_str_key_compare, free_bundle_hash_entry);
+static void bundle_destroy(struct connectbundle *cb_ptr)
+{
+ if(!cb_ptr)
+ return;
- if(!connc->hash) {
- free(connc);
- return NULL;
+ if(cb_ptr->conn_list) {
+ Curl_llist_destroy(cb_ptr->conn_list, NULL);
+ cb_ptr->conn_list = NULL;
}
+ free(cb_ptr);
+}
+
+/* Add a connection to a bundle */
+static CURLcode bundle_add_conn(struct connectbundle *cb_ptr,
+ struct connectdata *conn)
+{
+ if(!Curl_llist_insert_next(cb_ptr->conn_list, cb_ptr->conn_list->tail, conn))
+ return CURLE_OUT_OF_MEMORY;
+
+ conn->bundle = cb_ptr;
- return connc;
+ cb_ptr->num_connections++;
+ return CURLE_OK;
}
-void Curl_conncache_destroy(struct conncache *connc)
+/* Remove a connection from a bundle */
+static int bundle_remove_conn(struct connectbundle *cb_ptr,
+ struct connectdata *conn)
{
- if(connc) {
- Curl_hash_destroy(connc->hash);
- connc->hash = NULL;
- free(connc);
+ struct curl_llist_element *curr;
+
+ curr = cb_ptr->conn_list->head;
+ while(curr) {
+ if(curr->ptr == conn) {
+ Curl_llist_remove(cb_ptr->conn_list, curr, NULL);
+ cb_ptr->num_connections--;
+ conn->bundle = NULL;
+ return 1; /* we removed a handle */
+ }
+ curr = curr->next;
}
+ return 0;
}
-struct connectbundle *Curl_conncache_find_bundle(struct conncache *connc,
- char *hostname)
+static void free_bundle_hash_entry(void *freethis)
{
- struct connectbundle *bundle = NULL;
+ struct connectbundle *b = (struct connectbundle *) freethis;
+
+ bundle_destroy(b);
+}
+int Curl_conncache_init(struct conncache *connc, int size)
+{
+ return Curl_hash_init(&connc->hash, size, Curl_hash_str,
+ Curl_str_key_compare, free_bundle_hash_entry);
+}
+
+void Curl_conncache_destroy(struct conncache *connc)
+{
if(connc)
- bundle = Curl_hash_pick(connc->hash, hostname, strlen(hostname)+1);
+ Curl_hash_destroy(&connc->hash);
+}
+
+/* returns an allocated key to find a bundle for this connection */
+static char *hashkey(struct connectdata *conn)
+{
+ return aprintf("%s:%d",
+ conn->bits.proxy?conn->proxy.name:conn->host.name,
+ conn->localport);
+}
+
+/* Look up the bundle with all the connections to the same host this
+ connectdata struct is setup to use. */
+struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
+ struct conncache *connc)
+{
+ struct connectbundle *bundle = NULL;
+ if(connc) {
+ char *key = hashkey(conn);
+ if(key) {
+ bundle = Curl_hash_pick(&connc->hash, key, strlen(key));
+ free(key);
+ }
+ }
return bundle;
}
static bool conncache_add_bundle(struct conncache *connc,
- char *hostname,
+ char *key,
struct connectbundle *bundle)
{
- void *p;
-
- p = Curl_hash_add(connc->hash, hostname, strlen(hostname)+1, bundle);
+ void *p = Curl_hash_add(&connc->hash, key, strlen(key), bundle);
return p?TRUE:FALSE;
}
@@ -104,14 +172,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;
}
@@ -127,23 +195,32 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
struct connectbundle *new_bundle = NULL;
struct SessionHandle *data = conn->data;
- bundle = Curl_conncache_find_bundle(data->state.conn_cache,
- conn->host.name);
+ bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache);
if(!bundle) {
- result = Curl_bundle_create(data, &new_bundle);
- if(result != CURLE_OK)
+ char *key;
+ int rc;
+
+ result = bundle_create(data, &new_bundle);
+ if(result)
return result;
- if(!conncache_add_bundle(data->state.conn_cache,
- conn->host.name, new_bundle)) {
- Curl_bundle_destroy(new_bundle);
+ key = hashkey(conn);
+ if(!key) {
+ bundle_destroy(new_bundle);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle);
+ free(key);
+ if(!rc) {
+ bundle_destroy(new_bundle);
return CURLE_OUT_OF_MEMORY;
}
bundle = new_bundle;
}
- result = Curl_bundle_add_conn(bundle, conn);
- if(result != CURLE_OK) {
+ result = bundle_add_conn(bundle, conn);
+ if(result) {
if(new_bundle)
conncache_remove_bundle(data->state.conn_cache, new_bundle);
return result;
@@ -152,6 +229,10 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
conn->connection_id = connc->next_connection_id++;
connc->num_connections++;
+ DEBUGF(infof(conn->data, "Added connection %ld. "
+ "The cache now contains %" CURL_FORMAT_CURL_OFF_TU " members\n",
+ conn->connection_id, (curl_off_t) connc->num_connections));
+
return CURLE_OK;
}
@@ -163,7 +244,7 @@ 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) {
- Curl_bundle_remove_conn(bundle, conn);
+ bundle_remove_conn(bundle, conn);
if(bundle->num_connections == 0) {
conncache_remove_bundle(connc, bundle);
}
@@ -171,8 +252,9 @@ void Curl_conncache_remove_conn(struct conncache *connc,
if(connc) {
connc->num_connections--;
- DEBUGF(infof(conn->data, "The cache now contains %d members\n",
- connc->num_connections));
+ DEBUGF(infof(conn->data, "The cache now contains %"
+ CURL_FORMAT_CURL_OFF_TU " members\n",
+ (curl_off_t) connc->num_connections));
}
}
}
@@ -194,12 +276,11 @@ void Curl_conncache_foreach(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) {
struct connectbundle *bundle;
- struct connectdata *conn;
bundle = he->ptr;
he = Curl_hash_next_element(&iter);
@@ -208,7 +289,7 @@ void Curl_conncache_foreach(struct conncache *connc,
while(curr) {
/* Yes, we need to update curr before calling func(), because func()
might decide to remove the connection */
- conn = curr->ptr;
+ struct connectdata *conn = curr->ptr;
curr = curr->next;
if(1 == func(conn, param))
@@ -223,14 +304,14 @@ struct connectdata *
Curl_conncache_find_first_connection(struct conncache *connc)
{
struct curl_hash_iterator iter;
- struct curl_llist_element *curr;
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;