Separate generation of a buffer-stats string from writing it to disk.

The new rep_hist_format_buffer_stats() generates a buffer-stats string
that rep_hist_buffer_stats_write() writes to disk.  All the state
changing (e.g., resetting the buffer-stats history and initializing
the next measurement interval) takes place in
rep_hist_buffer_stats_write().  That allows us to finally test the
buffer-stats code better.
This commit is contained in:
Karsten Loesing 2011-08-03 13:26:49 +02:00
parent 95ebd01e62
commit 07dc46e7fc
2 changed files with 72 additions and 51 deletions

View File

@ -2420,42 +2420,41 @@ _buffer_stats_compare_entries(const void **_a, const void **_b)
void void
rep_hist_buffer_stats_term(void) rep_hist_buffer_stats_term(void)
{ {
start_of_buffer_stats_interval = 0; rep_hist_reset_buffer_stats(0);
}
/** Clear history of circuit statistics and set the measurement interval
* start to <b>now</b>. */
void
rep_hist_reset_buffer_stats(time_t now)
{
if (!circuits_for_buffer_stats) if (!circuits_for_buffer_stats)
circuits_for_buffer_stats = smartlist_create(); circuits_for_buffer_stats = smartlist_create();
SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *, SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *,
stat, tor_free(stat)); stat, tor_free(stat));
smartlist_clear(circuits_for_buffer_stats); smartlist_clear(circuits_for_buffer_stats);
start_of_buffer_stats_interval = now;
} }
/** Write buffer statistics to $DATADIR/stats/buffer-stats and return when /** Return a newly allocated string containing the buffer statistics until
* we would next want to write exit stats. */ * <b>now</b>, or NULL if we're not collecting buffer stats. */
time_t char *
rep_hist_buffer_stats_write(time_t now) rep_hist_format_buffer_stats(time_t now)
{ {
char *statsdir = NULL, *filename = NULL;
open_file_t *open_file = NULL;
FILE *out;
#define SHARES 10 #define SHARES 10
int processed_cells[SHARES], circs_in_share[SHARES], int processed_cells[SHARES], circs_in_share[SHARES],
number_of_circuits, i; number_of_circuits, i;
double queued_cells[SHARES], time_in_queue[SHARES]; double queued_cells[SHARES], time_in_queue[SHARES];
char *buf = NULL; char *buf = NULL;
circuit_t *circ;
smartlist_t *processed_cells_strings, *queued_cells_strings, smartlist_t *processed_cells_strings, *queued_cells_strings,
*time_in_queue_strings; *time_in_queue_strings;
char *processed_cells_string, *queued_cells_string, char *processed_cells_string, *queued_cells_string,
*time_in_queue_string; *time_in_queue_string;
char t[ISO_TIME_LEN+1]; char t[ISO_TIME_LEN+1];
char *result;
if (!start_of_buffer_stats_interval) if (!start_of_buffer_stats_interval)
return 0; /* Not initialized. */ return NULL; /* Not initialized. */
if (start_of_buffer_stats_interval + WRITE_STATS_INTERVAL > now)
goto done; /* Not ready to write */
/* add current circuits to stats */
for (circ = _circuit_get_global_list(); circ; circ = circ->next)
rep_hist_buffer_stats_add_circ(circ, now);
/* Calculate deciles if we saw at least one circuit. */ /* Calculate deciles if we saw at least one circuit. */
memset(processed_cells, 0, SHARES * sizeof(int)); memset(processed_cells, 0, SHARES * sizeof(int));
@ -2481,11 +2480,6 @@ rep_hist_buffer_stats_write(time_t now)
SMARTLIST_FOREACH_END(stat); SMARTLIST_FOREACH_END(stat);
} }
/* clear buffer stats history */
SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *,
stat, tor_free(stat));
smartlist_clear(circuits_for_buffer_stats);
/* Write deciles to strings. */ /* Write deciles to strings. */
processed_cells_strings = smartlist_create(); processed_cells_strings = smartlist_create();
queued_cells_strings = smartlist_create(); queued_cells_strings = smartlist_create();
@ -2520,41 +2514,66 @@ rep_hist_buffer_stats_write(time_t now)
smartlist_free(queued_cells_strings); smartlist_free(queued_cells_strings);
smartlist_free(time_in_queue_strings); smartlist_free(time_in_queue_strings);
/* Write everything to disk. */ /* Put everything together. */
statsdir = get_datadir_fname("stats");
if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0)
goto done;
filename = get_datadir_fname2("stats", "buffer-stats");
out = start_writing_to_stdio_file(filename, OPEN_FLAGS_REPLACE | O_TEXT,
0600, &open_file);
if (!out)
goto done;
format_iso_time(t, now); format_iso_time(t, now);
if (fprintf(out, "cell-stats-end %s (%d s)\n", t, tor_asprintf(&result, "cell-stats-end %s (%d s)\n"
(unsigned) (now - start_of_buffer_stats_interval)) < 0) "cell-processed-cells %s\n"
goto done; "cell-queued-cells %s\n"
if (fprintf(out, "cell-processed-cells %s\n", processed_cells_string) "cell-time-in-queue %s\n"
< 0) "cell-circuits-per-decile %d\n",
goto done; t, (unsigned) (now - start_of_buffer_stats_interval),
if (fprintf(out, "cell-queued-cells %s\n", queued_cells_string) < 0) processed_cells_string,
goto done; queued_cells_string,
if (fprintf(out, "cell-time-in-queue %s\n", time_in_queue_string) < 0) time_in_queue_string,
goto done; (number_of_circuits + SHARES - 1) / SHARES);
if (fprintf(out, "cell-circuits-per-decile %d\n",
(number_of_circuits + SHARES - 1) / SHARES) < 0)
goto done;
finish_writing_to_file(open_file);
open_file = NULL;
start_of_buffer_stats_interval = now;
done:
if (open_file)
abort_writing_to_file(open_file);
tor_free(filename);
tor_free(statsdir);
tor_free(processed_cells_string); tor_free(processed_cells_string);
tor_free(queued_cells_string); tor_free(queued_cells_string);
tor_free(time_in_queue_string); tor_free(time_in_queue_string);
return result;
#undef SHARES #undef SHARES
}
/** If 24 hours have passed since the beginning of the current buffer
* stats period, write buffer stats to $DATADIR/stats/buffer-stats
* (possibly overwriting an existing file) and reset counters. Return
* when we would next want to write buffer stats or 0 if we never want to
* write. */
time_t
rep_hist_buffer_stats_write(time_t now)
{
circuit_t *circ;
char *statsdir = NULL, *filename = NULL, *str = NULL;
if (!start_of_buffer_stats_interval)
return 0; /* Not initialized. */
if (start_of_buffer_stats_interval + WRITE_STATS_INTERVAL > now)
goto done; /* Not ready to write */
/* Add open circuits to the history. */
for (circ = _circuit_get_global_list(); circ; circ = circ->next) {
rep_hist_buffer_stats_add_circ(circ, now);
}
/* Generate history string. */
str = rep_hist_format_buffer_stats(now);
/* Reset both buffer history and counters of open circuits. */
rep_hist_reset_buffer_stats(now);
/* Try to write to disk. */
statsdir = get_datadir_fname("stats");
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", "buffer-stats");
if (write_str_to_file(filename, str, 0) < 0)
log_warn(LD_HIST, "Unable to write buffer stats to disk!");
done:
tor_free(str);
tor_free(filename);
tor_free(statsdir);
return start_of_buffer_stats_interval + WRITE_STATS_INTERVAL; return start_of_buffer_stats_interval + WRITE_STATS_INTERVAL;
} }

View File

@ -77,6 +77,8 @@ void rep_hist_buffer_stats_add_circ(circuit_t *circ,
time_t end_of_interval); time_t end_of_interval);
time_t rep_hist_buffer_stats_write(time_t now); time_t rep_hist_buffer_stats_write(time_t now);
void rep_hist_buffer_stats_term(void); void rep_hist_buffer_stats_term(void);
char *rep_hist_format_buffer_stats(time_t now);
void rep_hist_reset_buffer_stats(time_t now);
void rep_hist_conn_stats_init(time_t now); void rep_hist_conn_stats_init(time_t now);
void rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read, void rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read,