diff options
-rw-r--r-- | doc/TODO | 8 | ||||
-rw-r--r-- | src/or/main.c | 5 | ||||
-rw-r--r-- | src/or/or.h | 3 | ||||
-rw-r--r-- | src/or/rephist.c | 134 |
4 files changed, 123 insertions, 27 deletions
@@ -101,11 +101,13 @@ Things we'd like to do in 0.2.0.x: - Start caching consensus documents once authorities make them - Start downloading and using consensus documents once caches serve them . 104: Long and Short Router Descriptors - . Merge proposal + o Merge proposal - Drop bandwidth history from router-descriptors - 105: Version negotiation for the Tor protocol - - 108: Base "Stable" Flag on Mean Time Between Failures - - Track mtbf in rephist.c + . 108: Base "Stable" Flag on Mean Time Between Failures + o Track mtbf in rephist.c + - Do not delete old stability information if we're an authority. + - Make sure authorities call up/down functions as appropriate. - Record mtbf between invocations - Base stable on mtbf. - 113: Simplifying directory authority administration diff --git a/src/or/main.c b/src/or/main.c index 3719afe58..3ccad90ad 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -844,6 +844,7 @@ run_scheduled_events(time_t now) static time_t time_to_reset_descriptor_failures = 0; static time_t time_to_add_entropy = 0; static time_t time_to_write_hs_statistics = 0; + static time_t time_to_downrate_stability = 0; or_options_t *options = get_options(); int i; int have_dir_info; @@ -931,6 +932,10 @@ run_scheduled_events(time_t now) dirserv_test_reachability(0); } + /** 1d. DOCDOC */ + if (time_to_downrate_stability < now) + time_to_downrate_stability = rep_hist_downrate_old_runs(now); + /** 2. Periodically, we consider getting a new directory, getting a * new running-routers list, and/or force-uploading our descriptor * (if we've passed our internal checks). */ diff --git a/src/or/or.h b/src/or/or.h index 0864d24e5..88eb43c44 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3117,6 +3117,9 @@ void rep_hist_update_state(or_state_t *state); int rep_hist_load_state(or_state_t *state, char **err); void rep_history_clean(time_t before); +time_t rep_hist_downrate_old_runs(time_t now); +double rep_hist_get_stability(const char *id, time_t when); + void rep_hist_note_used_port(uint16_t port, time_t now); smartlist_t *rep_hist_get_predicted_ports(time_t now); void rep_hist_note_used_resolve(time_t now); diff --git a/src/or/rephist.c b/src/or/rephist.c index c712f1525..ccb8d7953 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -20,6 +20,10 @@ static void hs_usage_init(void); uint64_t rephist_total_alloc=0; uint32_t rephist_total_num=0; +#define STABILITY_EPSILON 0.0001 +#define STABILITY_ALPHA 0.9 +#define STABILITY_INTERVAL (12*60*60) + /** History of an OR-\>OR link. */ typedef struct link_history_t { /** When did we start tracking this list? */ @@ -52,11 +56,18 @@ typedef struct or_history_t { time_t up_since; /** If nonzero, we have been unable to connect since this time. */ time_t down_since; + /** DOCDOC */ + unsigned long weighted_run_length; + time_t start_of_run; + double total_run_weights; /** Map from hex OR2 identity digest to a link_history_t for the link * from this OR to OR2. */ digestmap_t *link_history_map; } or_history_t; +/** DOCDOC */ +static time_t stability_last_downrated = 0; + /** Map from hex OR identity digest to or_history_t. */ static digestmap_t *history_map = NULL; @@ -151,6 +162,42 @@ rep_hist_init(void) hs_usage_init(); } +/** DOCDOC */ +static void +mark_or_down(or_history_t *hist, time_t when, int failed) +{ + if (hist->start_of_run) { + /*XXXX020 treat failure specially. */ + long run_length = when - hist->start_of_run; + hist->weighted_run_length += run_length; + hist->total_run_weights += 1.0; + hist->start_of_run = 0; + } + if (hist->up_since) { + hist->uptime += (when - hist->up_since); + hist->up_since = 0; + } + if (failed && !hist->down_since) { + hist->down_since = when; + } +} + +/** DOCDOC */ +static void +mark_or_up(or_history_t *hist, time_t when) +{ + if (!hist->start_of_run) { + hist->start_of_run = when; + } + if (hist->down_since) { + hist->downtime += (when - hist->down_since); + hist->down_since = 0; + } + if (!hist->up_since) { + hist->up_since = when; + } +} + /** Remember that an attempt to connect to the OR with identity digest * <b>id</b> failed at <b>when</b>. */ @@ -162,12 +209,7 @@ rep_hist_note_connect_failed(const char* id, time_t when) if (!hist) return; ++hist->n_conn_fail; - if (hist->up_since) { - hist->uptime += (when - hist->up_since); - hist->up_since = 0; - } - if (!hist->down_since) - hist->down_since = when; + mark_or_down(hist, when, 1); hist->changed = when; } @@ -182,12 +224,7 @@ rep_hist_note_connect_succeeded(const char* id, time_t when) if (!hist) return; ++hist->n_conn_ok; - if (hist->down_since) { - hist->downtime += (when - hist->down_since); - hist->down_since = 0; - } - if (!hist->up_since) - hist->up_since = when; + mark_or_up(hist, when); hist->changed = when; } @@ -201,11 +238,7 @@ rep_hist_note_disconnect(const char* id, time_t when) hist = get_or_history(id); if (!hist) return; - ++hist->n_conn_ok; - if (hist->up_since) { - hist->uptime += (when - hist->up_since); - hist->up_since = 0; - } + mark_or_down(hist, when, 0); hist->changed = when; } @@ -217,7 +250,7 @@ rep_hist_note_connection_died(const char* id, time_t when) { or_history_t *hist; if (!id) { - /* If conn has no nickname, it didn't complete its handshake, or something + /* If conn has no identity, it didn't complete its handshake, or something * went wrong. Ignore it. */ return; @@ -225,15 +258,68 @@ rep_hist_note_connection_died(const char* id, time_t when) hist = get_or_history(id); if (!hist) return; - if (hist->up_since) { - hist->uptime += (when - hist->up_since); - hist->up_since = 0; - } - if (!hist->down_since) - hist->down_since = when; + mark_or_down(hist, when, 1); hist->changed = when; } +/**DOCDOC*/ +time_t +rep_hist_downrate_old_runs(time_t now) +{ + digestmap_iter_t *orhist_it; + const char *digest1; + or_history_t *hist; + void *hist_p; + double alpha = 1.0; + + if (!history_map) + history_map = digestmap_new(); + if (!stability_last_downrated) + stability_last_downrated = 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)) { + digestmap_iter_get(orhist_it, &digest1, &hist_p); + hist = hist_p; + + hist->weighted_run_length = + (unsigned long)(hist->weighted_run_length * alpha); + hist->total_run_weights *= alpha; + } + + return stability_last_downrated + STABILITY_INTERVAL; +} + +/**DOCDOC*/ +double +rep_hist_get_stability(const char *id, time_t when) +{ + or_history_t *hist = get_or_history(id); + unsigned long total; + double total_weights; + if (!hist) + return 0.0; + + total = hist->weighted_run_length; + total_weights = hist->total_run_weights; + if (hist->start_of_run) { + total += (when-hist->start_of_run); + total_weights += 1.0; + } + if (total_weights < STABILITY_EPSILON) + return 0.0; + + return total / total_weights; +} + /** Remember that we successfully extended from the OR with identity * digest <b>from_id</b> to the OR with identity digest * <b>to_name</b>. |