aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/TODO8
-rw-r--r--src/or/main.c5
-rw-r--r--src/or/or.h3
-rw-r--r--src/or/rephist.c134
4 files changed, 123 insertions, 27 deletions
diff --git a/doc/TODO b/doc/TODO
index 041b4e0a8..27eca82d7 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -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>.