summaryrefslogtreecommitdiff
path: root/src/or/hibernate.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2006-12-07 18:57:37 +0000
committerNick Mathewson <nickm@torproject.org>2006-12-07 18:57:37 +0000
commit6c8075d8a05b75496b236118e78de771721c9ae4 (patch)
treeebf0df749b32627bc40e6096373a466c49ffc9d5 /src/or/hibernate.c
parent63e4cfbeb609f88bdcc622b63cc74558a6e0e235 (diff)
downloadtor-6c8075d8a05b75496b236118e78de771721c9ae4.tar.gz
tor-6c8075d8a05b75496b236118e78de771721c9ae4.zip
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. svn:r9044
Diffstat (limited to 'src/or/hibernate.c')
-rw-r--r--src/or/hibernate.c114
1 files changed, 71 insertions, 43 deletions
diff --git a/src/or/hibernate.c b/src/or/hibernate.c
index 2b4657d4a1..79c51c7184 100644
--- a/src/or/hibernate.c
+++ b/src/or/hibernate.c
@@ -420,12 +420,8 @@ accounting_run_housekeeping(time_t now)
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 @@ accounting_set_wakeup_time(void)
/** 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,8 +542,11 @@ accounting_record_bandwidth_usage(time_t now)
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);
@@ -568,8 +567,17 @@ accounting_record_bandwidth_usage(time_t now)
(unsigned long)expected_bandwidth_usage);
tor_snprintf(fname, sizeof(fname), "%s/bw_accounting",
get_options()->DataDirectory);
+ r = 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 write_str_to_file(fname, buf, 0);
+ return r;
}
/** Read stored accounting information from disk. Return 0 on success;
@@ -582,60 +590,80 @@ read_bandwidth_usage(void)
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();
- 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 ((s = read_file_to_str(fname, 0, NULL)) == NULL) {
+ /* We have an old-format bw_accounting file. */
+ use_state = 1;
+ }
+ 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));
+ 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;
- }
- if (parse_iso_time(smartlist_get(elts,2), &t2)) {
- log_warn(LD_ACCT, "Error parsing bandwidth usage last-written time");
- goto err;
+ goto done;
}
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 @@ read_bandwidth_usage(void)
(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_begin(int new_state, time_t now)
}
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 @@ hibernate_go_dormant(time_t now)
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. */