[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r6954: start restructuring dns to use priority queues for expiring (in tor/trunk: . doc src/or)



Author: nickm
Date: 2006-07-31 14:00:18 -0400 (Mon, 31 Jul 2006)
New Revision: 6954

Modified:
   tor/trunk/
   tor/trunk/doc/TODO
   tor/trunk/src/or/dns.c
Log:
 r6959@Kushana:  nickm | 2006-07-29 22:33:18 -0400
 start restructuring dns to use priority queues for expiring entries.



Property changes on: tor/trunk
___________________________________________________________________
Name: svk:merge
   - c95137ef-5f19-0410-b913-86e773d04f59:/tor/branches/eventdns:6958
c95137ef-5f19-0410-b913-86e773d04f59:/tor/branches/oo-connections:6950
   + c95137ef-5f19-0410-b913-86e773d04f59:/tor/branches/eventdns:6959
c95137ef-5f19-0410-b913-86e773d04f59:/tor/branches/oo-connections:6950

Modified: tor/trunk/doc/TODO
===================================================================
--- tor/trunk/doc/TODO	2006-07-31 17:59:37 UTC (rev 6953)
+++ tor/trunk/doc/TODO	2006-07-31 18:00:18 UTC (rev 6954)
@@ -73,9 +73,11 @@
 
     - "bandwidth classes", for incoming vs initiated-here conns.
     o Asynchronous DNS
-      . and test it
-      - Make it work on windows.
-      - make it the default on platforms where it works
+      . And test it
+      . Make it work on windows.
+        o Implement
+        - Test
+      - Make it the default on platforms where it works
 
   - Security improvements
     - Directory guards

Modified: tor/trunk/src/or/dns.c
===================================================================
--- tor/trunk/src/or/dns.c	2006-07-31 17:59:37 UTC (rev 6953)
+++ tor/trunk/src/or/dns.c	2006-07-31 18:00:18 UTC (rev 6954)
@@ -73,14 +73,12 @@
 #define CACHE_STATE_PENDING 0
 #define CACHE_STATE_VALID 1
 #define CACHE_STATE_FAILED 2
-  uint32_t expire; /**< Remove items from cache after this time. */
+  time_t expire; /**< Remove items from cache after this time. */
   uint32_t ttl; /**< What TTL did the nameserver tell us? */
   pending_connection_t *pending_connections;
-  struct cached_resolve_t *next;
 } cached_resolve_t;
 
 static void purge_expired_resolves(uint32_t now);
-static void dns_purge_resolve(cached_resolve_t *resolve);
 static void dns_found_answer(const char *address, uint32_t addr, char outcome,
                              uint32_t ttl);
 static void send_resolved_cell(edge_connection_t *conn, uint8_t answer_type);
@@ -202,6 +200,32 @@
   tor_free(r);
 }
 
+/** DODDOC */
+static int
+_compare_cached_resolves_by_expiry(void *_a, void *_b)
+{
+  cached_resolve_t *a = _a, *b = _b;
+  if (a->expire < b->expire)
+    return -1;
+  else if (a->expire == b->expire)
+    return 0;
+  else
+    return 1;
+}
+
+/** Linked list of resolved addresses, oldest to newest. DOCDOC*/
+static smartlist_t *cached_resolve_pqueue = NULL;
+
+static void
+set_expiry(cached_resolve_t *resolve, time_t expires)
+{
+  tor_assert(resolve && resolve->expire == 0);
+  resolve->expire = expires;
+  smartlist_pqueue_add(cached_resolve_pqueue,
+                       _compare_cached_resolves_by_expiry,
+                       resolve);
+}
+
 /** Free all storage held in the DNS cache */
 void
 dns_free_all(void)
@@ -213,12 +237,12 @@
     _free_cached_resolve(item);
   }
   HT_CLEAR(cache_map, &cache_root);
+  smartlist_free(cached_resolve_pqueue);
+  cached_resolve_pqueue = NULL;
 }
 
-/** Linked list of resolved addresses, oldest to newest. */
-static cached_resolve_t *oldest_cached_resolve = NULL;
-static cached_resolve_t *newest_cached_resolve = NULL;
 
+
 /** Remove every cached_resolve whose <b>expire</b> time is before <b>now</b>
  * from the cache. */
 static void
@@ -229,11 +253,16 @@
   edge_connection_t *pendconn;
 
   assert_cache_ok();
-  /* this is fast because the linked list
-   * oldest_cached_resolve is ordered by when they came in.
-   */
-  while (oldest_cached_resolve && (oldest_cached_resolve->expire < now)) {
-    resolve = oldest_cached_resolve;
+  if (!cached_resolve_pqueue)
+    return;
+
+  while (smartlist_len(cached_resolve_pqueue)) {
+    resolve = smartlist_get(cached_resolve_pqueue, 0);
+    if (resolve->expire > now)
+      break;
+    smartlist_pqueue_pop(cached_resolve_pqueue,
+                         _compare_cached_resolves_by_expiry);
+
     log_debug(LD_EXIT,
               "Forgetting old cached resolve (address %s, expires %lu)",
               escaped_safe_str(resolve->address),
@@ -244,6 +273,7 @@
                 " Forgot to cull it?", escaped_safe_str(resolve->address));
       tor_fragile_assert();
     }
+
     if (resolve->pending_connections) {
       log_debug(LD_EXIT,
                 "Closing pending connections on expiring DNS resolve!");
@@ -261,18 +291,19 @@
         tor_free(pend);
       }
     }
-    oldest_cached_resolve = resolve->next;
-    if (!oldest_cached_resolve) /* if there are no more, */
-      newest_cached_resolve = NULL; /* then make sure the list's tail knows
-                                     * that too */
+
     removed = HT_REMOVE(cache_map, &cache_root, resolve);
     if (removed != resolve) {
-      log_notice(LD_EXIT, "Removed is %p, resolve is %p.", removed, resolve);
-      tor_assert(removed == resolve);
+      log_err(LD_BUG, "The expired resolve we purged didn't match any in"
+              " the cache. Tried to purge %s; instead got %s.",
+              resolve->address, removed ? removed->address : "NULL");
+
     }
+    tor_assert(removed == resolve);
     resolve->magic = 0xF0BBF0BB;
     tor_free(resolve);
   }
+
   assert_cache_ok();
 }
 
@@ -316,22 +347,6 @@
                                conn->cpath_layer);
 }
 
-/** Link <b>r</b> into the hash table of address-to-result mappings, and add it
- * to the linked list of resolves-by-age. */
-static void
-insert_resolve(cached_resolve_t *r)
-{
-  /* add us to the linked list of resolves */
-  if (!oldest_cached_resolve) {
-    oldest_cached_resolve = r;
-  } else {
-    newest_cached_resolve->next = r;
-  }
-  newest_cached_resolve = r;
-
-  HT_INSERT(cache_map, &cache_root, r);
-}
-
 /** See if we have a cache entry for <b>exitconn</b>-\>address. if so,
  * if resolve valid, put it into <b>exitconn</b>-\>addr and return 1.
  * If resolve failed, unlink exitconn if needed, free it, and return -1.
@@ -418,7 +433,6 @@
   resolve = tor_malloc_zero(sizeof(cached_resolve_t));
   resolve->magic = CACHED_RESOLVE_MAGIC;
   resolve->state = CACHE_STATE_PENDING;
-  resolve->expire = now + DEFAULT_DNS_TTL; /* this will get replaced. */
   strlcpy(resolve->address, exitconn->_base.address, sizeof(resolve->address));
 
   /* add us to the pending list */
@@ -427,7 +441,10 @@
   resolve->pending_connections = pending_connection;
   exitconn->_base.state = EXIT_CONN_STATE_RESOLVING;
 
-  insert_resolve(resolve);
+  /* Add this resolve to the cache. It has no expiry yet, so it doesn't
+   * go into the priority queue. */
+  HT_INSERT(cache_map, &cache_root, resolve);
+
   log_debug(LD_EXIT,"Assigning question %s to dnsworker.",
             escaped_safe_str(exitconn->_base.address));
   assert_cache_ok();
@@ -528,7 +545,7 @@
 {
   pending_connection_t *pend;
   cached_resolve_t search;
-  cached_resolve_t *resolve;
+  cached_resolve_t *resolve, *tmp;
   edge_connection_t *pendconn;
   circuit_t *circ;
 
@@ -550,6 +567,7 @@
     return;
   }
   tor_assert(resolve->pending_connections);
+  tor_assert(! resolve->expire);
 
   /* mark all pending connections to fail */
   log_debug(LD_EXIT,
@@ -573,37 +591,9 @@
     tor_free(pend);
   }
 
-  dns_purge_resolve(resolve);
-}
-
-/** Remove <b>resolve</b> from the cache.
- */
-static void
-dns_purge_resolve(cached_resolve_t *resolve)
-{
-  cached_resolve_t *tmp;
-
-  /* remove resolve from the linked list */
-  if (resolve == oldest_cached_resolve) {
-    oldest_cached_resolve = resolve->next;
-    if (oldest_cached_resolve == NULL)
-      newest_cached_resolve = NULL;
-  } else {
-    /* FFFF make it a doubly linked list if this becomes too slow */
-    for (tmp=oldest_cached_resolve; tmp && tmp->next != resolve; tmp=tmp->next)
-      ;
-    tor_assert(tmp); /* it's got to be in the list, or we screwed up somewhere
-                      * else */
-    tmp->next = resolve->next; /* unlink it */
-
-    if (newest_cached_resolve == resolve)
-      newest_cached_resolve = tmp;
-  }
-
-  /* remove resolve from the map */
   tmp = HT_REMOVE(cache_map, &cache_root, resolve);
   tor_assert(tmp == resolve);
-  resolve->magic = 0xAAAAAAAA;
+  resolve->magic = 0xABABABAB;
   tor_free(resolve);
 }
 
@@ -638,10 +628,10 @@
       CACHE_STATE_VALID : CACHE_STATE_FAILED;
     strlcpy(resolve->address, address, sizeof(resolve->address));
     resolve->addr = addr;
-    resolve->expire = time(NULL) + dns_get_expiry_ttl(ttl);
     resolve->ttl = ttl;
     assert_resolve_ok(resolve);
-    insert_resolve(resolve);
+    HT_INSERT(cache_map, &cache_root, resolve);
+    set_expiry(resolve, time(NULL) + dns_get_expiry_ttl(ttl));
     return;
   }
   assert_resolve_ok(resolve);
@@ -661,7 +651,6 @@
   /* tor_assert(resolve->state == CACHE_STATE_PENDING); */
 
   resolve->addr = addr;
-  resolve->expire = time(NULL) + dns_get_expiry_ttl(ttl);
   resolve->ttl = ttl;
   if (outcome == DNS_RESOLVE_SUCCEEDED)
     resolve->state = CACHE_STATE_VALID;
@@ -724,7 +713,12 @@
   assert_cache_ok();
 
   if (outcome == DNS_RESOLVE_FAILED_TRANSIENT) { /* remove from cache */
-    dns_purge_resolve(resolve);
+    cached_resolve_t *tmp = HT_REMOVE(cache_map, &cache_root, resolve);
+    tor_assert(tmp == resolve);
+    resolve->magic = 0xAAAAAAAA;
+    tor_free(resolve);
+  } else {
+    set_expiry(resolve, time(NULL) + dns_get_expiry_ttl(ttl));
   }
 
   assert_cache_ok();
@@ -1216,7 +1210,6 @@
   tor_assert(resolve);
   tor_assert(resolve->magic == CACHED_RESOLVE_MAGIC);
   tor_assert(strlen(resolve->address) < MAX_ADDRESSLEN);
-  tor_assert(! resolve->next || resolve->next->magic == CACHED_RESOLVE_MAGIC);
 }
 
 static void