[or-cvs] [tor/master] Implement queue with O(1) operations, and correct some math.

Nick Mathewson nickm at seul.org
Wed Aug 26 15:36:43 UTC 2009


Author: Karsten Loesing <karsten.loesing at gmx.net>
Date: Mon, 17 Aug 2009 13:07:56 +0200
Subject: Implement queue with O(1) operations, and correct some math.
Commit: f37af0180d63f59dbb856e897f44a77d0390ab1a

---
 src/or/or.h    |   18 +++++++++++++++-
 src/or/relay.c |   59 +++++++++++++++++++++++++++----------------------------
 2 files changed, 45 insertions(+), 32 deletions(-)

diff --git a/src/or/or.h b/src/or/or.h
index ce4fbd0..c9eb4a3 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -835,16 +835,30 @@ typedef struct var_cell_t {
 typedef struct packed_cell_t {
   struct packed_cell_t *next; /**< Next cell queued on this circuit. */
   char body[CELL_NETWORK_SIZE]; /**< Cell as packed for network. */
-  struct timeval packed_timeval; /**< When was this cell packed? */
 } packed_cell_t;
 
+/** Number of cells added to a circuit queue including their insertion
+ * time on 10 millisecond detail; used for buffer statistics. */
+typedef struct insertion_time_elem_t {
+  struct insertion_time_elem_t *next;
+  uint32_t insertion_time; /**< When were cells inserted (in 10 ms steps
+                             * starting at 0:00 of the current day)? */
+  unsigned counter; /**< How many cells were inserted? */
+} insertion_time_elem_t;
+
+/** Queue of insertion times. */
+typedef struct insertion_time_queue_t {
+  struct insertion_time_elem_t *first;
+  struct insertion_time_elem_t *last;
+} insertion_time_queue_t;
+
 /** A queue of cells on a circuit, waiting to be added to the
  * or_connection_t's outbuf. */
 typedef struct cell_queue_t {
   packed_cell_t *head; /**< The first cell, or NULL if the queue is empty. */
   packed_cell_t *tail; /**< The last cell, or NULL if the queue is empty. */
   int n; /**< The number of cells in the queue. */
-  smartlist_t *insertion_times;
+  insertion_time_queue_t *insertion_times;
 } cell_queue_t;
 
 /** Beginning of a RELAY cell payload. */
diff --git a/src/or/relay.c b/src/or/relay.c
index 929b2e7..66475b4 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -1612,14 +1612,6 @@ cell_queue_append(cell_queue_t *queue, packed_cell_t *cell)
   ++queue->n;
 }
 
-/** Number of cells added to a circuit queue including their insertion
- * time on 10 millisecond detail; used for buffer statistics. */
-typedef struct insertion_time_elem_t {
-  uint32_t insertion_time; /**< When were cells inserted (in 10 ms steps
-                             * starting at 0:00 of the current day)? */
-  unsigned counter; /**< How many cells were inserted? */
-} insertion_time_elem_t;
-
 /** Append a newly allocated copy of <b>cell</b> to the end of <b>queue</b> */
 void
 cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell)
@@ -1629,21 +1621,20 @@ cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell)
   if (get_options()->CellStatistics) {
     struct timeval now;
     uint32_t added;
-    insertion_time_elem_t *last_elem = NULL;
+    insertion_time_queue_t *it_queue = queue->insertion_times;
     int add_new_elem = 0;
     tor_gettimeofday(&now);
 #define SECONDS_IN_A_DAY 86400L
-    added = now.tv_sec % SECONDS_IN_A_DAY * 10L + now.tv_usec / 100000L;
-    if (!queue->insertion_times) {
-      queue->insertion_times = smartlist_create();
+    added = (now.tv_sec % SECONDS_IN_A_DAY) * 100L + now.tv_usec / 10000L;
+    if (!it_queue) {
+      it_queue = tor_malloc_zero(sizeof(insertion_time_queue_t));
+      queue->insertion_times = it_queue;
     }
-    if (smartlist_len(queue->insertion_times) < 1) {
+    if (!it_queue->first) {
       add_new_elem = 1;
     } else {
-      last_elem = smartlist_get(queue->insertion_times,
-                      smartlist_len(queue->insertion_times) - 1);
-      if (last_elem->insertion_time == added)
-        last_elem->counter++;
+      if (it_queue->last->insertion_time == added)
+        it_queue->last->counter++;
       else
         add_new_elem = 1;
     }
@@ -1652,7 +1643,12 @@ cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell)
           tor_malloc_zero(sizeof(insertion_time_elem_t));
       elem->insertion_time = added;
       elem->counter = 1;
-      smartlist_add(queue->insertion_times, elem);
+      if (it_queue->last) {
+        it_queue->last->next = elem;
+        it_queue->last = elem;
+      } else {
+        it_queue->first = it_queue->last = elem;
+      }
     }
   }
   cell_queue_append(queue, copy);
@@ -1672,8 +1668,11 @@ cell_queue_clear(cell_queue_t *queue)
   queue->head = queue->tail = NULL;
   queue->n = 0;
   if (queue->insertion_times) {
-    SMARTLIST_FOREACH(queue->insertion_times, void *, e, tor_free(e));
-    smartlist_free(queue->insertion_times);
+    while (queue->insertion_times->first) {
+      insertion_time_elem_t *elem = queue->insertion_times->first;
+      queue->insertion_times->first = elem->next;
+      tor_free(elem);
+    }
     queue->insertion_times = NULL;
   }
 }
@@ -1874,23 +1873,23 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max,
       struct timeval now;
       uint32_t flushed;
       uint32_t cell_waiting_time;
+      insertion_time_queue_t *it_queue = queue->insertion_times;
       tor_gettimeofday(&now);
-      flushed = now.tv_sec % SECONDS_IN_A_DAY * 10L + now.tv_usec / 100000L;
-      if (!queue->insertion_times ||
-          smartlist_len(queue->insertion_times) < 1) {
+      flushed = (now.tv_sec % SECONDS_IN_A_DAY) * 100L +
+                 now.tv_usec / 10000L;
+      if (!it_queue || !it_queue->first) {
         log_warn(LD_BUG, "Cannot determine insertion time of cell.");
       } else {
         or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
-        insertion_time_elem_t *elem = smartlist_get(
-            queue->insertion_times, 0);
-        cell_waiting_time = (flushed + SECONDS_IN_A_DAY * 10L -
-                            elem->insertion_time) % (SECONDS_IN_A_DAY * 10L);
+        insertion_time_elem_t *elem = it_queue->first;
+        cell_waiting_time = (flushed * 10L + SECONDS_IN_A_DAY * 1000L -
+            elem->insertion_time * 10L) % (SECONDS_IN_A_DAY * 1000L);
 #undef SECONDS_IN_A_DAY
         elem->counter--;
         if (elem->counter < 1) {
-// TODO this operation is really expensive! write own queue impl?
-//          smartlist_del(queue->insertion_times, 0);
-          smartlist_remove(queue->insertion_times, elem);
+          it_queue->first = elem->next;
+          if (elem == it_queue->last)
+            it_queue->last = NULL;
           tor_free(elem);
         }
         orcirc->total_cell_waiting_time += cell_waiting_time;
-- 
1.5.6.5




More information about the tor-commits mailing list