[tor-commits] [tor/maint-0.2.2] Add Maxima lists to bandwidth state.

nickm at torproject.org nickm at torproject.org
Fri Feb 25 16:23:51 UTC 2011


commit 105b94b75b51376128037cab05b930c4e4c15497
Author: Nick Mathewson <nickm at torproject.org>
Date:   Mon Jan 10 14:11:22 2011 -0500

    Add Maxima lists to bandwidth state.
    
    Right now, Tor routers don't save the maxima values from the
    bw_history_t between sessions.  That's no good, since we use those
    values to determine bandwidth.  This code adds a new BWHist.*Maximum
    set of values to the state file.  If they're not present, we estimate
    them by taking the observed total bandwidth and dividing it by the
    period length, which provides a lower bound.
    
    This should fix bug 1863.  I'm calling it a feature.
---
 changes/1863_bwhist |    8 +++++-
 src/or/config.c     |    4 +++
 src/or/or.h         |    8 +++++-
 src/or/rephist.c    |   65 +++++++++++++++++++++++++++++++++++++-------------
 4 files changed, 66 insertions(+), 19 deletions(-)

diff --git a/changes/1863_bwhist b/changes/1863_bwhist
index b9e8ef4..b942509 100644
--- a/changes/1863_bwhist
+++ b/changes/1863_bwhist
@@ -1,3 +1,10 @@
+  o Minor features
+    - Servers now save observed maximum bandwidth throughput rates
+      to their state file (along with total usage, which was already
+      saved) so that they can determine their correct estimated
+      bandwidth on restart.  Resolves bug 1863, where Tor servers
+      would reset their estimated bandwidth to 0 after restarting.
+
   o Minor bugfixes
     - Fix a bug in banwidth history state parsing that could have been
       triggered if a future version of Tor ever changed the timing
@@ -7,4 +14,3 @@
       error parsing any bw history value from the state file. Bugfix on
       Tor 0.2.2.15-alpha.
 
-
diff --git a/src/or/config.c b/src/or/config.c
index 17d776e..78978dc 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -443,15 +443,19 @@ static config_var_t _state_vars[] = {
   V(BWHistoryReadEnds,                ISOTIME,  NULL),
   V(BWHistoryReadInterval,            UINT,     "900"),
   V(BWHistoryReadValues,              CSV,      ""),
+  V(BWHistoryReadMaxima,              CSV,      ""),
   V(BWHistoryWriteEnds,               ISOTIME,  NULL),
   V(BWHistoryWriteInterval,           UINT,     "900"),
   V(BWHistoryWriteValues,             CSV,      ""),
+  V(BWHistoryWriteMaxima,             CSV,      ""),
   V(BWHistoryDirReadEnds,             ISOTIME,  NULL),
   V(BWHistoryDirReadInterval,         UINT,     "900"),
   V(BWHistoryDirReadValues,           CSV,      ""),
+  V(BWHistoryDirReadMaxima,           CSV,      ""),
   V(BWHistoryDirWriteEnds,            ISOTIME,  NULL),
   V(BWHistoryDirWriteInterval,        UINT,     "900"),
   V(BWHistoryDirWriteValues,          CSV,      ""),
+  V(BWHistoryDirWriteMaxima,          CSV,      ""),
 
   V(TorVersion,                       STRING,   NULL),
 
diff --git a/src/or/or.h b/src/or/or.h
index cb36126..e0f8bab 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2856,19 +2856,25 @@ typedef struct {
    * bandwidth usage. The "Interval" fields hold the granularity, in seconds,
    * of the entries of Values.  The "Values" lists hold decimal string
    * representations of the number of bytes read or written in each
-   * interval. */
+   * interval. The "Maxima" list holds decimal strings describing the highest
+   * rate achieved during the interval.
+   */
   time_t      BWHistoryReadEnds;
   int         BWHistoryReadInterval;
   smartlist_t *BWHistoryReadValues;
+  smartlist_t *BWHistoryReadMaxima;
   time_t      BWHistoryWriteEnds;
   int         BWHistoryWriteInterval;
   smartlist_t *BWHistoryWriteValues;
+  smartlist_t *BWHistoryWriteMaxima;
   time_t      BWHistoryDirReadEnds;
   int         BWHistoryDirReadInterval;
   smartlist_t *BWHistoryDirReadValues;
+  smartlist_t *BWHistoryDirReadMaxima;
   time_t      BWHistoryDirWriteEnds;
   int         BWHistoryDirWriteInterval;
   smartlist_t *BWHistoryDirWriteValues;
+  smartlist_t *BWHistoryDirWriteMaxima;
 
   /** Build time histogram */
   config_line_t * BuildtimeHistogram;
diff --git a/src/or/rephist.c b/src/or/rephist.c
index f0dd451..a3a2bab 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -1261,8 +1261,12 @@ add_obs(bw_array_t *b, time_t when, uint64_t n)
   /* If we're currently adding observations for an earlier second than
    * 'when', advance b->cur_obs_time and b->cur_obs_idx by an
    * appropriate number of seconds, and do all the other housekeeping */
-  while (when>b->cur_obs_time)
+  while (when>b->cur_obs_time) {
+    /* Doing this one second at a time is potentially inefficient, if we start
+       with a state file that is very old.  Fortunately, it doesn't seem to
+       show up in profiles, so we can just ignore it for now.  */
     advance_obs(b);
+  }
 
   b->obs[b->cur_obs_idx] += n;
   b->total_in_period += n;
@@ -1497,15 +1501,21 @@ static void
 rep_hist_update_bwhist_state_section(or_state_t *state,
                                      const bw_array_t *b,
                                      smartlist_t **s_values,
+                                     smartlist_t **s_maxima,
                                      time_t *s_begins,
                                      int *s_interval)
 {
-  char buf[20*NUM_TOTALS + 1], *cp;
+  char *cp;
+  int i,j;
 
   if (*s_values) {
     SMARTLIST_FOREACH(*s_values, char *, val, tor_free(val));
     smartlist_free(*s_values);
   }
+  if (*s_maxima) {
+    SMARTLIST_FOREACH(*s_values, char *, val, tor_free(val));
+    smartlist_free(*s_maxima);
+  }
   if (! server_mode(get_options())) {
     /* Clients don't need to store bandwidth history persistently;
      * force these values to the defaults. */
@@ -1519,18 +1529,30 @@ rep_hist_update_bwhist_state_section(or_state_t *state,
     *s_begins = 0;
     *s_interval = 900;
     *s_values = smartlist_create();
+    *s_maxima = smartlist_create();
     return;
   }
   *s_begins = b->next_period;
   *s_interval = NUM_SECS_BW_SUM_INTERVAL;
-  cp = buf;
-  cp += rep_hist_fill_bandwidth_history(cp, sizeof(buf), b);
-  tor_snprintf(cp, sizeof(buf)-(cp-buf),
-               cp == buf ? U64_FORMAT : ","U64_FORMAT,
-               U64_PRINTF_ARG(b->total_in_period));
+
   *s_values = smartlist_create();
-  if (server_mode(get_options()))
-    smartlist_split_string(*s_values, buf, ",", SPLIT_SKIP_SPACE, 0);
+  *s_maxima = smartlist_create();
+  /* Set i to first position in circular array */
+  i = (b->num_maxes_set <= b->next_max_idx) ? 0 : b->next_max_idx;
+  for (j=0; j < b->num_maxes_set; ++j,++i) {
+    uint64_t maxval;
+    if (i > NUM_TOTALS)
+      i = 0;
+    tor_asprintf(&cp, U64_FORMAT, U64_PRINTF_ARG(b->totals[i] & ~0x3ff));
+    smartlist_add(*s_values, cp);
+    maxval = b->maxima[i] / NUM_SECS_ROLLING_MEASURE;
+    tor_asprintf(&cp, U64_FORMAT, U64_PRINTF_ARG(maxval & ~0x3ff));
+    smartlist_add(*s_maxima, cp);
+  }
+  tor_asprintf(&cp, U64_FORMAT, U64_PRINTF_ARG(b->total_in_period & ~0x3ff));
+  smartlist_add(*s_values, cp);
+  tor_asprintf(&cp, U64_FORMAT, U64_PRINTF_ARG(b->max_total & ~0x3ff));
+  smartlist_add(*s_maxima, cp);
 }
 
 /** Update <b>state</b> with the newest bandwidth history. */
@@ -1541,6 +1563,7 @@ rep_hist_update_state(or_state_t *state)
   rep_hist_update_bwhist_state_section(state,\
                                        (arrname),\
                                        &state->BWHistory ## st ## Values, \
+                                       &state->BWHistory ## st ## Maxima, \
                                        &state->BWHistory ## st ## Ends, \
                                        &state->BWHistory ## st ## Interval)
 
@@ -1560,6 +1583,7 @@ rep_hist_update_state(or_state_t *state)
 static int
 rep_hist_load_bwhist_state_section(bw_array_t *b,
                                    const smartlist_t *s_values,
+                                   const smartlist_t *s_maxima,
                                    const time_t s_begins,
                                    const int s_interval)
 {
@@ -1567,8 +1591,9 @@ rep_hist_load_bwhist_state_section(bw_array_t *b,
   int retval = 0;
   time_t start;
 
-  uint64_t v;
-  int i,ok;
+  uint64_t v, mv;
+  int i,ok,ok_m;
+  int have_maxima = (smartlist_len(s_values) == smartlist_len(s_maxima));
 
   if (s_values && s_begins >= now - NUM_SECS_BW_SUM_INTERVAL*NUM_TOTALS) {
     start = s_begins - s_interval*(smartlist_len(s_values));
@@ -1578,12 +1603,22 @@ rep_hist_load_bwhist_state_section(bw_array_t *b,
     b->next_period = start + NUM_SECS_BW_SUM_INTERVAL;
     SMARTLIST_FOREACH_BEGIN(s_values, const char *, cp) {
         v = tor_parse_uint64(cp, 10, 0, UINT64_MAX, &ok, NULL);
-        if (!ok) {
+        if (have_maxima) {
+          const char *maxstr = smartlist_get(s_maxima, cp_sl_idx);
+          mv = tor_parse_uint64(maxstr, 10, 0, UINT64_MAX, &ok_m, NULL);
+          mv *= NUM_SECS_ROLLING_MEASURE;
+        } else {
+          /* No maxima known; guess average rate to be conservative. */
+          mv = v / s_interval;
+        }
+        if (!ok || !ok_m) {
           retval = -1;
           log_notice(LD_HIST, "Could not parse '%s' into a number.'", cp);
         }
+
         if (start < now) {
           add_obs(b, start, v);
+          b->max_total = mv;
           /* This will result in some fairly choppy history if s_interval
            * is notthe same as NUM_SECS_BW_SUM_INTERVAL. XXXX */
           start += s_interval;
@@ -1592,15 +1627,10 @@ rep_hist_load_bwhist_state_section(bw_array_t *b,
   }
 
   /* Clean up maxima and observed */
-  /* Do we really want to zero this for the purpose of max capacity? */
   for (i=0; i<NUM_SECS_ROLLING_MEASURE; ++i) {
     b->obs[i] = 0;
   }
   b->total_obs = 0;
-  for (i=0; i<NUM_TOTALS; ++i) {
-    b->maxima[i] = 0;
-  }
-  b->max_total = 0;
 
   return retval;
 }
@@ -1619,6 +1649,7 @@ rep_hist_load_state(or_state_t *state, char **err)
   if (rep_hist_load_bwhist_state_section(                               \
                                 (arrname),                              \
                                 state->BWHistory ## st ## Values,       \
+                                state->BWHistory ## st ## Maxima,       \
                                 state->BWHistory ## st ## Ends,         \
                                 state->BWHistory ## st ## Interval)<0)  \
     all_ok = 0





More information about the tor-commits mailing list