summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-08-17 20:31:59 +0000
committerNick Mathewson <nickm@torproject.org>2007-08-17 20:31:59 +0000
commitb34ed73706c03671bee2cb8f1bb86b004ea2015e (patch)
treee3b70423ecbee7fd0c784a2a06068f065468824b
parentb60f4a4d16882f15321223936aa9e5f8dc1a1f5e (diff)
downloadtor-b34ed73706c03671bee2cb8f1bb86b004ea2015e.tar.gz
tor-b34ed73706c03671bee2cb8f1bb86b004ea2015e.zip
r14630@catbus: nickm | 2007-08-17 16:30:42 -0400
Functions to save and load MTBF information. svn:r11153
-rw-r--r--doc/TODO5
-rw-r--r--src/or/or.h2
-rw-r--r--src/or/rephist.c154
3 files changed, 157 insertions, 4 deletions
diff --git a/doc/TODO b/doc/TODO
index c2ca80a084..c84edd00c8 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -108,8 +108,9 @@ Things we'd like to do in 0.2.0.x:
o Track mtbf in rephist.c
o Do not delete old stability information if we're an authority.
o Make sure authorities call up/down functions as appropriate.
- - Record mtbf between invocations
- - Base stable on mtbf.
+ o Record mtbf between invocations
+ - Base Stable on mtbf.
+ - Test mtbf logic.
- 113: Simplifying directory authority administration
- 110: prevent infinite-length circuits (phase one)
- servers should recognize relay_extend cells and pass them
diff --git a/src/or/or.h b/src/or/or.h
index b1ab23ca32..ff53d35d0e 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3119,6 +3119,8 @@ void rep_history_clean(time_t before);
void rep_hist_note_router_reachable(const char *id, time_t when);
void rep_hist_note_router_unreachable(const char *id, time_t when);
+int rep_hist_record_mtbf_data(const char *filename);
+int rep_hist_load_mtbf_data(const char *filename, time_t now);
time_t rep_hist_downrate_old_runs(time_t now);
double rep_hist_get_stability(const char *id, time_t when);
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 87804182af..1bb8775d8f 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -71,7 +71,8 @@ static time_t stability_last_downrated = 0;
/** Map from hex OR identity digest to or_history_t. */
static digestmap_t *history_map = NULL;
-/** Return the or_history_t for the named OR, creating it if necessary. */
+/** Return the or_history_t for the OR with identity digest <b>id</b>,
+ * creating it if necessary. */
static or_history_t *
get_or_history(const char* id)
{
@@ -270,7 +271,7 @@ rep_hist_note_router_unreachable(const char *id, time_t when)
{
or_history_t *hist = get_or_history(id);
if (hist && hist->start_of_run) {
- /*XXXX020 treat failure specially. */
+ /*XXXX020 treat failure specially? */
long run_length = when - hist->start_of_run;
hist->weighted_run_length += run_length;
hist->total_run_weights += 1.0;
@@ -501,6 +502,155 @@ rep_history_clean(time_t before)
}
}
+/** DOCDOC */
+int
+rep_hist_record_mtbf_data(const char *filename)
+{
+ char buf[128];
+ char time_buf[ISO_TIME_LEN+1];
+ smartlist_t *lines;
+
+ digestmap_iter_t *orhist_it;
+ const char *digest;
+ void *or_history_p;
+ or_history_t *hist;
+
+ lines = smartlist_create();
+
+ smartlist_add(lines, tor_strdup("format 1\n"));
+
+ if (stability_last_downrated) {
+ format_iso_time(time_buf, stability_last_downrated);
+ tor_snprintf(buf, sizeof(buf), "last-downrated %s\n", time_buf);
+ smartlist_add(lines, tor_strdup(buf));
+ }
+ smartlist_add(lines, tor_strdup("data\n"));
+
+ for (orhist_it = digestmap_iter_init(history_map);
+ !digestmap_iter_done(orhist_it);
+ orhist_it = digestmap_iter_next(history_map,orhist_it)) {
+ char dbuf[HEX_DIGEST_LEN+1];
+ const char *t = NULL;
+ digestmap_iter_get(orhist_it, &digest, &or_history_p);
+ hist = (or_history_t*) or_history_p;
+
+ base16_encode(dbuf, sizeof(dbuf), digest, DIGEST_LEN);
+ if (hist->start_of_run) {
+ format_iso_time(time_buf, hist->start_of_run);
+ t = time_buf;
+ }
+ tor_snprintf(buf, sizeof(buf), "%s %lu %.5lf%s%s\n",
+ dbuf, hist->weighted_run_length, hist->total_run_weights,
+ t ? " S=" : "", t ? t : "");
+ smartlist_add(lines, tor_strdup(buf));
+ }
+
+ smartlist_add(lines, tor_strdup(".\n"));
+
+ {
+ size_t sz;
+ /* XXXX This isn't terribly efficient; line-at-a-time would be
+ * way faster. */
+ char *data = smartlist_join_strings(lines, "", 0, &sz);
+ int r = write_bytes_to_file(filename, data, sz, 0);
+
+ tor_free(data);
+ SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
+ smartlist_free(lines);
+ return r;
+ }
+}
+
+/** DOCDOC */
+int
+rep_hist_load_mtbf_data(const char *filename, time_t now)
+{
+ /* XXXX won't handle being called while history is already populated. */
+ smartlist_t *lines;
+ const char *line = NULL;
+ int r=0, i;
+ time_t last_downrated = 0;
+
+ {
+ char *d = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL);
+ if (!d)
+ return -1;
+ lines = smartlist_create();
+ smartlist_split_string(lines, d, "\n", SPLIT_SKIP_SPACE, 0);
+ tor_free(d);
+ }
+
+ if (smartlist_len(lines)<4 || strcmp(smartlist_get(lines, 0), "format 1")) {
+ log_warn(LD_GENERAL,"Unrecognized format in mtbf history file. Skipping.");
+ goto err;
+ }
+ for (i = 1; i < smartlist_len(lines); ++i) {
+ line = smartlist_get(lines, i);
+ if (!strcmp(line, "data"))
+ break;
+ if (!strcmpstart(line, "last-downrated ")) {
+ if (parse_iso_time(line+strlen("last-downrated "), &last_downrated)<0)
+ log_warn(LD_GENERAL,"Couldn't parse downrate time in mtbf "
+ "history file.");
+ }
+ if (last_downrated > now)
+ last_downrated = now;
+ }
+ if (line && !strcmp(line, "data"))
+ ++i;
+
+ for (; i < smartlist_len(lines); ++i) {
+ char digest[DIGEST_LEN];
+ char hexbuf[HEX_DIGEST_LEN+1];
+ char timebuf[ISO_TIME_LEN+1];
+ time_t start_of_run = 0;
+ unsigned long wrl;
+ double trw;
+ int n;
+ or_history_t *hist;
+ line = smartlist_get(lines, i);
+ if (!strcmp(line, "."))
+ break;
+ /* XXXX020 audit the heck out of my scanf usage. */
+ n = sscanf(line, "%40s %lu %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));
+ continue;
+ }
+ if (base16_decode(digest, DIGEST_LEN, hexbuf, HEX_DIGEST_LEN) < 0) {
+ log_warn(LD_GENERAL, "Couldn't hex string %s", escaped(hexbuf));
+ continue;
+ }
+ if (n == 5) {
+ timebuf[10] = ' ';
+ if (parse_iso_time(timebuf, &start_of_run)<0)
+ log_warn(LD_GENERAL, "Couldn't parse time %s", escaped(timebuf));
+ }
+ hist = get_or_history(digest);
+ if (!hist)
+ continue;
+ if (start_of_run > now)
+ start_of_run = now;
+ hist->start_of_run = start_of_run;
+ hist->weighted_run_length = wrl;
+ hist->total_run_weights = trw;
+ /* Subtract time in which */
+ }
+ if (strcmp(line, "."))
+ log_warn(LD_GENERAL, "Truncated MTBF file %s", escaped(filename));
+
+ stability_last_downrated = last_downrated;
+
+ goto done;
+ err:
+ r = -1;
+ done:
+ SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
+ smartlist_free(lines);
+ return r;
+}
+
/** For how many seconds do we keep track of individual per-second bandwidth
* totals? */
#define NUM_SECS_ROLLING_MEASURE 10