diff options
author | Karsten Loesing <karsten.loesing@gmx.net> | 2009-08-19 15:41:12 +0200 |
---|---|---|
committer | Karsten Loesing <karsten.loesing@gmx.net> | 2009-08-19 15:41:12 +0200 |
commit | 4e29f3342754fa8802c364b58f7b2f98e983a291 (patch) | |
tree | f570d879362bf688ab1da6290689d1d099656df1 /src/or | |
parent | 10fbc998e146b271508066e7680cb0cd00a70c63 (diff) | |
download | tor-4e29f3342754fa8802c364b58f7b2f98e983a291.tar tor-4e29f3342754fa8802c364b58f7b2f98e983a291.tar.gz |
Write all statistics to disk exactly every 24 hours.
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/circuitlist.c | 2 | ||||
-rw-r--r-- | src/or/config.c | 40 | ||||
-rw-r--r-- | src/or/connection.c | 4 | ||||
-rw-r--r-- | src/or/connection_edge.c | 2 | ||||
-rw-r--r-- | src/or/geoip.c | 106 | ||||
-rw-r--r-- | src/or/main.c | 44 | ||||
-rw-r--r-- | src/or/or.h | 22 | ||||
-rw-r--r-- | src/or/rephist.c | 225 |
8 files changed, 230 insertions, 215 deletions
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 04b1d8edb..065559620 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -449,7 +449,7 @@ circuit_free(circuit_t *circ) or_circuit_t *ocirc = TO_OR_CIRCUIT(circ); /* Remember cell statistics for this circuit before deallocating. */ if (get_options()->CellStatistics) - add_circ_to_buffer_stats(circ, time(NULL)); + rep_hist_buffer_stats_add_circ(circ, time(NULL)); mem = ocirc; memlen = sizeof(or_circuit_t); tor_assert(circ->magic == OR_CIRCUIT_MAGIC); diff --git a/src/or/config.c b/src/or/config.c index 7b3f0ad07..acc544b8b 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1407,29 +1407,13 @@ options_act(or_options_t *old_options) tor_free(actual_fname); } - if (options->DirReqStatistics) { + if (options->DirReqStatistics && !geoip_is_loaded()) { /* Check if GeoIP database could be loaded. */ - if (!geoip_is_loaded()) { - log_warn(LD_CONFIG, "Configured to measure directory request " - "statistics, but no GeoIP database found!"); - return -1; - } - log_notice(LD_CONFIG, "Configured to count directory requests by " - "country and write aggregate statistics to disk. Check the " - "dirreq-stats file in your data directory that will first " - "be written in 24 hours from now."); + log_warn(LD_CONFIG, "Configured to measure directory request " + "statistics, but no GeoIP database found!"); + return -1; } - if (options->ExitPortStatistics) - log_notice(LD_CONFIG, "Configured to measure exit port statistics. " - "Look for the exit-stats file that will first be written to " - "the data directory in 24 hours from now."); - - if (options->CellStatistics) - log_notice(LD_CONFIG, "Configured to measure cell statistics. Look " - "for the buffer-stats file that will first be written to " - "the data directory in 24 hours from now."); - if (options->EntryStatistics) { if (should_record_bridge_info(options)) { /* Don't allow measuring statistics on entry guards when configured @@ -1442,11 +1426,7 @@ options_act(or_options_t *old_options) log_warn(LD_CONFIG, "Configured to measure entry node statistics, " "but no GeoIP database found!"); return -1; - } else - log_notice(LD_CONFIG, "Configured to measure entry node " - "statistics. Look for the entry-stats file that will " - "first be written to the data directory in 24 hours " - "from now."); + } } /* Check if we need to parse and add the EntryNodes config option. */ @@ -3784,6 +3764,16 @@ options_transition_allowed(or_options_t *old, or_options_t *new_val, return -1; } + if (old->CellStatistics != new_val->CellStatistics || + old->DirReqStatistics != new_val->DirReqStatistics || + old->EntryStatistics != new_val->EntryStatistics || + old->ExitPortStatistics != new_val->ExitPortStatistics) { + *msg = tor_strdup("While Tor is running, changing either " + "CellStatistics, DirReqStatistics, EntryStatistics, " + "or ExitPortStatistics is not allowed."); + return -1; + } + return 0; } diff --git a/src/or/connection.c b/src/or/connection.c index 48f827857..c961f16c6 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1704,12 +1704,12 @@ connection_buckets_decrement(connection_t *conn, time_t now, if (num_read > 0) { if (conn->type == CONN_TYPE_EXIT) - rep_hist_note_exit_bytes_read(conn->port, num_read, now); + rep_hist_note_exit_bytes_read(conn->port, num_read); rep_hist_note_bytes_read(num_read, now); } if (num_written > 0) { if (conn->type == CONN_TYPE_EXIT) - rep_hist_note_exit_bytes_written(conn->port, num_written, now); + rep_hist_note_exit_bytes_written(conn->port, num_written); rep_hist_note_bytes_written(num_written, now); } diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 1df576d63..f25202725 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -333,7 +333,7 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) escaped_safe_str(conn->address),conn->port, safe_str(fmt_addr(&conn->addr))); - rep_hist_note_exit_stream_opened(conn->port, approx_time()); + rep_hist_note_exit_stream_opened(conn->port); conn->state = EXIT_CONN_STATE_OPEN; connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */ diff --git a/src/or/geoip.c b/src/or/geoip.c index 824428b7d..9f37c021c 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -12,8 +12,6 @@ #include "ht.h" static void clear_geoip_db(void); -static void dump_geoip_stats(void); -static void dump_entry_stats(void); /** An entry from the GeoIP file: maps an IP range to a country. */ typedef struct geoip_entry_t { @@ -390,37 +388,6 @@ geoip_note_client_seen(geoip_client_action_t action, return; } - /* Rotate the current request period. */ - while (current_request_period_starts + REQUEST_HIST_PERIOD < now) { - if (!geoip_countries) - geoip_countries = smartlist_create(); - if (!current_request_period_starts) { - current_request_period_starts = now; - break; - } - /* Also discard all items in the client history that are too old. - * (This only works here because bridge and directory stats are - * independent. Otherwise, we'd only want to discard those items - * with action GEOIP_CLIENT_NETWORKSTATUS{_V2}.) */ - geoip_remove_old_clients(current_request_period_starts); - /* Before rotating, write the current stats to disk. */ - dump_geoip_stats(); - if (get_options()->EntryStatistics) - dump_entry_stats(); - /* Now rotate request period */ - SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, { - memmove(&c->n_v2_ns_requests[0], &c->n_v2_ns_requests[1], - sizeof(uint32_t)*(REQUEST_HIST_LEN-1)); - memmove(&c->n_v3_ns_requests[0], &c->n_v3_ns_requests[1], - sizeof(uint32_t)*(REQUEST_HIST_LEN-1)); - c->n_v2_ns_requests[REQUEST_HIST_LEN-1] = 0; - c->n_v3_ns_requests[REQUEST_HIST_LEN-1] = 0; - }); - current_request_period_starts += REQUEST_HIST_PERIOD; - if (n_old_request_periods < REQUEST_HIST_LEN-1) - ++n_old_request_periods; - } - lookup.ipaddr = addr; lookup.action = (int)action; ent = HT_FIND(clientmap, &client_history, &lookup); @@ -940,12 +907,20 @@ geoip_get_request_history(time_t now, geoip_client_action_t action) return result; } +/** Start time of directory request stats. */ +static time_t start_of_dirreq_stats_interval; + +/** Initialize directory request stats. */ +void +geoip_dirreq_stats_init(time_t now) +{ + start_of_dirreq_stats_interval = now; +} + /** Store all our geoip statistics into $DATADIR/dirreq-stats. */ -static void -dump_geoip_stats(void) +void +geoip_dirreq_stats_write(time_t now) { - time_t now = time(NULL); - time_t request_start; char *filename = get_datadir_fname("dirreq-stats"); char *data_v2 = NULL, *data_v3 = NULL; char written[ISO_TIME_LEN+1]; @@ -957,11 +932,14 @@ dump_geoip_stats(void) if (!get_options()->DirReqStatistics) goto done; + /* Discard all items in the client history that are too old. */ + geoip_remove_old_clients(start_of_dirreq_stats_interval); + data_v2 = geoip_get_client_history_dirreq(now, GEOIP_CLIENT_NETWORKSTATUS_V2); data_v3 = geoip_get_client_history_dirreq(now, GEOIP_CLIENT_NETWORKSTATUS); - format_iso_time(written, geoip_get_history_start() + REQUEST_HIST_PERIOD); + format_iso_time(written, now); out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND, 0600, &open_file); if (!out) @@ -973,8 +951,6 @@ dump_geoip_stats(void) tor_free(data_v2); tor_free(data_v3); - request_start = current_request_period_starts - - (n_old_request_periods * REQUEST_HIST_PERIOD); data_v2 = geoip_get_request_history(now, GEOIP_CLIENT_NETWORKSTATUS_V2); data_v3 = geoip_get_request_history(now, GEOIP_CLIENT_NETWORKSTATUS); if (fprintf(out, "dirreq-v3-reqs %s\ndirreq-v2-reqs %s\n", @@ -1033,6 +1009,22 @@ dump_geoip_stats(void) finish_writing_to_file(open_file); open_file = NULL; + + /* Rotate request period */ + SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, { + memmove(&c->n_v2_ns_requests[0], &c->n_v2_ns_requests[1], + sizeof(uint32_t)*(REQUEST_HIST_LEN-1)); + memmove(&c->n_v3_ns_requests[0], &c->n_v3_ns_requests[1], + sizeof(uint32_t)*(REQUEST_HIST_LEN-1)); + c->n_v2_ns_requests[REQUEST_HIST_LEN-1] = 0; + c->n_v3_ns_requests[REQUEST_HIST_LEN-1] = 0; + }); + current_request_period_starts += REQUEST_HIST_PERIOD; + if (n_old_request_periods < REQUEST_HIST_LEN-1) + ++n_old_request_periods; + + start_of_dirreq_stats_interval = now; + done: if (open_file) abort_writing_to_file(open_file); @@ -1041,29 +1033,46 @@ dump_geoip_stats(void) tor_free(data_v3); } +/** Start time of entry stats. */ +static time_t start_of_entry_stats_interval; + +/** Initialize entry stats. */ +void +geoip_entry_stats_init(time_t now) +{ + start_of_entry_stats_interval = now; +} + /** Store all our geoip statistics as entry guards into * $DATADIR/entry-stats. */ -static void -dump_entry_stats(void) +void +geoip_entry_stats_write(time_t now) { -#ifdef ENABLE_ENTRY_STATS - time_t now = time(NULL); char *filename = get_datadir_fname("entry-stats"); char *data = NULL; char written[ISO_TIME_LEN+1]; open_file_t *open_file = NULL; FILE *out; - data = geoip_get_client_history(now, GEOIP_CLIENT_CONNECT); - format_iso_time(written, geoip_get_history_start() + REQUEST_HIST_PERIOD); + if (!get_options()->EntryStatistics) + goto done; + + /* Discard all items in the client history that are too old. */ + geoip_remove_old_clients(start_of_entry_stats_interval); + + data = geoip_get_client_history_dirreq(now, GEOIP_CLIENT_CONNECT); + format_iso_time(written, now); out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND, 0600, &open_file); if (!out) goto done; - if (fprintf(out, "entry-stats-end %s (%d s)\nentry-ips %s\n", - written, REQUEST_HIST_PERIOD, data ? data : "") < 0) + if (fprintf(out, "entry-stats-end %s (%u s)\nentry-ips %s\n", + written, (unsigned) (now - start_of_entry_stats_interval), + data ? data : "") < 0) goto done; + start_of_entry_stats_interval = now; + finish_writing_to_file(open_file); open_file = NULL; done: @@ -1071,7 +1080,6 @@ dump_entry_stats(void) abort_writing_to_file(open_file); tor_free(filename); tor_free(data); -#endif } /** Helper used to implement GETINFO ip-to-country/... controller command. */ diff --git a/src/or/main.c b/src/or/main.c index 403ae9362..16136cb27 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -830,7 +830,7 @@ run_scheduled_events(time_t now) static time_t time_to_clean_caches = 0; static time_t time_to_recheck_bandwidth = 0; static time_t time_to_check_for_expired_networkstatus = 0; - static time_t time_to_dump_buffer_stats = 0; + static time_t time_to_write_stats_files = 0; static time_t time_to_retry_dns_init = 0; or_options_t *options = get_options(); int i; @@ -958,10 +958,44 @@ run_scheduled_events(time_t now) time_to_check_for_expired_networkstatus = now + CHECK_EXPIRED_NS_INTERVAL; } - if (time_to_dump_buffer_stats < now) { - if (get_options()->CellStatistics && time_to_dump_buffer_stats) - dump_buffer_stats(); - time_to_dump_buffer_stats = now + DUMP_BUFFER_STATS_INTERVAL; + /* 1g. Check whether we should write statistics to disk. + */ + if (time_to_write_stats_files >= 0 && time_to_write_stats_files < now) { +#define WRITE_STATS_INTERVAL (24*60*60) + or_options_t *options = get_options(); + if (options->CellStatistics || options->DirReqStatistics || + options->EntryStatistics || options->ExitPortStatistics) { + if (!time_to_write_stats_files) { + /* Initialize stats. */ + if (options->CellStatistics) + rep_hist_buffer_stats_init(now); + if (options->DirReqStatistics) + geoip_dirreq_stats_init(now); + if (options->EntryStatistics) + geoip_entry_stats_init(now); + if (options->ExitPortStatistics) + rep_hist_exit_stats_init(now); + log_notice(LD_CONFIG, "Configured to measure statistics. Look for " + "the *-stats files that will first be written to the " + "data directory in %d hours from now.", + WRITE_STATS_INTERVAL / (60 * 60)); + time_to_write_stats_files = now + WRITE_STATS_INTERVAL; + } else { + /* Write stats to disk. */ + time_to_write_stats_files += WRITE_STATS_INTERVAL; + if (options->CellStatistics) + rep_hist_buffer_stats_write(time_to_write_stats_files); + if (options->DirReqStatistics) + geoip_dirreq_stats_write(time_to_write_stats_files); + if (options->EntryStatistics) + geoip_entry_stats_write(time_to_write_stats_files); + if (options->ExitPortStatistics) + rep_hist_exit_stats_write(time_to_write_stats_files); + } + } else { + /* Never write stats to disk */ + time_to_write_stats_files = -1; + } } /* Remove old information from rephist and the rend cache. */ diff --git a/src/or/or.h b/src/or/or.h index 9a0f51f46..98ab860a0 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3739,6 +3739,11 @@ void geoip_start_dirreq(uint64_t dirreq_id, size_t response_size, void geoip_change_dirreq_state(uint64_t dirreq_id, dirreq_type_t type, dirreq_state_t new_state); +void geoip_dirreq_stats_init(time_t now); +void geoip_dirreq_stats_write(time_t now); +void geoip_entry_stats_init(time_t now); +void geoip_entry_stats_write(time_t now); + /********************************* hibernate.c **********************/ int accounting_parse_options(or_options_t *options, int validate_only); @@ -4076,11 +4081,11 @@ void rep_hist_note_extend_failed(const char *from_name, const char *to_name); void rep_hist_dump_stats(time_t now, int severity); void rep_hist_note_bytes_read(size_t num_bytes, time_t when); void rep_hist_note_bytes_written(size_t num_bytes, time_t when); -void rep_hist_note_exit_bytes_read(uint16_t port, size_t num_bytes, - time_t now); -void rep_hist_note_exit_bytes_written(uint16_t port, size_t num_bytes, - time_t now); -void rep_hist_note_exit_stream_opened(uint16_t port, time_t now); +void rep_hist_note_exit_bytes_read(uint16_t port, size_t num_bytes); +void rep_hist_note_exit_bytes_written(uint16_t port, size_t num_bytes); +void rep_hist_note_exit_stream_opened(uint16_t port); +void rep_hist_exit_stats_init(time_t now); +void rep_hist_exit_stats_write(time_t now); int rep_hist_bandwidth_assess(void); char *rep_hist_get_bandwidth_lines(int for_extrainfo); void rep_hist_update_state(or_state_t *state); @@ -4132,9 +4137,10 @@ void hs_usage_note_fetch_successful(const char *service_id, time_t now); void hs_usage_write_statistics_to_file(time_t now); void hs_usage_free_all(void); -#define DUMP_BUFFER_STATS_INTERVAL (24*60*60) -void add_circ_to_buffer_stats(circuit_t *circ, time_t end_of_interval); -void dump_buffer_stats(void); +void rep_hist_buffer_stats_init(time_t now); +void rep_hist_buffer_stats_add_circ(circuit_t *circ, + time_t end_of_interval); +void rep_hist_buffer_stats_write(time_t now); /********************************* rendclient.c ***************************/ diff --git a/src/or/rephist.c b/src/or/rephist.c index 3e4ba672d..44bf94001 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -1321,8 +1321,6 @@ rep_hist_note_bytes_read(size_t num_bytes, time_t when) } /* Some constants */ -/** How long are the intervals for measuring exit stats? */ -#define EXIT_STATS_INTERVAL_SEC (24 * 60 * 60) /** To what multiple should byte numbers be rounded up? */ #define EXIT_STATS_ROUND_UP_BYTES 1024 /** To what multiple should stream counts be rounded up? */ @@ -1344,10 +1342,14 @@ static uint64_t *exit_bytes_written = NULL; /** Number of streams opened in current period by exit port */ static uint32_t *exit_streams = NULL; -/** Set up arrays for exit port statistics. */ -static void -exit_stats_init(void) +/** When does the current exit stats period end? */ +static time_t start_of_exit_stats_interval; + +/** Initialize exit port stats. */ +void +rep_hist_exit_stats_init(time_t now) { + start_of_exit_stats_interval = now; exit_bytes_read = tor_malloc_zero(EXIT_STATS_NUM_PORTS * sizeof(uint64_t)); exit_bytes_written = tor_malloc_zero(EXIT_STATS_NUM_PORTS * @@ -1356,12 +1358,9 @@ exit_stats_init(void) sizeof(uint32_t)); } -/** When does the current exit stats period end? */ -static time_t end_of_current_exit_stats_period = 0; - /** Write exit stats for the current period to disk and reset counters. */ -static void -write_exit_stats(time_t when) +void +rep_hist_exit_stats_write(time_t now) { char t[ISO_TIME_LEN+1]; int r, i, comma; @@ -1372,98 +1371,93 @@ write_exit_stats(time_t when) open_file_t *open_file = NULL; FILE *out = NULL; - log_debug(LD_HIST, "Considering writing exit port statistics to disk.."); - if (!exit_bytes_read) - exit_stats_init(); - while (when > end_of_current_exit_stats_period) { - format_iso_time(t, end_of_current_exit_stats_period); - log_info(LD_HIST, "Writing exit port statistics to disk for period " - "ending at %s.", t); - - if (!open_file) { - out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND, - 0600, &open_file); - if (!out) { - log_warn(LD_HIST, "Couldn't open '%s'.", filename); - goto done; - } - } + format_iso_time(t, now); + log_info(LD_HIST, "Writing exit port statistics to disk for period " + "ending at %s.", t); - /* written yyyy-mm-dd HH:MM:SS (n s) */ - if (fprintf(out, "exit-stats-end %s (%d s)\n", t, - EXIT_STATS_INTERVAL_SEC) < 0) + if (!open_file) { + out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND, + 0600, &open_file); + if (!out) { + log_warn(LD_HIST, "Couldn't open '%s'.", filename); goto done; - - /* Count the total number of bytes, so that we can attribute all - * observations below a threshold of 1 / EXIT_STATS_THRESHOLD_RECIPROCAL - * of all bytes to a special port 'other'. */ - total_bytes = 0; - for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { - total_bytes += exit_bytes_read[i]; - total_bytes += exit_bytes_written[i]; - } - threshold_bytes = total_bytes / EXIT_STATS_THRESHOLD_RECIPROCAL; - - /* kibibytes-(read|written) port=kibibytes,.. */ - for (r = 0; r < 2; r++) { - b = r ? exit_bytes_read : exit_bytes_written; - tor_assert(b); - if (fprintf(out, "%s ", - r ? "exit-kibibytes-read" - : "exit-kibibytes-written") < 0) - goto done; - - comma = 0; - other_bytes = 0; - for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { - if (b[i] > 0) { - if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) { - uint64_t num = round_uint64_to_next_multiple_of(b[i], - EXIT_STATS_ROUND_UP_BYTES); - num /= 1024; - if (fprintf(out, "%s%d="U64_FORMAT, - comma++ ? "," : "", i, - U64_PRINTF_ARG(num)) < 0) - goto done; - } else - other_bytes += b[i]; - } - } - other_bytes = round_uint64_to_next_multiple_of(other_bytes, - EXIT_STATS_ROUND_UP_BYTES); - other_bytes /= 1024; - if (fprintf(out, "%sother="U64_FORMAT"\n", - comma ? "," : "", U64_PRINTF_ARG(other_bytes))<0) - goto done; } - /* streams-opened port=num,.. */ - if (fprintf(out, "exit-streams-opened ") < 0) + } + + /* written yyyy-mm-dd HH:MM:SS (n s) */ + if (fprintf(out, "exit-stats-end %s (%d s)\n", t, + (unsigned) (now - start_of_exit_stats_interval)) < 0) + goto done; + + /* Count the total number of bytes, so that we can attribute all + * observations below a threshold of 1 / EXIT_STATS_THRESHOLD_RECIPROCAL + * of all bytes to a special port 'other'. */ + total_bytes = 0; + for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { + total_bytes += exit_bytes_read[i]; + total_bytes += exit_bytes_written[i]; + } + threshold_bytes = total_bytes / EXIT_STATS_THRESHOLD_RECIPROCAL; + + /* exit-kibibytes-(read|written) port=kibibytes,.. */ + for (r = 0; r < 2; r++) { + b = r ? exit_bytes_read : exit_bytes_written; + tor_assert(b); + if (fprintf(out, "%s ", + r ? "exit-kibibytes-read" + : "exit-kibibytes-written") < 0) goto done; + comma = 0; - other_streams = 0; + other_bytes = 0; for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { - if (exit_streams[i] > 0) { + if (b[i] > 0) { if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) { - uint32_t num = round_uint32_to_next_multiple_of(exit_streams[i], - EXIT_STATS_ROUND_UP_STREAMS); - if (fprintf(out, "%s%d=%u", - comma++ ? "," : "", i, num)<0) + uint64_t num = round_uint64_to_next_multiple_of(b[i], + EXIT_STATS_ROUND_UP_BYTES); + num /= 1024; + if (fprintf(out, "%s%d="U64_FORMAT, + comma++ ? "," : "", i, + U64_PRINTF_ARG(num)) < 0) goto done; } else - other_streams += exit_streams[i]; + other_bytes += b[i]; } } - other_streams = round_uint32_to_next_multiple_of(other_streams, - EXIT_STATS_ROUND_UP_STREAMS); - if (fprintf(out, "%sother=%u\n", - comma ? "," : "", other_streams)<0) + other_bytes = round_uint64_to_next_multiple_of(other_bytes, + EXIT_STATS_ROUND_UP_BYTES); + other_bytes /= 1024; + if (fprintf(out, "%sother="U64_FORMAT"\n", + comma ? "," : "", U64_PRINTF_ARG(other_bytes))<0) goto done; - /* Reset counters */ - memset(exit_bytes_read, 0, sizeof(exit_bytes_read)); - memset(exit_bytes_written, 0, sizeof(exit_bytes_written)); - memset(exit_streams, 0, sizeof(exit_streams)); - end_of_current_exit_stats_period += EXIT_STATS_INTERVAL_SEC; } + /* exit-streams-opened port=num,.. */ + if (fprintf(out, "exit-streams-opened ") < 0) + goto done; + comma = 0; + other_streams = 0; + for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { + if (exit_streams[i] > 0) { + if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) { + uint32_t num = round_uint32_to_next_multiple_of(exit_streams[i], + EXIT_STATS_ROUND_UP_STREAMS); + if (fprintf(out, "%s%d=%u", + comma++ ? "," : "", i, num)<0) + goto done; + } else + other_streams += exit_streams[i]; + } + } + other_streams = round_uint32_to_next_multiple_of(other_streams, + EXIT_STATS_ROUND_UP_STREAMS); + if (fprintf(out, "%sother=%u\n", + comma ? "," : "", other_streams)<0) + goto done; + /* Reset counters */ + memset(exit_bytes_read, 0, sizeof(exit_bytes_read)); + memset(exit_bytes_written, 0, sizeof(exit_bytes_written)); + memset(exit_streams, 0, sizeof(exit_streams)); + start_of_exit_stats_interval = now; if (open_file) finish_writing_to_file(open_file); @@ -1474,59 +1468,36 @@ write_exit_stats(time_t when) tor_free(filename); } -/** Prepare to add an exit stats observation at second <b>when</b> by - * checking whether this observation lies in the current observation - * period; if not, shift the current period forward by one until the - * reported event fits it and write all results in between to disk. */ -static void -add_exit_obs(time_t when) -{ - if (!exit_bytes_read) - exit_stats_init(); - if (when > end_of_current_exit_stats_period) { - if (end_of_current_exit_stats_period) - write_exit_stats(when); - else - end_of_current_exit_stats_period = when + EXIT_STATS_INTERVAL_SEC; - } -} - /** Note that we wrote <b>num_bytes</b> to an exit connection to - * <b>port</b> in second <b>when</b>. */ + * <b>port</b>. */ void -rep_hist_note_exit_bytes_written(uint16_t port, size_t num_bytes, - time_t when) +rep_hist_note_exit_bytes_written(uint16_t port, size_t num_bytes) { if (!get_options()->ExitPortStatistics) return; - add_exit_obs(when); exit_bytes_written[port] += num_bytes; log_debug(LD_HIST, "Written %lu bytes to exit connection to port %d.", (unsigned long)num_bytes, port); } /** Note that we read <b>num_bytes</b> from an exit connection to - * <b>port</b> in second <b>when</b>. */ + * <b>port</b>. */ void -rep_hist_note_exit_bytes_read(uint16_t port, size_t num_bytes, - time_t when) +rep_hist_note_exit_bytes_read(uint16_t port, size_t num_bytes) { if (!get_options()->ExitPortStatistics) return; - add_exit_obs(when); exit_bytes_read[port] += num_bytes; log_debug(LD_HIST, "Read %lu bytes from exit connection to port %d.", (unsigned long)num_bytes, port); } -/** Note that we opened an exit stream to <b>port</b> in second - * <b>when</b>. */ +/** Note that we opened an exit stream to <b>port</b>. */ void -rep_hist_note_exit_stream_opened(uint16_t port, time_t when) +rep_hist_note_exit_stream_opened(uint16_t port) { if (!get_options()->ExitPortStatistics) return; - add_exit_obs(when); exit_streams[port]++; log_debug(LD_HIST, "Opened exit stream to port %d", port); } @@ -2623,7 +2594,14 @@ hs_usage_write_statistics_to_file(time_t now) /*** cell statistics ***/ /** Start of the current buffer stats interval. */ -time_t start_of_buffer_stats_interval; +static time_t start_of_buffer_stats_interval; + +/** Initialize buffer stats. */ +void +rep_hist_buffer_stats_init(time_t now) +{ + start_of_buffer_stats_interval = now; +} typedef struct circ_buffer_stats_t { uint32_t processed_cells; @@ -2639,7 +2617,7 @@ smartlist_t *circuits_for_buffer_stats = NULL; * <b>end_of_interval</b> and reset cell counters in case the circuit * remains open in the next measurement interval. */ void -add_circ_to_buffer_stats(circuit_t *circ, time_t end_of_interval) +rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval) { circ_buffer_stats_t *stat; time_t start_of_interval; @@ -2687,9 +2665,8 @@ _buffer_stats_compare_entries(const void **_a, const void **_b) /** Append buffer statistics to local file. */ void -dump_buffer_stats(void) +rep_hist_buffer_stats_write(time_t now) { - time_t now = time(NULL); char *filename; char written[ISO_TIME_LEN+1]; open_file_t *open_file = NULL; @@ -2704,7 +2681,7 @@ dump_buffer_stats(void) circuit_t *circ; /* add current circuits to stats */ for (circ = _circuit_get_global_list(); circ; circ = circ->next) - add_circ_to_buffer_stats(circ, now); + rep_hist_buffer_stats_add_circ(circ, now); /* calculate deciles */ memset(processed_cells, 0, SHARES * sizeof(int)); memset(circs_in_share, 0, SHARES * sizeof(int)); @@ -2736,7 +2713,7 @@ dump_buffer_stats(void) goto done; format_iso_time(written, now); if (fprintf(out, "cell-stats-end %s (%d s)\n", written, - DUMP_BUFFER_STATS_INTERVAL) < 0) + (unsigned) (now - start_of_buffer_stats_interval)) < 0) goto done; for (i = 0; i < SHARES; i++) { tor_snprintf(buf, sizeof(buf), "%d", !circs_in_share[i] ? 0 : |