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

[or-cvs] Split dns_cancel_pending_resolve into dns_cancel_pending_re...



Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/tmp/cvs-serv32174/src/or

Modified Files:
	connection.c dns.c or.h 
Log Message:
Split dns_cancel_pending_resolve into dns_cancel_pending_resolve (kill a
resolve in response to a DNS worker dying) and connection_dns_remove (remove
a pending connection from the resolve structure.)


Index: connection.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection.c,v
retrieving revision 1.164
retrieving revision 1.165
diff -u -d -r1.164 -r1.165
--- connection.c	28 Feb 2004 19:14:11 -0000	1.164
+++ connection.c	28 Feb 2004 22:23:44 -0000	1.165
@@ -182,14 +182,14 @@
     case CONN_TYPE_EXIT:
     case CONN_TYPE_AP:
       if (conn->state == EXIT_CONN_STATE_RESOLVING)
-        dns_cancel_pending_resolve(conn->address, conn);
+        connection_dns_remove(conn);
       if (!conn->has_sent_end && reason &&
           connection_edge_end(conn, reason, conn->cpath_layer) < 0)
         return -1;
       break;
     case CONN_TYPE_DNSWORKER:
       if (conn->state == DNSWORKER_STATE_BUSY) {
-        dns_cancel_pending_resolve(conn->address, NULL);
+        dns_cancel_pending_resolve(conn->address);
       }
       break;
     default:

Index: dns.c
===================================================================
RCS file: /home/or/cvsroot/src/or/dns.c,v
retrieving revision 1.58
retrieving revision 1.59
diff -u -d -r1.58 -r1.59
--- dns.c	28 Feb 2004 22:13:58 -0000	1.58
+++ dns.c	28 Feb 2004 22:23:44 -0000	1.59
@@ -171,7 +171,7 @@
 
   if(!dnsconn) {
     log_fn(LOG_WARN,"no idle dns workers. Failing.");
-    dns_cancel_pending_resolve(exitconn->address, NULL);
+    dns_cancel_pending_resolve(exitconn->address);
     return -1;
   }
 
@@ -192,12 +192,53 @@
 }
 
 
+void connection_dns_remove(connection_t *conn)
+{
+  struct pending_connection_t *pend, *victim;
+  struct cached_resolve search;
+  struct cached_resolve *resolve;
+
+  strncpy(search.address, conn->address, MAX_ADDRESSLEN);
+  search.address[MAX_ADDRESSLEN-1] = 0;
+
+  resolve = SPLAY_FIND(cache_tree, &cache_root, &search);
+  if(!resolve) {
+    log_fn(LOG_WARN,"Address '%s' is not pending. Dropping.", conn->address);
+    return;
+  }
+
+  assert(resolve->pending_connections);
+  assert_connection_ok(conn,0);
+
+  pend = resolve->pending_connections;
+
+  if(pend->conn == conn) {
+    resolve->pending_connections = pend->next;
+    free(pend);
+    log_fn(LOG_DEBUG, "Connection (fd %d) no longer waiting for resolve of '%s'",
+           conn->s, conn->address);
+    return;
+  } else {
+    for( ; pend->next; pend = pend->next) {
+      if(pend->next->conn == conn) {
+        victim = pend->next;
+        pend->next = victim->next;
+        free(victim);
+        log_fn(LOG_DEBUG, "Connection (fd %d) no longer waiting for resolve of '%s'",
+               conn->s, conn->address);
+        return; /* more are pending */
+      }
+    }
+    assert(0); /* not reachable unless onlyconn not in pending list */
+  }
+}
+
 /* If onlyconn is NULL, cancel all pending connections. If onlyconn is
  * defined, then remove onlyconn from the pending list.  Does not cancel the
  * resolve itself, or remove the 'struct cached_resolve' from the cache.
  */
-void dns_cancel_pending_resolve(char *address, connection_t *onlyconn) {
-  struct pending_connection_t *pend, *victim;
+void dns_cancel_pending_resolve(char *address) {
+  struct pending_connection_t *pend;
   struct cached_resolve search;
   struct cached_resolve *resolve, *tmp;
 
@@ -212,40 +253,38 @@
 
   assert(resolve->pending_connections);
 
-  if(onlyconn) {
-    assert_connection_ok(onlyconn,0);
+  /* mark all pending connections to fail */
+  log_fn(LOG_DEBUG, "Failing all connections waiting on DNS resolve of '%s'",
+         address);
+  while(resolve->pending_connections) {
     pend = resolve->pending_connections;
-    if(pend->conn == onlyconn) {
-      resolve->pending_connections = pend->next;
-      free(pend);
-      if(resolve->pending_connections) {/* more pending, don't cancel it */
-        log_fn(LOG_DEBUG, "Connection (fd %d) no longer waiting for resolve of '%s'",
-               onlyconn->s, address);
-      }
-    } else {
-      for( ; pend->next; pend = pend->next) {
-        if(pend->next->conn == onlyconn) {
-          victim = pend->next;
-          pend->next = victim->next;
-          free(victim);
-          log_fn(LOG_DEBUG, "Connection (fd %d) no longer waiting for resolve of '%s'",
-                 onlyconn->s, address);
-          return; /* more are pending */
-        }
-      }
-      assert(0); /* not reachable unless onlyconn not in pending list */
-    }
+    /* This calls dns_cancel_pending_resolve, which removes pend
+     * from the list, so we don't have to do it.  Beware of
+     * modify-while-iterating bugs hereabouts! */
+    connection_mark_for_close(pend->conn, END_STREAM_REASON_MISC);
+    assert(resolve->pending_connections != pend);
+  }
+
+  /* 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 {
-    /* mark all pending connections to fail */
-    log_fn(LOG_DEBUG, "Failing all connections waiting on DNS resolve of '%s'",
-           address);
-    while(resolve->pending_connections) {
-      pend = resolve->pending_connections;
-      connection_mark_for_close(pend->conn, END_STREAM_REASON_MISC);
-      resolve->pending_connections = pend->next;
-      free(pend);
-    }
+    /* FFFF make it a doubly linked list if this becomes too slow */
+    for(tmp=oldest_cached_resolve; tmp && tmp->next != resolve; tmp=tmp->next) ;
+    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 tree */
+  SPLAY_REMOVE(cache_tree, &cache_root, resolve);
+
+  free(resolve);
+
 }
 
 static void dns_found_answer(char *address, uint32_t addr) {
@@ -315,7 +354,7 @@
   if(conn->inbuf_reached_eof) {
     log_fn(LOG_WARN,"Read eof. Worker dying.");
     if(conn->state == DNSWORKER_STATE_BUSY) {
-      dns_cancel_pending_resolve(conn->address, NULL);
+      dns_cancel_pending_resolve(conn->address);
       num_dnsworkers_busy--;
     }
     num_dnsworkers--;

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.235
retrieving revision 1.236
diff -u -d -r1.235 -r1.236
--- or.h	28 Feb 2004 19:14:11 -0000	1.235
+++ or.h	28 Feb 2004 22:23:44 -0000	1.236
@@ -754,7 +754,8 @@
 void dns_init(void);
 int connection_dns_finished_flushing(connection_t *conn);
 int connection_dns_process_inbuf(connection_t *conn);
-void dns_cancel_pending_resolve(char *question, connection_t *onlyconn);
+void connection_dns_remove(connection_t *conn);
+void dns_cancel_pending_resolve(char *question);
 int dns_resolve(connection_t *exitconn);
 
 /********************************* main.c ***************************/