aboutsummaryrefslogtreecommitdiff
path: root/src/or/rephist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/rephist.c')
-rw-r--r--src/or/rephist.c292
1 files changed, 104 insertions, 188 deletions
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 3b0d9dd35..5446c25e3 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2012, The Tor Project, Inc. */
+ * Copyright (c) 2007-2013, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -160,7 +160,7 @@ get_link_history(const char *from_id, const char *to_id)
/** Helper: free storage held by a single link history entry. */
static void
-_free_link_history(void *val)
+free_link_history_(void *val)
{
rephist_total_alloc -= sizeof(link_history_t);
tor_free(val);
@@ -171,7 +171,7 @@ static void
free_or_history(void *_hist)
{
or_history_t *hist = _hist;
- digestmap_free(hist->link_history_map, _free_link_history);
+ digestmap_free(hist->link_history_map, free_link_history_);
rephist_total_alloc -= sizeof(or_history_t);
rephist_total_num--;
tor_free(hist);
@@ -310,9 +310,10 @@ rep_hist_note_router_reachable(const char *id, const tor_addr_t *at_addr,
tor_assert(hist);
tor_assert((!at_addr && !at_port) || (at_addr && at_port));
- addr_changed = at_addr &&
+ addr_changed = at_addr && !tor_addr_is_null(&hist->last_reached_addr) &&
tor_addr_compare(at_addr, &hist->last_reached_addr, CMP_EXACT) != 0;
- port_changed = at_port && at_port != hist->last_reached_port;
+ port_changed = at_port && hist->last_reached_port &&
+ at_port != hist->last_reached_port;
if (!started_tracking_stability)
started_tracking_stability = time(NULL);
@@ -422,6 +423,21 @@ rep_hist_note_router_unreachable(const char *id, time_t when)
}
}
+/** Mark a router with ID <b>id</b> as non-Running, and retroactively declare
+ * that it has never been running: give it no stability and no WFU. */
+void
+rep_hist_make_router_pessimal(const char *id, time_t when)
+{
+ or_history_t *hist = get_or_history(id);
+ tor_assert(hist);
+
+ rep_hist_note_router_unreachable(id, when);
+ mark_or_down(hist, when, 1);
+
+ hist->weighted_run_length = 0;
+ hist->weighted_uptime = 0;
+}
+
/** Helper: Discount all old MTBF data, if it is time to do so. Return
* the time at which we should next discount MTBF data. */
time_t
@@ -648,7 +664,7 @@ rep_hist_dump_stats(time_t now, int severity)
rep_history_clean(now - get_options()->RephistTrackTime);
- log(severity, LD_HIST, "--------------- Dumping history information:");
+ tor_log(severity, LD_HIST, "--------------- Dumping history information:");
for (orhist_it = digestmap_iter_init(history_map);
!digestmap_iter_done(orhist_it);
@@ -673,7 +689,7 @@ rep_hist_dump_stats(time_t now, int severity)
} else {
uptime=1.0;
}
- log(severity, LD_HIST,
+ tor_log(severity, LD_HIST,
"OR %s [%s]: %ld/%ld good connections; uptime %ld/%ld sec (%.2f%%); "
"wmtbf %lu:%02lu:%02lu",
name1, hexdigest1,
@@ -707,7 +723,7 @@ rep_hist_dump_stats(time_t now, int severity)
else
len += ret;
}
- log(severity, LD_HIST, "%s", buffer);
+ tor_log(severity, LD_HIST, "%s", buffer);
}
}
}
@@ -863,126 +879,6 @@ rep_hist_record_mtbf_data(time_t now, int missing_means_down)
return -1;
}
-/** Format the current tracked status of the router in <b>hist</b> at time
- * <b>now</b> for analysis; return it in a newly allocated string. */
-static char *
-rep_hist_format_router_status(or_history_t *hist, time_t now)
-{
- char sor_buf[ISO_TIME_LEN+1];
- char sod_buf[ISO_TIME_LEN+1];
- double wfu;
- double mtbf;
- int up = 0, down = 0;
- char *cp = NULL;
-
- if (hist->start_of_run) {
- format_iso_time(sor_buf, hist->start_of_run);
- up = 1;
- }
- if (hist->start_of_downtime) {
- format_iso_time(sod_buf, hist->start_of_downtime);
- down = 1;
- }
-
- wfu = get_weighted_fractional_uptime(hist, now);
- mtbf = get_stability(hist, now);
- tor_asprintf(&cp,
- "%s%s%s"
- "%s%s%s"
- "wfu %0.3f\n"
- " weighted-time %lu\n"
- " weighted-uptime %lu\n"
- "mtbf %0.1f\n"
- " weighted-run-length %lu\n"
- " total-run-weights %f\n",
- up?"uptime-started ":"", up?sor_buf:"", up?" UTC\n":"",
- down?"downtime-started ":"", down?sod_buf:"", down?" UTC\n":"",
- wfu,
- hist->total_weighted_time,
- hist->weighted_uptime,
- mtbf,
- hist->weighted_run_length,
- hist->total_run_weights
- );
- return cp;
-}
-
-/** The last stability analysis document that we created, or NULL if we never
- * have created one. */
-static char *last_stability_doc = NULL;
-/** The last time we created a stability analysis document, or 0 if we never
- * have created one. */
-static time_t built_last_stability_doc_at = 0;
-/** Shortest allowable time between building two stability documents. */
-#define MAX_STABILITY_DOC_BUILD_RATE (3*60)
-
-/** Return a pointer to a NUL-terminated document describing our view of the
- * stability of the routers we've been tracking. Return NULL on failure. */
-const char *
-rep_hist_get_router_stability_doc(time_t now)
-{
- char *result;
- smartlist_t *chunks;
- if (built_last_stability_doc_at + MAX_STABILITY_DOC_BUILD_RATE > now)
- return last_stability_doc;
-
- if (!history_map)
- return NULL;
-
- tor_free(last_stability_doc);
- chunks = smartlist_new();
-
- if (rep_hist_have_measured_enough_stability()) {
- smartlist_add(chunks, tor_strdup("we-have-enough-measurements\n"));
- } else {
- smartlist_add(chunks, tor_strdup("we-do-not-have-enough-measurements\n"));
- }
-
- DIGESTMAP_FOREACH(history_map, id, or_history_t *, hist) {
- const node_t *node;
- char dbuf[BASE64_DIGEST_LEN+1];
- char *info;
- digest_to_base64(dbuf, id);
- node = node_get_by_id(id);
- if (node) {
- char ip[INET_NTOA_BUF_LEN+1];
- char tbuf[ISO_TIME_LEN+1];
- time_t published = node_get_published_on(node);
- node_get_address_string(node,ip,sizeof(ip));
- if (published > 0)
- format_iso_time(tbuf, published);
- else
- strlcpy(tbuf, "???", sizeof(tbuf));
- smartlist_add_asprintf(chunks,
- "router %s %s %s\n"
- "published %s\n"
- "relevant-flags %s%s%s\n"
- "declared-uptime %ld\n",
- dbuf, node_get_nickname(node), ip,
- tbuf,
- node->is_running ? "Running " : "",
- node->is_valid ? "Valid " : "",
- node->ri && node->ri->is_hibernating ? "Hibernating " : "",
- node_get_declared_uptime(node));
- } else {
- smartlist_add_asprintf(chunks,
- "router %s {no descriptor}\n", dbuf);
- }
- info = rep_hist_format_router_status(hist, now);
- if (info)
- smartlist_add(chunks, info);
-
- } DIGESTMAP_FOREACH_END;
-
- result = smartlist_join_strings(chunks, "", 0, NULL);
- SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
- smartlist_free(chunks);
-
- last_stability_doc = result;
- built_last_stability_doc_at = time(NULL);
- return result;
-}
-
/** Helper: return the first j >= i such that !strcmpstart(sl[j], prefix) and
* such that no line sl[k] with i <= k < j starts with "R ". Return -1 if no
* such line exists. */
@@ -1035,7 +931,7 @@ correct_time(time_t t, time_t now, time_t stored_at, time_t started_measuring)
return 0;
else {
long run_length = stored_at - t;
- t = now - run_length;
+ t = (time_t)(now - run_length);
if (t < started_measuring)
t = started_measuring;
return t;
@@ -1136,7 +1032,7 @@ rep_hist_load_mtbf_data(time_t now)
wfu_timebuf[0] = '\0';
if (format == 1) {
- n = sscanf(line, "%40s %ld %lf S=%10s %8s",
+ n = tor_sscanf(line, "%40s %ld %lf S=%10s %8s",
hexbuf, &wrl, &trw, mtbf_timebuf, mtbf_timebuf+11);
if (n != 3 && n != 5) {
log_warn(LD_HIST, "Couldn't scan line %s", escaped(line));
@@ -1153,7 +1049,7 @@ rep_hist_load_mtbf_data(time_t now)
wfu_idx = find_next_with(lines, i+1, "+WFU ");
if (mtbf_idx >= 0) {
const char *mtbfline = smartlist_get(lines, mtbf_idx);
- n = sscanf(mtbfline, "+MTBF %lu %lf S=%10s %8s",
+ n = tor_sscanf(mtbfline, "+MTBF %lu %lf S=%10s %8s",
&wrl, &trw, mtbf_timebuf, mtbf_timebuf+11);
if (n == 2 || n == 4) {
have_mtbf = 1;
@@ -1164,7 +1060,7 @@ rep_hist_load_mtbf_data(time_t now)
}
if (wfu_idx >= 0) {
const char *wfuline = smartlist_get(lines, wfu_idx);
- n = sscanf(wfuline, "+WFU %lu %lu S=%10s %8s",
+ n = tor_sscanf(wfuline, "+WFU %lu %lu S=%10s %8s",
&wt_uptime, &total_wt_time,
wfu_timebuf, wfu_timebuf+11);
if (n == 2 || n == 4) {
@@ -1196,7 +1092,7 @@ rep_hist_load_mtbf_data(time_t now)
hist->start_of_run = correct_time(start_of_run, now, stored_at,
tracked_since);
if (hist->start_of_run < latest_possible_start + wrl)
- latest_possible_start = hist->start_of_run - wrl;
+ latest_possible_start = (time_t)(hist->start_of_run - wrl);
hist->weighted_run_length = wrl;
hist->total_run_weights = trw;
@@ -1531,10 +1427,10 @@ rep_hist_get_bandwidth_lines(void)
const char *desc = NULL;
size_t len;
- /* opt [dirreq-](read|write)-history yyyy-mm-dd HH:MM:SS (n s) n,n,n... */
+ /* [dirreq-](read|write)-history yyyy-mm-dd HH:MM:SS (n s) n,n,n... */
/* The n,n,n part above. Largest representation of a uint64_t is 20 chars
* long, plus the comma. */
-#define MAX_HIST_VALUE_LEN 21*NUM_TOTALS
+#define MAX_HIST_VALUE_LEN (21*NUM_TOTALS)
len = (67+MAX_HIST_VALUE_LEN)*4;
buf = tor_malloc_zero(len);
cp = buf;
@@ -1846,22 +1742,20 @@ rep_hist_note_used_port(time_t now, uint16_t port)
add_predicted_port(now, port);
}
-/** For this long after we've seen a request for a given port, assume that
- * we'll want to make connections to the same port in the future. */
-#define PREDICTED_CIRCS_RELEVANCE_TIME (60*60)
-
/** Return a newly allocated pointer to a list of uint16_t * for ports that
* are likely to be asked for in the near future.
*/
smartlist_t *
rep_hist_get_predicted_ports(time_t now)
{
+ int predicted_circs_relevance_time;
smartlist_t *out = smartlist_new();
tor_assert(predicted_ports_list);
+ predicted_circs_relevance_time = get_options()->PredictedPortsRelevanceTime;
/* clean out obsolete entries */
SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
- if (pp->time + PREDICTED_CIRCS_RELEVANCE_TIME < now) {
+ if (pp->time + predicted_circs_relevance_time < now) {
log_debug(LD_CIRC, "Expiring predicted port %d", pp->port);
rephist_total_alloc -= sizeof(predicted_port_t);
@@ -1928,14 +1822,17 @@ int
rep_hist_get_predicted_internal(time_t now, int *need_uptime,
int *need_capacity)
{
+ int predicted_circs_relevance_time;
+ predicted_circs_relevance_time = get_options()->PredictedPortsRelevanceTime;
+
if (!predicted_internal_time) { /* initialize it */
predicted_internal_time = now;
predicted_internal_uptime_time = now;
predicted_internal_capacity_time = now;
}
- if (predicted_internal_time + PREDICTED_CIRCS_RELEVANCE_TIME < now)
+ if (predicted_internal_time + predicted_circs_relevance_time < now)
return 0; /* too long ago */
- if (predicted_internal_uptime_time + PREDICTED_CIRCS_RELEVANCE_TIME >= now)
+ if (predicted_internal_uptime_time + predicted_circs_relevance_time >= now)
*need_uptime = 1;
// Always predict that we need capacity.
*need_capacity = 1;
@@ -1947,8 +1844,11 @@ rep_hist_get_predicted_internal(time_t now, int *need_uptime,
int
any_predicted_circuits(time_t now)
{
+ int predicted_circs_relevance_time;
+ predicted_circs_relevance_time = get_options()->PredictedPortsRelevanceTime;
+
return smartlist_len(predicted_ports_list) ||
- predicted_internal_time + PREDICTED_CIRCS_RELEVANCE_TIME >= now;
+ predicted_internal_time + predicted_circs_relevance_time >= now;
}
/** Return 1 if we have no need for circuits currently, else return 0. */
@@ -2042,7 +1942,7 @@ note_crypto_pk_op(pk_op_t operation)
void
dump_pk_ops(int severity)
{
- log(severity, LD_HIST,
+ tor_log(severity, LD_HIST,
"PK operations: %lu directory objects signed, "
"%lu directory objects verified, "
"%lu routerdescs signed, "
@@ -2131,7 +2031,7 @@ rep_hist_exit_stats_term(void)
* but works fine for sorting an array of port numbers, which is what we use
* it for. */
static int
-_compare_int(const void *x, const void *y)
+compare_int_(const void *x, const void *y)
{
return (*(int*)x - *(int*)y);
}
@@ -2218,7 +2118,7 @@ rep_hist_format_exit_stats(time_t now)
other_streams = total_streams;
/* Sort the ports; this puts them out of sync with top_bytes, but we
* won't be using top_bytes again anyway */
- qsort(top_ports, top_elements, sizeof(int), _compare_int);
+ qsort(top_ports, top_elements, sizeof(int), compare_int_);
for (j = 0; j < top_elements; j++) {
cur_port = top_ports[j];
if (exit_bytes_written[cur_port] > 0) {
@@ -2297,7 +2197,7 @@ rep_hist_format_exit_stats(time_t now)
time_t
rep_hist_exit_stats_write(time_t now)
{
- char *statsdir = NULL, *filename = NULL, *str = NULL;
+ char *str = NULL;
if (!start_of_exit_stats_interval)
return 0; /* Not initialized. */
@@ -2313,19 +2213,12 @@ rep_hist_exit_stats_write(time_t now)
rep_hist_reset_exit_stats(now);
/* Try to write to disk. */
- statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
- log_warn(LD_HIST, "Unable to create stats/ directory!");
- goto done;
+ if (!check_or_create_data_subdir("stats")) {
+ write_to_data_subdir("stats", "exit-stats", str, "exit port statistics");
}
- filename = get_datadir_fname2("stats", "exit-stats");
- if (write_str_to_file(filename, str, 0) < 0)
- log_warn(LD_HIST, "Unable to write exit port statistics to disk!");
done:
tor_free(str);
- tor_free(statsdir);
- tor_free(filename);
return start_of_exit_stats_interval + WRITE_STATS_INTERVAL;
}
@@ -2418,7 +2311,7 @@ rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval)
return;
start_of_interval = (circ->timestamp_created.tv_sec >
start_of_buffer_stats_interval) ?
- circ->timestamp_created.tv_sec :
+ (time_t)circ->timestamp_created.tv_sec :
start_of_buffer_stats_interval;
interval_length = (int) (end_of_interval - start_of_interval);
if (interval_length <= 0)
@@ -2440,7 +2333,7 @@ rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval)
/** Sorting helper: return -1, 1, or 0 based on comparison of two
* circ_buffer_stats_t */
static int
-_buffer_stats_compare_entries(const void **_a, const void **_b)
+buffer_stats_compare_entries_(const void **_a, const void **_b)
{
const circ_buffer_stats_t *a = *_a, *b = *_b;
if (a->processed_cells < b->processed_cells)
@@ -2505,7 +2398,7 @@ rep_hist_format_buffer_stats(time_t now)
number_of_circuits = smartlist_len(circuits_for_buffer_stats);
if (number_of_circuits > 0) {
smartlist_sort(circuits_for_buffer_stats,
- _buffer_stats_compare_entries);
+ buffer_stats_compare_entries_);
i = 0;
SMARTLIST_FOREACH_BEGIN(circuits_for_buffer_stats,
circ_buffer_stats_t *, stat)
@@ -2582,7 +2475,7 @@ time_t
rep_hist_buffer_stats_write(time_t now)
{
circuit_t *circ;
- char *statsdir = NULL, *filename = NULL, *str = NULL;
+ char *str = NULL;
if (!start_of_buffer_stats_interval)
return 0; /* Not initialized. */
@@ -2590,7 +2483,7 @@ rep_hist_buffer_stats_write(time_t now)
goto done; /* Not ready to write */
/* Add open circuits to the history. */
- for (circ = _circuit_get_global_list(); circ; circ = circ->next) {
+ TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) {
rep_hist_buffer_stats_add_circ(circ, now);
}
@@ -2601,19 +2494,12 @@ rep_hist_buffer_stats_write(time_t now)
rep_hist_reset_buffer_stats(now);
/* Try to write to disk. */
- statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
- log_warn(LD_HIST, "Unable to create stats/ directory!");
- goto done;
+ if (!check_or_create_data_subdir("stats")) {
+ write_to_data_subdir("stats", "buffer-stats", str, "buffer statistics");
}
- filename = get_datadir_fname2("stats", "buffer-stats");
- if (write_str_to_file(filename, str, 0) < 0)
- log_warn(LD_HIST, "Unable to write buffer stats to disk!");
done:
tor_free(str);
- tor_free(filename);
- tor_free(statsdir);
return start_of_buffer_stats_interval + WRITE_STATS_INTERVAL;
}
@@ -2725,7 +2611,7 @@ rep_hist_format_desc_stats(time_t now)
time_t
rep_hist_desc_stats_write(time_t now)
{
- char *statsdir = NULL, *filename = NULL, *str = NULL;
+ char *filename = NULL, *str = NULL;
if (!start_of_served_descs_stats_interval)
return 0; /* We're not collecting stats. */
@@ -2735,10 +2621,8 @@ rep_hist_desc_stats_write(time_t now)
str = rep_hist_format_desc_stats(now);
tor_assert(str != NULL);
- statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
- log_warn(LD_HIST, "Unable to create stats/ directory!");
- goto done;
+ if (check_or_create_data_subdir("stats") < 0) {
+ goto done;
}
filename = get_datadir_fname2("stats", "served-desc-stats");
if (append_bytes_to_file(filename, str, strlen(str), 0) < 0)
@@ -2747,7 +2631,6 @@ rep_hist_desc_stats_write(time_t now)
rep_hist_reset_desc_stats(now);
done:
- tor_free(statsdir);
tor_free(filename);
tor_free(str);
return start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL;
@@ -2965,7 +2848,7 @@ rep_hist_format_conn_stats(time_t now)
time_t
rep_hist_conn_stats_write(time_t now)
{
- char *statsdir = NULL, *filename = NULL, *str = NULL;
+ char *str = NULL;
if (!start_of_conn_stats_interval)
return 0; /* Not initialized. */
@@ -2979,22 +2862,55 @@ rep_hist_conn_stats_write(time_t now)
rep_hist_reset_conn_stats(now);
/* Try to write to disk. */
- statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
- log_warn(LD_HIST, "Unable to create stats/ directory!");
- goto done;
+ if (!check_or_create_data_subdir("stats")) {
+ write_to_data_subdir("stats", "conn-stats", str, "connection statistics");
}
- filename = get_datadir_fname2("stats", "conn-stats");
- if (write_str_to_file(filename, str, 0) < 0)
- log_warn(LD_HIST, "Unable to write conn stats to disk!");
done:
tor_free(str);
- tor_free(filename);
- tor_free(statsdir);
return start_of_conn_stats_interval + WRITE_STATS_INTERVAL;
}
+/** Internal statistics to track how many requests of each type of
+ * handshake we've received, and how many we've assigned to cpuworkers.
+ * Useful for seeing trends in cpu load.
+ * @{ */
+STATIC int onion_handshakes_requested[MAX_ONION_HANDSHAKE_TYPE+1] = {0};
+STATIC int onion_handshakes_assigned[MAX_ONION_HANDSHAKE_TYPE+1] = {0};
+/**@}*/
+
+/** A new onionskin (using the <b>type</b> handshake) has arrived. */
+void
+rep_hist_note_circuit_handshake_requested(uint16_t type)
+{
+ if (type <= MAX_ONION_HANDSHAKE_TYPE)
+ onion_handshakes_requested[type]++;
+}
+
+/** We've sent an onionskin (using the <b>type</b> handshake) to a
+ * cpuworker. */
+void
+rep_hist_note_circuit_handshake_assigned(uint16_t type)
+{
+ if (type <= MAX_ONION_HANDSHAKE_TYPE)
+ onion_handshakes_assigned[type]++;
+}
+
+/** Log our onionskin statistics since the last time we were called. */
+void
+rep_hist_log_circuit_handshake_stats(time_t now)
+{
+ (void)now;
+ log_notice(LD_HEARTBEAT, "Circuit handshake stats since last time: "
+ "%d/%d TAP, %d/%d NTor.",
+ onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_TAP],
+ onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP],
+ onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR],
+ onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR]);
+ memset(onion_handshakes_assigned, 0, sizeof(onion_handshakes_assigned));
+ memset(onion_handshakes_requested, 0, sizeof(onion_handshakes_requested));
+}
+
/** Free all storage held by the OR/link history caches, by the
* bandwidth history arrays, by the port history, or by statistics . */
void
@@ -3003,11 +2919,11 @@ rep_hist_free_all(void)
digestmap_free(history_map, free_or_history);
tor_free(read_array);
tor_free(write_array);
- tor_free(last_stability_doc);
+ tor_free(dir_read_array);
+ tor_free(dir_write_array);
tor_free(exit_bytes_read);
tor_free(exit_bytes_written);
tor_free(exit_streams);
- built_last_stability_doc_at = 0;
predicted_ports_free();
bidi_map_free();