commit 88083463cb895df0286210830e14c635c9e026a5 Author: Karsten Loesing karsten.loesing@gmx.net Date: Thu Aug 4 14:14:01 2011 +0200
Separate generation of an entry-stats string from writing it to disk.
This commit is similar to the previous two commits for dirreq-stats, but for entry-stats. --- src/or/geoip.c | 75 +++++++++++++++++++++++++++++++++++------------------- src/or/geoip.h | 2 + src/test/test.c | 49 +++++++++++++++++++++++++++++++++++- 3 files changed, 98 insertions(+), 28 deletions(-)
diff --git a/src/or/geoip.c b/src/or/geoip.c index acc00a8..e525b2a 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -1332,25 +1332,51 @@ geoip_entry_stats_init(time_t now) start_of_entry_stats_interval = now; }
+/** Reset counters for entry stats. */ +void +geoip_reset_entry_stats(time_t now) +{ + client_history_clear(); + start_of_entry_stats_interval = now; +} + /** Stop collecting entry stats in a way that we can re-start doing so in * geoip_entry_stats_init(). */ void geoip_entry_stats_term(void) { - client_history_clear(); - start_of_entry_stats_interval = 0; + geoip_reset_entry_stats(0); +} + +/** Return a newly allocated string containing the entry statistics + * until <b>now</b>, or NULL if we're not collecting entry stats. */ +char * +geoip_format_entry_stats(time_t now) +{ + char t[ISO_TIME_LEN+1]; + char *data = NULL; + char *result; + + if (!start_of_entry_stats_interval) + return NULL; /* Not initialized. */ + + data = geoip_get_client_history(GEOIP_CLIENT_CONNECT); + format_iso_time(t, now); + tor_asprintf(&result, "entry-stats-end %s (%u s)\nentry-ips %s\n", + t, (unsigned) (now - start_of_entry_stats_interval), + data ? data : ""); + tor_free(data); + return result; }
-/** Write entry statistics to $DATADIR/stats/entry-stats and return time - * when we would next want to write. */ +/** If 24 hours have passed since the beginning of the current entry stats + * period, write entry stats to $DATADIR/stats/entry-stats (possibly + * overwriting an existing file) and reset counters. Return when we would + * next want to write entry stats or 0 if we never want to write. */ time_t geoip_entry_stats_write(time_t now) { - char *statsdir = NULL, *filename = NULL; - char *data = NULL; - char written[ISO_TIME_LEN+1]; - open_file_t *open_file = NULL; - FILE *out; + char *statsdir = NULL, *filename = NULL, *str = NULL;
if (!start_of_entry_stats_interval) return 0; /* Not initialized. */ @@ -1360,31 +1386,26 @@ geoip_entry_stats_write(time_t now) /* Discard all items in the client history that are too old. */ geoip_remove_old_clients(start_of_entry_stats_interval);
+ /* Generate history string .*/ + str = geoip_format_entry_stats(now); + + /* Write entry-stats string to disk. */ statsdir = get_datadir_fname("stats"); - if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) + if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) { + log_warn(LD_HIST, "Unable to create stats/ directory!"); goto done; + } filename = get_datadir_fname2("stats", "entry-stats"); - data = geoip_get_client_history(GEOIP_CLIENT_CONNECT); - format_iso_time(written, now); - out = start_writing_to_stdio_file(filename, OPEN_FLAGS_REPLACE | O_TEXT, - 0600, &open_file); - if (!out) - goto done; - 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; + if (write_str_to_file(filename, str, 0) < 0) + log_warn(LD_HIST, "Unable to write entry statistics to disk!");
- start_of_entry_stats_interval = now; + /* Reset measurement interval start. */ + geoip_reset_entry_stats(now);
- finish_writing_to_file(open_file); - open_file = NULL; done: - if (open_file) - abort_writing_to_file(open_file); - tor_free(filename); tor_free(statsdir); - tor_free(data); + tor_free(filename); + tor_free(str); return start_of_entry_stats_interval + WRITE_STATS_INTERVAL; }
diff --git a/src/or/geoip.h b/src/or/geoip.h index 3472ee2..3372260 100644 --- a/src/or/geoip.h +++ b/src/or/geoip.h @@ -50,6 +50,8 @@ void geoip_dirreq_stats_term(void); void geoip_entry_stats_init(time_t now); time_t geoip_entry_stats_write(time_t now); void geoip_entry_stats_term(void); +void geoip_reset_entry_stats(time_t now); +char *geoip_format_entry_stats(time_t now); void geoip_bridge_stats_init(time_t now); time_t geoip_bridge_stats_write(time_t now); void geoip_bridge_stats_term(void); diff --git a/src/test/test.c b/src/test/test.c index 9e34984..fe8146a 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1538,7 +1538,13 @@ test_geoip(void) "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n" "dirreq-v3-tunneled-dl complete=0,timeout=0,running=4\n" - "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n"; + "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n", + *entry_stats_1 = + "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "entry-ips ab=8\n", + *entry_stats_2 = + "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "entry-ips \n";
/* Populate the DB a bit. Add these in order, since we can't do the final * 'sort' step. These aren't very good IP addresses, but they're perfectly @@ -1590,6 +1596,7 @@ test_geoip(void)
/* Stop being a bridge and start being a directory mirror that gathers * directory request statistics. */ + geoip_bridge_stats_term(); get_options_mutable()->BridgeRelay = 0; get_options_mutable()->BridgeRecordUsageByCountry = 0; get_options_mutable()->DirReqStatistics = 1; @@ -1637,6 +1644,46 @@ test_geoip(void) s = geoip_format_dirreq_stats(now + 86400); test_streq(dirreq_stats_4, s);
+ /* Stop collecting directory request statistics and start gathering + * entry stats. */ + geoip_dirreq_stats_term(); + get_options_mutable()->DirReqStatistics = 0; + get_options_mutable()->EntryStatistics = 1; + + /* Start testing entry statistics by making sure that we don't collect + * anything without initializing entry stats. */ + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 100, now); + s = geoip_format_entry_stats(now + 86400); + test_assert(!s); + + /* Initialize stats, note one connecting client, and generate the + * entry-stats history string. */ + geoip_entry_stats_init(now); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 100, now); + s = geoip_format_entry_stats(now + 86400); + test_streq(entry_stats_1, s); + tor_free(s); + + /* Stop collecting stats, add another connecting client, and ensure we + * don't generate a history string. */ + geoip_entry_stats_term(); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 101, now); + s = geoip_format_entry_stats(now + 86400); + test_assert(!s); + + /* Re-start stats, add a connecting client, reset stats, and make sure + * that we get an all empty history string. */ + geoip_entry_stats_init(now); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 100, now); + geoip_reset_entry_stats(now); + s = geoip_format_entry_stats(now + 86400); + test_streq(entry_stats_2, s); + tor_free(s); + + /* Stop collecting entry statistics. */ + geoip_entry_stats_term(); + get_options_mutable()->EntryStatistics = 0; + done: tor_free(s); }