|
@@ -20,9 +20,18 @@ static void hs_usage_init(void);
|
|
|
uint64_t rephist_total_alloc=0;
|
|
|
uint32_t rephist_total_num=0;
|
|
|
|
|
|
+
|
|
|
+ * below this amount, the router can be treated as having 0 MTBF. */
|
|
|
#define STABILITY_EPSILON 0.0001
|
|
|
-#define STABILITY_ALPHA 0.9
|
|
|
+
|
|
|
+ * is compounded every STABILITY_INTERVAL. */
|
|
|
+#define STABILITY_ALPHA 0.95
|
|
|
+
|
|
|
#define STABILITY_INTERVAL (12*60*60)
|
|
|
+
|
|
|
+ * interval that just ended counts twice as much as one that ended a week ago,
|
|
|
+ * 20X as much as one that ended a month ago, and routers that have had no
|
|
|
+ * uptime data for about half a year will get forgotten.) */
|
|
|
|
|
|
|
|
|
typedef struct link_history_t {
|
|
@@ -56,18 +65,30 @@ typedef struct or_history_t {
|
|
|
time_t up_since;
|
|
|
|
|
|
time_t down_since;
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ */
|
|
|
unsigned long weighted_run_length;
|
|
|
+
|
|
|
+ * when did it come online? */
|
|
|
time_t start_of_run;
|
|
|
+
|
|
|
double total_run_weights;
|
|
|
+
|
|
|
|
|
|
* from this OR to OR2. */
|
|
|
digestmap_t *link_history_map;
|
|
|
} or_history_t;
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * total_run_weights by STABILITY_ALPHA? */
|
|
|
static time_t stability_last_downrated = 0;
|
|
|
|
|
|
+
|
|
|
+static time_t started_tracking_stability = 0;
|
|
|
+
|
|
|
|
|
|
static digestmap_t *history_map = NULL;
|
|
|
|
|
@@ -163,7 +184,9 @@ rep_hist_init(void)
|
|
|
hs_usage_init();
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * <b>hist</b>. If <b>failed</b>, the connection failed; otherwise, it was
|
|
|
+ * closed correctly. */
|
|
|
static void
|
|
|
mark_or_down(or_history_t *hist, time_t when, int failed)
|
|
|
{
|
|
@@ -176,7 +199,8 @@ mark_or_down(or_history_t *hist, time_t when, int failed)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * <b>hist</b>. */
|
|
|
static void
|
|
|
mark_or_up(or_history_t *hist, time_t when)
|
|
|
{
|
|
@@ -259,6 +283,8 @@ void
|
|
|
rep_hist_note_router_reachable(const char *id, time_t when)
|
|
|
{
|
|
|
or_history_t *hist = get_or_history(id);
|
|
|
+ if (!started_tracking_stability)
|
|
|
+ started_tracking_stability = time(NULL);
|
|
|
if (hist && !hist->start_of_run) {
|
|
|
hist->start_of_run = when;
|
|
|
}
|
|
@@ -270,6 +296,8 @@ void
|
|
|
rep_hist_note_router_unreachable(const char *id, time_t when)
|
|
|
{
|
|
|
or_history_t *hist = get_or_history(id);
|
|
|
+ if (!started_tracking_stability)
|
|
|
+ started_tracking_stability = time(NULL);
|
|
|
if (hist && hist->start_of_run) {
|
|
|
|
|
|
long run_length = when - hist->start_of_run;
|
|
@@ -279,7 +307,8 @@ rep_hist_note_router_unreachable(const char *id, time_t when)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * the time at which we should next discount MTBF data. */
|
|
|
time_t
|
|
|
rep_hist_downrate_old_runs(time_t now)
|
|
|
{
|
|
@@ -296,11 +325,13 @@ rep_hist_downrate_old_runs(time_t now)
|
|
|
if (stability_last_downrated + STABILITY_INTERVAL > now)
|
|
|
return stability_last_downrated + STABILITY_INTERVAL;
|
|
|
|
|
|
+
|
|
|
while (stability_last_downrated + STABILITY_INTERVAL < now) {
|
|
|
stability_last_downrated += STABILITY_INTERVAL;
|
|
|
alpha *= STABILITY_ALPHA;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
for (orhist_it = digestmap_iter_init(history_map);
|
|
|
!digestmap_iter_done(orhist_it);
|
|
|
orhist_it = digestmap_iter_next(history_map,orhist_it)) {
|
|
@@ -315,7 +346,7 @@ rep_hist_downrate_old_runs(time_t now)
|
|
|
return stability_last_downrated + STABILITY_INTERVAL;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
static double
|
|
|
get_stability(or_history_t *hist, time_t when)
|
|
|
{
|
|
@@ -323,16 +354,21 @@ get_stability(or_history_t *hist, time_t when)
|
|
|
double total_weights = hist->total_run_weights;
|
|
|
|
|
|
if (hist->start_of_run) {
|
|
|
+
|
|
|
+ * they would hold if the current run were to end now. */
|
|
|
total += (when-hist->start_of_run);
|
|
|
total_weights += 1.0;
|
|
|
}
|
|
|
- if (total_weights < STABILITY_EPSILON)
|
|
|
+ if (total_weights < STABILITY_EPSILON) {
|
|
|
+
|
|
|
return 0.0;
|
|
|
+ }
|
|
|
|
|
|
return total / total_weights;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * <b>id</b>. Return 0 if the router is unknown. */
|
|
|
double
|
|
|
rep_hist_get_stability(const char *id, time_t when)
|
|
|
{
|
|
@@ -343,6 +379,16 @@ rep_hist_get_stability(const char *id, time_t when)
|
|
|
return get_stability(hist, when);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * prounounce on Stability. */
|
|
|
+int
|
|
|
+rep_hist_have_measured_enough_stability(void)
|
|
|
+{
|
|
|
+
|
|
|
+ * as to whether we're tracking router stability. */
|
|
|
+ return started_tracking_stability < time(NULL) - 4*60*60;
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
* digest <b>from_id</b> to the OR with identity digest
|
|
|
* <b>to_name</b>.
|
|
@@ -502,7 +548,8 @@ rep_history_clean(time_t before)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * MTBF information. */
|
|
|
static char *
|
|
|
get_mtbf_filename(void)
|
|
|
{
|
|
@@ -513,7 +560,7 @@ get_mtbf_filename(void)
|
|
|
return fn;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
int
|
|
|
rep_hist_record_mtbf_data(void)
|
|
|
{
|
|
@@ -526,6 +573,16 @@ rep_hist_record_mtbf_data(void)
|
|
|
void *or_history_p;
|
|
|
or_history_t *hist;
|
|
|
|
|
|
+
|
|
|
+ * FormatLine *KeywordLine Data
|
|
|
+ *
|
|
|
+ * FormatLine = "format 1" NL
|
|
|
+ * KeywordLine = Keyword SP Arguments NL
|
|
|
+ * Data = "data" NL *RouterMTBFLine "." NL
|
|
|
+ * RouterMTBFLine = Fingerprint SP WeightedRunLen SP
|
|
|
+ * TotalRunWeights [SP S=StartRunTime] NL
|
|
|
+ */
|
|
|
+
|
|
|
lines = smartlist_create();
|
|
|
|
|
|
smartlist_add(lines, tor_strdup("format 1\n"));
|
|
@@ -534,6 +591,11 @@ rep_hist_record_mtbf_data(void)
|
|
|
tor_snprintf(buf, sizeof(buf), "stored-at %s\n", time_buf);
|
|
|
smartlist_add(lines, tor_strdup(buf));
|
|
|
|
|
|
+ if (started_tracking_stability) {
|
|
|
+ format_iso_time(time_buf, started_tracking_stability);
|
|
|
+ tor_snprintf(buf, sizeof(buf), "tracked-since %s\n", time_buf);
|
|
|
+ smartlist_add(lines, tor_strdup(buf));
|
|
|
+ }
|
|
|
if (stability_last_downrated) {
|
|
|
format_iso_time(time_buf, stability_last_downrated);
|
|
|
tor_snprintf(buf, sizeof(buf), "last-downrated %s\n", time_buf);
|
|
@@ -579,7 +641,8 @@ rep_hist_record_mtbf_data(void)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * on failure. */
|
|
|
int
|
|
|
rep_hist_load_mtbf_data(time_t now)
|
|
|
{
|
|
@@ -587,7 +650,8 @@ rep_hist_load_mtbf_data(time_t now)
|
|
|
smartlist_t *lines;
|
|
|
const char *line = NULL;
|
|
|
int r=0, i;
|
|
|
- time_t last_downrated = 0, stored_at = 0;
|
|
|
+ time_t last_downrated = 0, stored_at = 0, tracked_since = 0;
|
|
|
+ time_t latest_possible_start = now;
|
|
|
|
|
|
{
|
|
|
char *filename = get_mtbf_filename();
|
|
@@ -618,9 +682,16 @@ rep_hist_load_mtbf_data(time_t now)
|
|
|
log_warn(LD_GENERAL,"Couldn't parse stored time in mtbf "
|
|
|
"history file.");
|
|
|
}
|
|
|
+ if (!strcmpstart(line, "tracked-since ")) {
|
|
|
+ if (parse_iso_time(line+strlen("tracked-since "), &tracked_since)<0)
|
|
|
+ log_warn(LD_GENERAL,"Couldn't parse started-tracking time in mtbf "
|
|
|
+ "history file.");
|
|
|
+ }
|
|
|
}
|
|
|
if (last_downrated > now)
|
|
|
last_downrated = now;
|
|
|
+ if (tracked_since > now)
|
|
|
+ tracked_since = now;
|
|
|
|
|
|
if (!stored_at) {
|
|
|
log_warn(LD_GENERAL, "No stored time recorded.");
|
|
@@ -635,7 +706,7 @@ rep_hist_load_mtbf_data(time_t now)
|
|
|
char hexbuf[HEX_DIGEST_LEN+1];
|
|
|
char timebuf[ISO_TIME_LEN+1];
|
|
|
time_t start_of_run = 0;
|
|
|
- unsigned long wrl;
|
|
|
+ long wrl;
|
|
|
double trw;
|
|
|
int n;
|
|
|
or_history_t *hist;
|
|
@@ -643,7 +714,7 @@ rep_hist_load_mtbf_data(time_t now)
|
|
|
if (!strcmp(line, "."))
|
|
|
break;
|
|
|
|
|
|
- n = sscanf(line, "%40s %lu %lf S=%10s %8s",
|
|
|
+ n = sscanf(line, "%40s %ld %lf S=%10s %8s",
|
|
|
hexbuf, &wrl, &trw, timebuf, timebuf+11);
|
|
|
if (n != 3 && n != 5) {
|
|
|
log_warn(LD_GENERAL, "Couldn't scan line %s", escaped(line));
|
|
@@ -668,6 +739,8 @@ rep_hist_load_mtbf_data(time_t now)
|
|
|
long run_length = stored_at - start_of_run;
|
|
|
hist->start_of_run = now - run_length;
|
|
|
}
|
|
|
+ if (hist->start_of_run < latest_possible_start + wrl)
|
|
|
+ latest_possible_start = hist->start_of_run - wrl;
|
|
|
|
|
|
hist->weighted_run_length = wrl;
|
|
|
hist->total_run_weights = trw;
|
|
@@ -675,7 +748,11 @@ rep_hist_load_mtbf_data(time_t now)
|
|
|
if (strcmp(line, "."))
|
|
|
log_warn(LD_GENERAL, "Truncated MTBF file.");
|
|
|
|
|
|
+ if (!tracked_since)
|
|
|
+ tracked_since = latest_possible_start;
|
|
|
+
|
|
|
stability_last_downrated = last_downrated;
|
|
|
+ started_tracking_stability = tracked_since;
|
|
|
|
|
|
goto done;
|
|
|
err:
|