aboutsummaryrefslogtreecommitdiff
path: root/src/or/circuitlist.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2013-11-15 15:35:00 -0500
committerNick Mathewson <nickm@torproject.org>2013-11-15 15:35:00 -0500
commit7a2b30fe16eacc040b3dd11f8c39c410628c2f43 (patch)
tree356e060be24608160a8e5d4fea33d39cc01a4c46 /src/or/circuitlist.c
parent4aa9affec2eac0a95ba026e380718b032451a0af (diff)
parent59f50c80d443a7e148f85cfed493e3e703cc4386 (diff)
downloadtor-7a2b30fe16eacc040b3dd11f8c39c410628c2f43.tar
tor-7a2b30fe16eacc040b3dd11f8c39c410628c2f43.tar.gz
Merge remote-tracking branch 'origin/maint-0.2.4'
Conflicts: src/or/relay.c Conflict changes were easy; compilation fixes required were using using TOR_SIMPLEQ_FIRST to get head of cell queue.
Diffstat (limited to 'src/or/circuitlist.c')
-rw-r--r--src/or/circuitlist.c58
1 files changed, 48 insertions, 10 deletions
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 19f46188b..c31bc49d0 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -1620,25 +1620,58 @@ n_cells_in_circ_queues(const circuit_t *c)
return n;
}
-/** helper to sort a list of circuit_q by total queue lengths, in descending
- * order. */
+/**
+ * Return the age of the oldest cell queued on <b>c</b>, in milliseconds.
+ * Return 0 if there are no cells queued on c. Requires that <b>now</b> be
+ * the current time in milliseconds since the epoch, truncated.
+ *
+ * This function will return incorrect results if the oldest cell queued on
+ * the circuit is older than 2**32 msec (about 49 days) old.
+ */
+static uint32_t
+circuit_max_queued_cell_age(const circuit_t *c, uint32_t now)
+{
+ uint32_t age = 0;
+ packed_cell_t *cell;
+
+ if (NULL != (cell = TOR_SIMPLEQ_FIRST(&c->n_chan_cells.head)))
+ age = now - cell->inserted_time;
+
+ if (! CIRCUIT_IS_ORIGIN(c)) {
+ const or_circuit_t *orcirc = TO_OR_CIRCUIT((circuit_t*)c);
+ if (NULL != (cell = TOR_SIMPLEQ_FIRST(&orcirc->p_chan_cells.head))) {
+ uint32_t age2 = now - cell->inserted_time;
+ if (age2 > age)
+ return age2;
+ }
+ }
+ return age;
+}
+
+/** Temporary variable for circuits_compare_by_oldest_queued_cell_ This is a
+ * kludge to work around the fact that qsort doesn't provide a way for
+ * comparison functions to take an extra argument. */
+static uint32_t circcomp_now_tmp;
+
+/** Helper to sort a list of circuit_t by age of oldest cell, in descending
+ * order. Requires that circcomp_now_tmp is set correctly. */
static int
-circuits_compare_by_queue_len_(const void **a_, const void **b_)
+circuits_compare_by_oldest_queued_cell_(const void **a_, const void **b_)
{
const circuit_t *a = *a_;
const circuit_t *b = *b_;
- size_t a_n = n_cells_in_circ_queues(a);
- size_t b_n = n_cells_in_circ_queues(b);
+ uint32_t age_a = circuit_max_queued_cell_age(a, circcomp_now_tmp);
+ uint32_t age_b = circuit_max_queued_cell_age(b, circcomp_now_tmp);
- if (a_n < b_n)
+ if (age_a < age_b)
return 1;
- else if (a_n == b_n)
+ else if (age_a == age_b)
return 0;
else
return -1;
}
-#define FRACTION_OF_CIRCS_TO_RETAIN_ON_OOM 0.90
+#define FRACTION_OF_CELLS_TO_RETAIN_ON_OOM 0.90
/** We're out of memory for cells, having allocated <b>current_allocation</b>
* bytes' worth. Kill the 'worst' circuits until we're under
@@ -1651,13 +1684,14 @@ circuits_handle_oom(size_t current_allocation)
circuit_t *circ;
size_t n_cells_removed=0, n_cells_to_remove;
int n_circuits_killed=0;
+ struct timeval now;
log_notice(LD_GENERAL, "We're low on memory. Killing circuits with "
"over-long queues. (This behavior is controlled by "
"MaxMemInCellQueues.)");
{
size_t mem_target = (size_t)(get_options()->MaxMemInCellQueues *
- FRACTION_OF_CIRCS_TO_RETAIN_ON_OOM);
+ FRACTION_OF_CELLS_TO_RETAIN_ON_OOM);
size_t mem_to_recover;
if (current_allocation <= mem_target)
return;
@@ -1670,9 +1704,13 @@ circuits_handle_oom(size_t current_allocation)
TOR_LIST_FOREACH(circ, &global_circuitlist, head)
smartlist_add(circlist, circ);
+ /* Set circcomp_now_tmp so that the sort can work. */
+ tor_gettimeofday_cached(&now);
+ circcomp_now_tmp = (uint32_t)tv_to_msec(&now);
+
/* This is O(n log n); there are faster algorithms we could use instead.
* Let's hope this doesn't happen enough to be in the critical path. */
- smartlist_sort(circlist, circuits_compare_by_queue_len_);
+ smartlist_sort(circlist, circuits_compare_by_oldest_queued_cell_);
/* Okay, now the worst circuits are at the front of the list. Let's mark
* them, and reclaim their storage aggressively. */