Commit 80b3de87 authored by Nick Mathewson's avatar Nick Mathewson 🤹
Browse files

Tolerate a little skew in accounting intervals.

This will make changes for DST still work, and avoid double-spending
bytes when there are slight changes to configurations.

Fixes bug 1511; the DST issue is a bugfix on 0.0.9pre5.
parent 20817403
Loading
Loading
Loading
Loading

changes/bug1511

0 → 100644
+9 −0
Original line number Diff line number Diff line
  o Minor bugfixes:
    - Tolerate skew in stored vs computed interval starts for bandwidth
      accounting.  Now, if we change our configuration so that the start
      of the period changes by no more than 50% of the period's duration,
      we remember bytes that we transferred in the old one.  The upshot
      of this is that daylight savings time should no longer mess up
      bandwidth accounting and make each period potentially happen
      twice.  Fixes bug 1511; bugfix on 0.0.9pre5.
+25 −4
Original line number Diff line number Diff line
@@ -341,6 +341,15 @@ start_of_accounting_period_after(time_t now)
  return edge_of_accounting_period_containing(now, 1);
}

/** Return the length of the accounting period containing the time
 * <b>now</b>. */
static long
length_of_accounting_period_containing(time_t now)
{
  return edge_of_accounting_period_containing(now, 1) -
    edge_of_accounting_period_containing(now, 0);
}

/** Initialize the accounting subsystem. */
void
configure_accounting(time_t now)
@@ -360,11 +369,23 @@ configure_accounting(time_t now)
    log_info(LD_ACCT, "Continuing accounting interval.");
    /* We are in the interval we thought we were in. Do nothing.*/
    interval_end_time = start_of_accounting_period_after(interval_start_time);
  } else {
    time_t s_now = start_of_accounting_period_containing(interval_start_time);
    long duration = length_of_accounting_period_containing(interval_start_time);
    double delta = ((double)(s_now - interval_start_time)) / duration;
    if (-0.50 <= delta && delta <= 0.50) {
      /* The start of the period is now a little later than we remembered.
       * That's fine; we might lose a little time, but that's ok.  */
      log_info(LD_ACCT, "Accounting interval moved by %.02f%%; "
               "that's fine.", delta*100);
      interval_end_time = start_of_accounting_period_after(interval_start_time);
    } else {
      log_warn(LD_ACCT,
             "Mismatched accounting interval; starting a fresh one.");
               "Mismatched accounting interval: moved by %.02f%%. "
               "Starting a fresh one.", delta*100);
      reset_accounting(now);
    }
  }
  accounting_set_wakeup_time();
}