Make cach'ing work with threads now, there are now three cases:
authorSterling Hughes <sterling@bumblebury.com>
Mon, 7 Jan 2002 20:52:32 +0000 (20:52 +0000)
committerSterling Hughes <sterling@bumblebury.com>
Mon, 7 Jan 2002 20:52:32 +0000 (20:52 +0000)
    - Use a global dns cache (via setting the tentatively named,
    CURLOPT_DNS_USE_GLOBAL_CACHE option to true)
    - Use a per-handle dns cache, by default
    - Use a pooled dns cache when in the "multi" interface

include/curl/curl.h
lib/easy.c
lib/hash.c
lib/hash.h
lib/hostip.c
lib/hostip.h
lib/multi.c
lib/url.c
lib/urldata.h

index 1157417..3d91c85 100644 (file)
@@ -488,6 +488,9 @@ typedef enum {
    */
   CINIT(SSLENGINE_DEFAULT, LONG, 90),
 
+  /* Non-zero value means to use the global dns cache */
+  CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91),
+
   CURLOPT_LASTENTRY /* the last unusued */
 } CURLoption;
 
index c24eb90..45de7e8 100644 (file)
@@ -141,8 +141,6 @@ CURLcode curl_global_init(long flags)
   if (initialized)
     return CURLE_OK;
 
-  Curl_host_cache_init();
-  
   if (flags & CURL_GLOBAL_SSL)
     Curl_SSL_init();
 
@@ -165,8 +163,8 @@ void curl_global_cleanup(void)
   if (!initialized)
     return;
 
-  Curl_host_cache_dtor();
-  
+  Curl_global_host_cache_dtor();
+
   if (init_flags & CURL_GLOBAL_SSL)
     Curl_SSL_cleanup();
 
@@ -235,12 +233,24 @@ CURLcode curl_easy_perform(CURL *curl)
 {
   struct SessionHandle *data = (struct SessionHandle *)curl;
 
+  if (!data->hostcache) {
+    if (Curl_global_host_cache_use(data)) {
+      data->hostcache = Curl_global_host_cache_get();
+    }
+    else {
+      data->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo);
+    }
+  }
+
   return Curl_perform(data);
 }
 
 void curl_easy_cleanup(CURL *curl)
 {
   struct SessionHandle *data = (struct SessionHandle *)curl;
+  if (!Curl_global_host_cache_use(data)) {
+    curl_hash_destroy(data->hostcache);
+  }
   Curl_close(data);
 }
 
index c0680e4..1ed3cc2 100644 (file)
@@ -255,11 +255,22 @@ curl_hash_clean(curl_hash *h)
   h->table = NULL;
 }
 
+size_t 
+curl_hash_count(curl_hash *h)
+{
+  return h->size;
+}
+
 void 
 curl_hash_destroy(curl_hash *h)
 {
+  if (!h) {
+    return;
+  }
+
   curl_hash_clean(h);
   free(h);
+  h = NULL;
 }
 
 /*
index 420bb89..66ef3df 100644 (file)
@@ -71,6 +71,7 @@ int curl_hash_extended_delete(curl_hash *h, char *str_key, unsigned int str_key_
 int curl_hash_extended_find(curl_hash *h, char *str_key, unsigned int str_key_len, 
                             unsigned long num_key, void **p);
 void curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *));
+size_t curl_hash_count(curl_hash *h);
 void curl_hash_clean(curl_hash *h);
 void curl_hash_destroy(curl_hash *h);
 
index db02b86..791ee03 100644 (file)
 #endif
 
 static curl_hash hostname_cache;
+static int host_cache_initialized;
 
-void Curl_host_cache_init(void)
+void Curl_global_host_cache_init(void)
 {
-  curl_hash_init(&hostname_cache, 7, Curl_freeaddrinfo);
+  if (!host_cache_initialized) {
+    curl_hash_init(&hostname_cache, 7, Curl_freeaddrinfo);
+    host_cache_initialized = 1;
+  }
 }
 
-void Curl_host_cache_dtor(void)
+curl_hash *Curl_global_host_cache_get(void)
 {
-  curl_hash_clean(&hostname_cache);
+  return &hostname_cache;
 }
 
+void Curl_global_host_cache_dtor(void)
+{
+  if (host_cache_initialized) {
+    curl_hash_clean(&hostname_cache);
+  }
+}
 
 Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
                            char *hostname,
@@ -90,14 +100,15 @@ Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
   Curl_addrinfo *addr = NULL;
   size_t hostname_len = strlen(hostname)+1;
 
-  if (curl_hash_find(&hostname_cache, hostname, hostname_len, (void **) &addr))
+  if (curl_hash_find(data->hostcache, hostname, hostname_len, (void **) &addr)) {
     return addr;
-
+  }
+  
   addr = Curl_getaddrinfo(data, hostname, port, bufp);
   if (!addr)
     return NULL;
 
-  curl_hash_add(&hostname_cache, hostname, hostname_len, (const void *) addr);
+  curl_hash_add(data->hostcache, hostname, hostname_len, (const void *) addr);
   return addr;
 }
 
@@ -405,3 +416,4 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
  * vim600: fdm=marker
  * vim: et sw=2 ts=2 sts=2 tw=78
  */
index 97b50ae..0cc98b6 100644 (file)
  * $Id$
  *****************************************************************************/
 
+#include "hash.h"
+
 struct addrinfo;
 struct hostent;
 struct SessionHandle;
 
-void Curl_host_cache_init(void);
-void Curl_host_cache_dtor(void);
+void Curl_global_host_cache_init(void);
+void Curl_global_host_cache_dtor(void);
+curl_hash *Curl_global_host_cache_get(void);
+
+#define Curl_global_host_cache_use(__p) ((__p)->set.global_dns_cache)
 
 Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
                           char *hostname,
index b7ab209..bfd3949 100644 (file)
@@ -82,7 +82,8 @@ struct Curl_multi {
   struct Curl_message *msgs;
   /* amount of messages in the queue */
   int num_msgs;
-
+  /* Hostname cache */
+  curl_hash *hostcache;
 };
 
 
@@ -244,7 +245,6 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
 
   easy=multi->easy.next;
   while(easy) {
-
     switch(easy->state) {
     case CURLM_STATE_INIT:
       /* init this transfer. */
@@ -256,6 +256,17 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
       }
       break;
     case CURLM_STATE_CONNECT:
+      if (Curl_global_host_cache_use(easy->easy_handle)) {
+        easy->easy_handle->hostcache = Curl_global_host_cache_get();
+      }
+      else {
+        if (multi->hostcache == NULL) {
+          multi->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo);
+        }
+
+        easy->easy_handle->hostcache = multi->hostcache;
+      }
+
       /* Connect. We get a connection identifier filled in. */
       easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn);
 
@@ -328,7 +339,7 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
   struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
   if(GOOD_MULTI_HANDLE(multi)) {
     multi->type = 0; /* not good anymore */
-
+    curl_hash_destroy(multi->hostcache);
     /* remove all easy handles */
 
     free(multi);
@@ -341,3 +352,10 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
 
 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue);
 
+/*
+ * local variables:
+ * eval: (load-file "../curl-mode.el")
+ * end:
+ * vim600: fdm=marker
+ * vim: et sw=2 ts=2 sts=2 tw=78
+ */
index 5f75680..56e7fa7 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -284,6 +284,15 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
   va_start(param, option);
 
   switch(option) {
+    case CURLOPT_DNS_USE_GLOBAL_CACHE: {
+      int use_cache = va_arg(param, int);
+      if (use_cache) {
+        Curl_global_host_cache_init();
+      }
+
+      data->set.global_dns_cache = use_cache;
+    }
+    break;
   case CURLOPT_SSL_CIPHER_LIST:
     /* set a list of cipher we want to use in the SSL connection */
     data->set.ssl.cipher_list = va_arg(param, char *);
index b7f3a2f..36358d6 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "setup.h"
 #include "hostip.h"
+#include "hash.h"
 
 #define PORT_FTP 21
 #define PORT_TELNET 23
@@ -644,6 +645,8 @@ struct UserDefined {
   bool reuse_fresh;      /* do not re-use an existing connection  */
   bool expect100header;  /* TRUE if we added Expect: 100-continue */
   bool ftp_use_epsv;     /* if EPSV is to be attempted or not */
+
+  bool global_dns_cache;
 };
 
 /*
@@ -658,6 +661,7 @@ struct UserDefined {
  * 'struct urlstate' instead.  */
 
 struct SessionHandle {
+  curl_hash          *hostcache;
   struct UserDefined set;      /* values set by the libcurl user */
   struct DynamicStatic change; /* possibly modified userdefined data */