mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +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("HelperNodes", LINELIST_V, HelperNodes, NULL),
|
||||||
VAR("LastWritten", ISOTIME, LastWritten, 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 }
|
{ NULL, CONFIG_TYPE_OBSOLETE, 0, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3516,7 +3523,8 @@ or_state_set(or_state_t *new_state)
|
|||||||
global_state = new_state;
|
global_state = new_state;
|
||||||
if (helper_nodes_parse_state(global_state, 1, &err)<0)
|
if (helper_nodes_parse_state(global_state, 1, &err)<0)
|
||||||
warn(LD_GENERAL,"Unparseable helper nodes state: %s",err);
|
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 */
|
/* DOCDOC */
|
||||||
@ -3589,6 +3597,7 @@ or_state_save(void)
|
|||||||
char *fname;
|
char *fname;
|
||||||
|
|
||||||
helper_nodes_update_state(global_state);
|
helper_nodes_update_state(global_state);
|
||||||
|
rep_hist_update_state(global_state);
|
||||||
|
|
||||||
if (!global_state->dirty)
|
if (!global_state->dirty)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -779,6 +779,9 @@ run_scheduled_events(time_t now)
|
|||||||
* and the rend cache. */
|
* and the rend cache. */
|
||||||
rep_history_clean(now - options->RephistTrackTime);
|
rep_history_clean(now - options->RephistTrackTime);
|
||||||
rend_cache_clean();
|
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. */
|
/* Caches need to fetch running_routers; directory clients don't. */
|
||||||
@ -1494,6 +1497,7 @@ tor_cleanup(void)
|
|||||||
unlink(options->PidFile);
|
unlink(options->PidFile);
|
||||||
if (accounting_is_enabled(options))
|
if (accounting_is_enabled(options))
|
||||||
accounting_record_bandwidth_usage(time(NULL));
|
accounting_record_bandwidth_usage(time(NULL));
|
||||||
|
or_state_save();
|
||||||
tor_free_all(0); /* move tor_free_all back into the ifdef below later. XXX*/
|
tor_free_all(0); /* move tor_free_all back into the ifdef below later. XXX*/
|
||||||
crypto_global_cleanup();
|
crypto_global_cleanup();
|
||||||
#ifdef USE_DMALLOC
|
#ifdef USE_DMALLOC
|
||||||
|
10
src/or/or.h
10
src/or/or.h
@ -1369,6 +1369,13 @@ typedef struct {
|
|||||||
uint64_t AccountingExpectedUsage;
|
uint64_t AccountingExpectedUsage;
|
||||||
|
|
||||||
config_line_t *HelperNodes;
|
config_line_t *HelperNodes;
|
||||||
|
|
||||||
|
time_t BWHistoryReadEnds;
|
||||||
|
int BWHistoryReadInterval;
|
||||||
|
smartlist_t *BWHistoryReadValues;
|
||||||
|
time_t BWHistoryWriteEnds;
|
||||||
|
int BWHistoryWriteInterval;
|
||||||
|
smartlist_t *BWHistoryWriteValues;
|
||||||
} or_state_t;
|
} or_state_t;
|
||||||
|
|
||||||
#define MAX_SOCKS_REPLY_LEN 1024
|
#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 rep_hist_get_predicted_internal(time_t now, int *need_uptime,
|
||||||
int *need_capacity);
|
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);
|
void rep_hist_free_all(void);
|
||||||
|
|
||||||
/********************************* rendclient.c ***************************/
|
/********************************* rendclient.c ***************************/
|
||||||
|
161
src/or/rephist.c
161
src/or/rephist.c
@ -579,6 +579,41 @@ rep_hist_bandwidth_assess(void)
|
|||||||
return 0;
|
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
|
* Allocate and return lines for representing this server's bandwidth
|
||||||
* history in its descriptor.
|
* history in its descriptor.
|
||||||
@ -588,7 +623,7 @@ rep_hist_get_bandwidth_lines(void)
|
|||||||
{
|
{
|
||||||
char *buf, *cp;
|
char *buf, *cp;
|
||||||
char t[ISO_TIME_LEN+1];
|
char t[ISO_TIME_LEN+1];
|
||||||
int r, i, n;
|
int r;
|
||||||
bw_array_t *b;
|
bw_array_t *b;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
@ -604,31 +639,117 @@ rep_hist_get_bandwidth_lines(void)
|
|||||||
r ? "read-history" : "write-history", t,
|
r ? "read-history" : "write-history", t,
|
||||||
NUM_SECS_BW_SUM_INTERVAL);
|
NUM_SECS_BW_SUM_INTERVAL);
|
||||||
cp += strlen(cp);
|
cp += strlen(cp);
|
||||||
|
cp += rep_hist_fill_bandwidth_history(cp, len-(cp-buf), b);
|
||||||
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);
|
|
||||||
}
|
|
||||||
strlcat(cp, "\n", len-(cp-buf));
|
strlcat(cp, "\n", len-(cp-buf));
|
||||||
++cp;
|
++cp;
|
||||||
}
|
}
|
||||||
return buf;
|
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. */
|
/** A list of port numbers that have been used recently. */
|
||||||
static smartlist_t *predicted_ports_list=NULL;
|
static smartlist_t *predicted_ports_list=NULL;
|
||||||
/** The corresponding most recently used time for each port. */
|
/** The corresponding most recently used time for each port. */
|
||||||
|
Loading…
Reference in New Issue
Block a user