[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r9044: Make bandwidth accounting information get stored to the stat (in tor/trunk: . src/or)



Author: nickm
Date: 2006-12-07 13:57:37 -0500 (Thu, 07 Dec 2006)
New Revision: 9044

Modified:
   tor/trunk/
   tor/trunk/ChangeLog
   tor/trunk/src/or/hibernate.c
   tor/trunk/src/or/main.c
   tor/trunk/src/or/or.h
Log:
 r11462@Kushana:  nickm | 2006-12-07 13:42:21 -0500
 Make bandwidth accounting information get stored to the state file as well as bw_accounting.  Read from the state file if it is more recent than bw_accounting, or if bw_accounting is not there.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r11462] on c95137ef-5f19-0410-b913-86e773d04f59

Modified: tor/trunk/ChangeLog
===================================================================
--- tor/trunk/ChangeLog	2006-12-07 18:57:29 UTC (rev 9043)
+++ tor/trunk/ChangeLog	2006-12-07 18:57:37 UTC (rev 9044)
@@ -1,4 +1,9 @@
 Changes in version 0.1.2.5-xxxx - 200?-??-??
+  o Minor features
+    - Start using the state file to store bandwidth accounting data:
+      the bw_accounting file is now obsolete.  We'll keep generating it
+      for a while for people who are still using 0.1.2.4-alpha.
+
   o Minor bugfixes;
     - Fix a bug when a PF socket is first used.  (Patch from Fabian
       Keil.)

Modified: tor/trunk/src/or/hibernate.c
===================================================================
--- tor/trunk/src/or/hibernate.c	2006-12-07 18:57:29 UTC (rev 9043)
+++ tor/trunk/src/or/hibernate.c	2006-12-07 18:57:37 UTC (rev 9044)
@@ -420,12 +420,8 @@
     configure_accounting(now);
   }
   if (time_to_record_bandwidth_usage(now)) {
-    if (accounting_record_bandwidth_usage(now)) {
-      log_err(LD_FS, "Couldn't record bandwidth usage to disk; exiting.");
-      /* This can fail when we're out of fd's, causing a crash.
-       * The current answer is to reserve 32 more than we need, in
-       * set_max_file_descriptors(). */
-      exit(1);
+    if (accounting_record_bandwidth_usage(now, get_or_state())) {
+      log_warn(LD_FS, "Couldn't record bandwidth usage to disk.");
     }
   }
 }
@@ -538,7 +534,7 @@
 /** Save all our bandwidth tracking information to disk. Return 0 on
  * success, -1 on failure. */
 int
-accounting_record_bandwidth_usage(time_t now)
+accounting_record_bandwidth_usage(time_t now, or_state_t *state)
 {
   char buf[128];
   char fname[512];
@@ -546,9 +542,12 @@
   char time2[ISO_TIME_LEN+1];
   char *cp = buf;
   time_t tmp;
-  /* Format is:
-     Version\nTime\nTime\nRead\nWrite\nSeconds\nExpected-Rate\n */
+  int r;
 
+  /* First, update bw_accounting. Until 0.1.2.5-x, this was the only place
+   * we stored this information. The format is:
+   * Version\nTime\nTime\nRead\nWrite\nSeconds\nExpected-Rate\n */
+
   format_iso_time(time1, interval_start_time);
   format_iso_time(time2, now);
   /* now check to see if they're valid times -- if they're not,
@@ -568,8 +567,17 @@
                (unsigned long)expected_bandwidth_usage);
   tor_snprintf(fname, sizeof(fname), "%s/bw_accounting",
                get_options()->DataDirectory);
+  r = write_str_to_file(fname, buf, 0);
 
-  return write_str_to_file(fname, buf, 0);
+  /* Now update the state */
+  state->AccountingIntervalStart = interval_start_time;
+  state->AccountingBytesReadInInterval = n_bytes_read_in_interval;
+  state->AccountingBytesWrittenInInterval = n_bytes_written_in_interval;
+  state->AccountingSecondsActive = n_seconds_active_in_interval;
+  state->AccountingExpectedUsage = expected_bandwidth_usage;
+  state->dirty = 1;
+
+  return r;
 }
 
 /** Read stored accounting information from disk. Return 0 on success;
@@ -582,60 +590,80 @@
   time_t t1, t2;
   uint64_t n_read, n_written;
   uint32_t expected_bw, n_seconds;
-  smartlist_t *elts;
-  int ok;
+  smartlist_t *elts = NULL;
+  int ok, use_state=0, r=-1;
+  or_state_t *state = get_or_state();
 
   tor_snprintf(fname, sizeof(fname), "%s/bw_accounting",
                get_options()->DataDirectory);
-  if (!(s = read_file_to_str(fname, 0, NULL))) {
-    return 0;
+  elts = smartlist_create();
+  if ((s = read_file_to_str(fname, 0, NULL)) == NULL) {
+    /* We have an old-format bw_accounting file. */
+    use_state = 1;
   }
-  elts = smartlist_create();
-  smartlist_split_string(elts, s, "\n", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK,0);
-  tor_free(s);
+  if (!use_state) {
+    smartlist_split_string(elts, s, "\n",
+                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK,0);
+    tor_free(s);
 
-  if (smartlist_len(elts)<1 ||
-      atoi(smartlist_get(elts,0)) != BW_ACCOUNTING_VERSION) {
-    log_warn(LD_ACCT, "Unrecognized bw_accounting file version: %s",
-             (const char*)smartlist_get(elts,0));
-    goto err;
+    if (smartlist_len(elts)<1 ||
+        atoi(smartlist_get(elts,0)) != BW_ACCOUNTING_VERSION) {
+      log_warn(LD_ACCT, "Unrecognized bw_accounting file version: %s",
+               (const char*)smartlist_get(elts,0));
+      use_state = 1;
+    }
   }
-  if (smartlist_len(elts) < 7) {
+  if (!use_state && smartlist_len(elts) < 7) {
     log_warn(LD_ACCT, "Corrupted bw_accounting file: %d lines",
              smartlist_len(elts));
-    goto err;
+    use_state = 1;
   }
+  if (!use_state && parse_iso_time(smartlist_get(elts,2), &t2)) {
+    log_warn(LD_ACCT, "Error parsing bandwidth usage last-written time");
+    use_state = 1;
+  }
+  if (use_state || t2 <= state->LastWritten) {
+    /* Okay; it looks like the state file is more up-to-date than the
+     * bw_accounting file, or the bw_accounting file is nonexistant,
+     * or the bw_accounting file is corrupt.
+     */
+    log_info(LD_ACCT, "Reading bandwdith accounting data from state file");
+    n_bytes_read_in_interval = state->AccountingBytesReadInInterval;
+    n_bytes_written_in_interval = state->AccountingBytesWrittenInInterval;
+    n_seconds_active_in_interval = state->AccountingSecondsActive;
+    interval_start_time = state->AccountingIntervalStart;
+    expected_bandwidth_usage = state->AccountingExpectedUsage;
+    r = 0;
+    goto done;
+  }
+
   if (parse_iso_time(smartlist_get(elts,1), &t1)) {
     log_warn(LD_ACCT, "Error parsing bandwidth usage start time.");
-    goto err;
+    goto done;
   }
-  if (parse_iso_time(smartlist_get(elts,2), &t2)) {
-    log_warn(LD_ACCT, "Error parsing bandwidth usage last-written time");
-    goto err;
-  }
   n_read = tor_parse_uint64(smartlist_get(elts,3), 10, 0, UINT64_MAX,
                             &ok, NULL);
   if (!ok) {
     log_warn(LD_ACCT, "Error parsing number of bytes read");
-    goto err;
+    goto done;
   }
   n_written = tor_parse_uint64(smartlist_get(elts,4), 10, 0, UINT64_MAX,
                                &ok, NULL);
   if (!ok) {
     log_warn(LD_ACCT, "Error parsing number of bytes written");
-    goto err;
+    goto done;
   }
   n_seconds = (uint32_t)tor_parse_ulong(smartlist_get(elts,5), 10,0,ULONG_MAX,
                                         &ok, NULL);
   if (!ok) {
     log_warn(LD_ACCT, "Error parsing number of seconds live");
-    goto err;
+    goto done;
   }
   expected_bw =(uint32_t)tor_parse_ulong(smartlist_get(elts,6), 10,0,ULONG_MAX,
                                         &ok, NULL);
   if (!ok) {
     log_warn(LD_ACCT, "Error parsing expected bandwidth");
-    goto err;
+    goto done;
   }
 
   n_bytes_read_in_interval = n_read;
@@ -656,14 +684,14 @@
        (unsigned long)((uint64_t)expected_bandwidth_usage*1024/60),
        U64_PRINTF_ARG(n_bytes_read_in_interval),
        U64_PRINTF_ARG(n_bytes_written_in_interval));
-  SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
-  smartlist_free(elts);
 
-  return 0;
- err:
-  SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
-  smartlist_free(elts);
-  return -1;
+  r = 0;
+ done:
+  if (elts) {
+    SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
+    smartlist_free(elts);
+  }
+  return r;
 }
 
 /** Return true iff we have sent/received all the bytes we are willing
@@ -731,7 +759,7 @@
   }
 
   hibernate_state = new_state;
-  accounting_record_bandwidth_usage(now);
+  accounting_record_bandwidth_usage(now, get_or_state());
 }
 
 /** Called when we've been hibernating and our timeout is reached. */
@@ -798,7 +826,7 @@
       connection_mark_for_close(conn);
   }
 
-  accounting_record_bandwidth_usage(now);
+  accounting_record_bandwidth_usage(now, get_or_state());
 }
 
 /** Called when hibernate_end_time has arrived. */

Modified: tor/trunk/src/or/main.c
===================================================================
--- tor/trunk/src/or/main.c	2006-12-07 18:57:29 UTC (rev 9043)
+++ tor/trunk/src/or/main.c	2006-12-07 18:57:37 UTC (rev 9044)
@@ -1066,7 +1066,7 @@
 
   log_notice(LD_GENERAL,"Received reload signal (hup). Reloading config.");
   if (accounting_is_enabled(options))
-    accounting_record_bandwidth_usage(time(NULL));
+    accounting_record_bandwidth_usage(time(NULL), get_or_state());
 
   router_reset_warnings();
   routerlist_reset_warnings();
@@ -1594,7 +1594,7 @@
     if (options->PidFile)
       unlink(options->PidFile);
     if (accounting_is_enabled(options))
-      accounting_record_bandwidth_usage(time(NULL));
+      accounting_record_bandwidth_usage(time(NULL), get_or_state());
     or_state_save();
   }
   tor_free_all(0); /* move tor_free_all back into the ifdef below later. XXX*/

Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h	2006-12-07 18:57:29 UTC (rev 9043)
+++ tor/trunk/src/or/or.h	2006-12-07 18:57:37 UTC (rev 9044)
@@ -1655,9 +1655,10 @@
 /** Persistent state for an onion router, as saved to disk. */
 typedef struct {
   uint32_t _magic;
+  /** True iff this state has been changed since it was last read/written
+   * to the disk. */
   int dirty;
 
-  /* XXXX These options aren't actually attached to anything yet. */
   time_t LastWritten;
   time_t AccountingIntervalStart;
   uint64_t AccountingBytesReadInInterval;
@@ -2261,7 +2262,7 @@
 void configure_accounting(time_t now);
 void accounting_run_housekeeping(time_t now);
 void accounting_add_bytes(size_t n_read, size_t n_written, int seconds);
-int accounting_record_bandwidth_usage(time_t now);
+int accounting_record_bandwidth_usage(time_t now, or_state_t *state);
 void hibernate_begin_shutdown(void);
 int we_are_hibernating(void);
 void consider_hibernation(time_t now);