* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se>
+ * Copyright (C) 2012 - 2014, 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
*
***************************************************************************/
-#include "setup.h"
+#include "curl_setup.h"
#include <curl/curl.h>
/* The last #include file should be: */
#include "memdebug.h"
-#define CONNECTION_HASH_SIZE 97
-
static void free_bundle_hash_entry(void *freethis)
{
struct connectbundle *b = (struct connectbundle *) freethis;
Curl_bundle_destroy(b);
}
-struct conncache *Curl_conncache_init(int type)
+struct conncache *Curl_conncache_init(int size)
{
struct conncache *connc;
if(!connc)
return NULL;
- connc->hash = Curl_hash_alloc(CONNECTION_HASH_SIZE, Curl_hash_str,
+ connc->hash = Curl_hash_alloc(size, Curl_hash_str,
Curl_str_key_compare, free_bundle_hash_entry);
if(!connc->hash) {
return NULL;
}
- connc->type = type;
- connc->num_connections = 0;
-
return connc;
}
void Curl_conncache_destroy(struct conncache *connc)
{
- Curl_hash_destroy(connc->hash);
- free(connc);
+ if(connc) {
+ Curl_hash_destroy(connc->hash);
+ connc->hash = NULL;
+ free(connc);
+ }
}
struct connectbundle *Curl_conncache_find_bundle(struct conncache *connc,
{
CURLcode result;
struct connectbundle *bundle;
+ struct connectbundle *new_bundle = NULL;
struct SessionHandle *data = conn->data;
bundle = Curl_conncache_find_bundle(data->state.conn_cache,
conn->host.name);
if(!bundle) {
- result = Curl_bundle_create(data, &bundle);
- if(result != CURLE_OK)
+ result = Curl_bundle_create(data, &new_bundle);
+ if(result)
return result;
if(!conncache_add_bundle(data->state.conn_cache,
- conn->host.name, bundle))
+ conn->host.name, new_bundle)) {
+ Curl_bundle_destroy(new_bundle);
return CURLE_OUT_OF_MEMORY;
+ }
+ bundle = new_bundle;
}
result = Curl_bundle_add_conn(bundle, conn);
- if(result != CURLE_OK)
+ if(result) {
+ if(new_bundle)
+ conncache_remove_bundle(data->state.conn_cache, new_bundle);
return result;
+ }
+ 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;
}
if(bundle->num_connections == 0) {
conncache_remove_bundle(connc, bundle);
}
- connc->num_connections--;
- DEBUGF(infof(conn->data, "The cache now contains %d members\n",
- connc->num_connections));
+ 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));
+ }
}
}
/* 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 */
+ and the supplied 'param' argument as the other,
+
+ Return 0 from func() to continue the loop, return 1 to abort it.
+ */
void Curl_conncache_foreach(struct conncache *connc,
void *param,
- void (*func)(void *conn, void *param))
+ int (*func)(struct connectdata *conn, void *param))
{
struct curl_hash_iterator iter;
struct curl_llist_element *curr;
he = Curl_hash_next_element(&iter);
while(he) {
struct connectbundle *bundle;
- struct connectdata *conn;
bundle = he->ptr;
+ he = Curl_hash_next_element(&iter);
curr = bundle->conn_list->head;
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;
- func(conn, param);
+ if(1 == func(conn, param))
+ return;
}
-
- he = Curl_hash_next_element(&iter);
}
}
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;
he = Curl_hash_next_element(&iter);
while(he) {
+ struct curl_llist_element *curr;
bundle = he->ptr;
curr = bundle->conn_list->head;