mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
Keep bandwidth history accross restarts/crashes
svn:r5637
This commit is contained in:
parent
f7e82babcb
commit
4bd65f0f98
@ -229,6 +229,13 @@ static config_var_t _state_vars[] = {
|
||||
VAR("HelperNodes", LINELIST_V, HelperNodes, NULL),
|
||||
VAR("LastWritten", ISOTIME, LastWritten, NULL),
|
||||
|
||||
VAR("BWHistoryReadEnds", ISOTIME, BWHistoryReadEnds, NULL),
|
||||
VAR("BWHistoryReadInterval", UINT, BWHistoryReadInterval, NULL),
|
||||
VAR("BWHistoryReadValues", CSV, BWHistoryReadValues, NULL),
|
||||
VAR("BWHistoryWriteEnds", ISOTIME, BWHistoryWriteEnds, NULL),
|
||||
VAR("BWHistoryWriteInterval", UINT, BWHistoryWriteInterval, NULL),
|
||||
VAR("BWHistoryWriteValues", CSV, BWHistoryWriteValues, NULL),
|
||||
|
||||
{ NULL, CONFIG_TYPE_OBSOLETE, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
@ -3516,7 +3523,8 @@ or_state_set(or_state_t *new_state)
|
||||
global_state = new_state;
|
||||
if (helper_nodes_parse_state(global_state, 1, &err)<0)
|
||||
warn(LD_GENERAL,"Unparseable helper nodes state: %s",err);
|
||||
|
||||
if (rep_hist_load_state(global_state, &err)<0)
|
||||
warn(LD_GENERAL,"Unparseable bandwidth history state: %s",err);
|
||||
}
|
||||
|
||||
/* DOCDOC */
|
||||
@ -3589,6 +3597,7 @@ or_state_save(void)
|
||||
char *fname;
|
||||
|
||||
helper_nodes_update_state(global_state);
|
||||
rep_hist_update_state(global_state);
|
||||
|
||||
if (!global_state->dirty)
|
||||
return 0;
|
||||
|
@ -779,6 +779,9 @@ run_scheduled_events(time_t now)
|
||||
* and the rend cache. */
|
||||
rep_history_clean(now - options->RephistTrackTime);
|
||||
rend_cache_clean();
|
||||
/* And while we are at it, save the state with bandwidth history
|
||||
* and more. */
|
||||
or_state_save();
|
||||
}
|
||||
|
||||
/* Caches need to fetch running_routers; directory clients don't. */
|
||||
@ -1494,6 +1497,7 @@ tor_cleanup(void)
|
||||
unlink(options->PidFile);
|
||||
if (accounting_is_enabled(options))
|
||||
accounting_record_bandwidth_usage(time(NULL));
|
||||
or_state_save();
|
||||
tor_free_all(0); /* move tor_free_all back into the ifdef below later. XXX*/
|
||||
crypto_global_cleanup();
|
||||
#ifdef USE_DMALLOC
|
||||
|
10
src/or/or.h
10
src/or/or.h
@ -1369,6 +1369,13 @@ typedef struct {
|
||||
uint64_t AccountingExpectedUsage;
|
||||
|
||||
config_line_t *HelperNodes;
|
||||
|
||||
time_t BWHistoryReadEnds;
|
||||
int BWHistoryReadInterval;
|
||||
smartlist_t *BWHistoryReadValues;
|
||||
time_t BWHistoryWriteEnds;
|
||||
int BWHistoryWriteInterval;
|
||||
smartlist_t *BWHistoryWriteValues;
|
||||
} or_state_t;
|
||||
|
||||
#define MAX_SOCKS_REPLY_LEN 1024
|
||||
@ -2024,6 +2031,9 @@ void rep_hist_note_used_internal(time_t now, int need_uptime,
|
||||
int rep_hist_get_predicted_internal(time_t now, int *need_uptime,
|
||||
int *need_capacity);
|
||||
|
||||
int rep_hist_update_state(or_state_t *state);
|
||||
int rep_hist_load_state(or_state_t *state, const char **err);
|
||||
|
||||
void rep_hist_free_all(void);
|
||||
|
||||
/********************************* rendclient.c ***************************/
|
||||
|
161
src/or/rephist.c
161
src/or/rephist.c
@ -579,6 +579,41 @@ rep_hist_bandwidth_assess(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the bandwidth history of b (either read_array or write_array)
|
||||
* into the buffer pointed to by buf. The format is simply comma
|
||||
* separated numbers, from oldest to newest.
|
||||
*
|
||||
* It returns the number of bytes written.
|
||||
*/
|
||||
size_t
|
||||
rep_hist_fill_bandwidth_history(char *buf, size_t len, bw_array_t *b)
|
||||
{
|
||||
char *cp = buf;
|
||||
int i, n;
|
||||
|
||||
if (b->num_maxes_set <= b->next_max_idx) {
|
||||
/* We haven't been through the circular array yet; time starts at i=0.*/
|
||||
i = 0;
|
||||
} else {
|
||||
/* We've been around the array at least once. The next i to be
|
||||
overwritten is the oldest. */
|
||||
i = b->next_max_idx;
|
||||
}
|
||||
|
||||
for (n=0; n<b->num_maxes_set; ++n,++i) {
|
||||
while (i >= NUM_TOTALS) i -= NUM_TOTALS;
|
||||
if (n==(b->num_maxes_set-1))
|
||||
tor_snprintf(cp, len-(cp-buf), U64_FORMAT,
|
||||
U64_PRINTF_ARG(b->totals[i]));
|
||||
else
|
||||
tor_snprintf(cp, len-(cp-buf), U64_FORMAT",",
|
||||
U64_PRINTF_ARG(b->totals[i]));
|
||||
cp += strlen(cp);
|
||||
}
|
||||
return cp-buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate and return lines for representing this server's bandwidth
|
||||
* history in its descriptor.
|
||||
@ -588,7 +623,7 @@ rep_hist_get_bandwidth_lines(void)
|
||||
{
|
||||
char *buf, *cp;
|
||||
char t[ISO_TIME_LEN+1];
|
||||
int r, i, n;
|
||||
int r;
|
||||
bw_array_t *b;
|
||||
size_t len;
|
||||
|
||||
@ -604,31 +639,117 @@ rep_hist_get_bandwidth_lines(void)
|
||||
r ? "read-history" : "write-history", t,
|
||||
NUM_SECS_BW_SUM_INTERVAL);
|
||||
cp += strlen(cp);
|
||||
|
||||
if (b->num_maxes_set <= b->next_max_idx)
|
||||
/* We haven't been through the circular array yet; time starts at i=0.*/
|
||||
i = 0;
|
||||
else
|
||||
/* We've been around the array at least once. The next i to be
|
||||
overwritten is the oldest. */
|
||||
i = b->next_max_idx;
|
||||
|
||||
for (n=0; n<b->num_maxes_set; ++n,++i) {
|
||||
while (i >= NUM_TOTALS) i -= NUM_TOTALS;
|
||||
if (n==(b->num_maxes_set-1))
|
||||
tor_snprintf(cp, len-(cp-buf), U64_FORMAT,
|
||||
U64_PRINTF_ARG(b->totals[i]));
|
||||
else
|
||||
tor_snprintf(cp, len-(cp-buf), U64_FORMAT",",
|
||||
U64_PRINTF_ARG(b->totals[i]));
|
||||
cp += strlen(cp);
|
||||
}
|
||||
cp += rep_hist_fill_bandwidth_history(cp, len-(cp-buf), b);
|
||||
strlcat(cp, "\n", len-(cp-buf));
|
||||
++cp;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/** Update the state with bandwidth history
|
||||
* A return value of 0 means nothing was updated,
|
||||
* a value of 1 means something has
|
||||
*/
|
||||
int
|
||||
rep_hist_update_state(or_state_t *state)
|
||||
{
|
||||
int len, r;
|
||||
char *buf, *cp;
|
||||
smartlist_t **s_values;
|
||||
time_t *s_begins;
|
||||
int *s_interval;
|
||||
bw_array_t *b;
|
||||
|
||||
len = 20*NUM_TOTALS+1;
|
||||
buf = tor_malloc_zero(len);
|
||||
|
||||
for (r=0;r<2;++r) {
|
||||
b = r?read_array:write_array;
|
||||
s_begins = r?&state->BWHistoryReadEnds :&state->BWHistoryWriteEnds;
|
||||
s_interval= r?&state->BWHistoryReadInterval:&state->BWHistoryWriteInterval;
|
||||
s_values = r?&state->BWHistoryReadValues :&state->BWHistoryWriteValues;
|
||||
|
||||
*s_begins = b->next_period;
|
||||
*s_interval = NUM_SECS_BW_SUM_INTERVAL;
|
||||
if (*s_values) {
|
||||
SMARTLIST_FOREACH(*s_values, char *, cp, tor_free(cp));
|
||||
smartlist_free(*s_values);
|
||||
}
|
||||
cp = buf;
|
||||
cp += rep_hist_fill_bandwidth_history(cp, len, b);
|
||||
tor_snprintf(cp, len-(cp-buf), cp == buf ? U64_FORMAT : ","U64_FORMAT,
|
||||
U64_PRINTF_ARG(b->total_in_period));
|
||||
*s_values = smartlist_create();
|
||||
smartlist_split_string(*s_values, buf, ",", SPLIT_SKIP_SPACE, 0);
|
||||
}
|
||||
tor_free(buf);
|
||||
state->dirty = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Set bandwidth history from our saved state.
|
||||
*/
|
||||
int
|
||||
rep_hist_load_state(or_state_t *state, const char **err)
|
||||
{
|
||||
time_t s_begins, start;
|
||||
time_t now = time(NULL);
|
||||
uint64_t v;
|
||||
int r,i,ok;
|
||||
int all_ok = 1;
|
||||
int s_interval;
|
||||
smartlist_t *s_values;
|
||||
bw_array_t *b;
|
||||
|
||||
/* Assert they already have been malloced */
|
||||
tor_assert(read_array && write_array);
|
||||
|
||||
for (r=0;r<2;++r) {
|
||||
b = r?read_array:write_array;
|
||||
s_begins = r?state->BWHistoryReadEnds:state->BWHistoryWriteEnds;
|
||||
s_interval = r?state->BWHistoryReadInterval:state->BWHistoryWriteInterval;
|
||||
s_values = r?state->BWHistoryReadValues:state->BWHistoryWriteValues;
|
||||
if (s_values && s_begins >= now - NUM_SECS_BW_SUM_INTERVAL*NUM_TOTALS) {
|
||||
start = s_begins - s_interval*(smartlist_len(s_values));
|
||||
|
||||
b->cur_obs_time = start;
|
||||
b->next_period = start + NUM_SECS_BW_SUM_INTERVAL;
|
||||
SMARTLIST_FOREACH(s_values, char *, cp, {
|
||||
v = tor_parse_uint64(cp, 10, 0, UINT64_MAX, &ok, NULL);
|
||||
if (!ok) {
|
||||
all_ok=0;
|
||||
notice(LD_GENERAL, "Could not parse '%s' into a number.'", cp);
|
||||
}
|
||||
add_obs(b, start, v);
|
||||
start += NUM_SECS_BW_SUM_INTERVAL;
|
||||
});
|
||||
}
|
||||
|
||||
/* Clean up maxima and observed */
|
||||
/* Do we really want to zero this for the purpose of max capacity? */
|
||||
for (i=0; i<NUM_SECS_ROLLING_MEASURE; ++i) {
|
||||
b->obs[i] = 0;
|
||||
}
|
||||
b->total_obs = 0;
|
||||
for (i=0; i<NUM_TOTALS; ++i) {
|
||||
b->maxima[i] = 0;
|
||||
}
|
||||
b->max_total = 0;
|
||||
}
|
||||
|
||||
if (!all_ok) {
|
||||
if (err)
|
||||
*err = "Parsing of bandwidth history values failed";
|
||||
/* and create fresh arrays */
|
||||
tor_free(read_array);
|
||||
tor_free(write_array);
|
||||
read_array = bw_array_new();
|
||||
write_array = bw_array_new();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** A list of port numbers that have been used recently. */
|
||||
static smartlist_t *predicted_ports_list=NULL;
|
||||
/** The corresponding most recently used time for each port. */
|
||||
|
Loading…
Reference in New Issue
Block a user