[tor-commits] [tor/master] Separate generation of an entry-stats string from writing it to disk.

nickm at torproject.org nickm at torproject.org
Thu Aug 4 19:47:09 UTC 2011


commit 88083463cb895df0286210830e14c635c9e026a5
Author: Karsten Loesing <karsten.loesing at 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);
 }





More information about the tor-commits mailing list