sr: Don't use a dynamic voting schedule

The exposed get_voting_schedule() allocates and return a new object everytime
it is called leading to an awful lot of memory allocation when getting the
start time of the current round which is done for each node in the consensus.

Closes #23623

Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
David Goulet 2017-10-27 09:16:29 -04:00
parent 60164f057c
commit 7ee0a2b9aa
6 changed files with 18 additions and 50 deletions

View File

@ -2790,7 +2790,7 @@ dirvote_get_start_of_next_interval(time_t now, int interval, int offset)
/* Populate and return a new voting_schedule_t that can be used to schedule
* voting. The object is allocated on the heap and it's the responsibility of
* the caller to free it. Can't fail. */
voting_schedule_t *
static voting_schedule_t *
get_voting_schedule(const or_options_t *options, time_t now, int severity)
{
int interval, vote_delay, dist_delay;
@ -2845,7 +2845,7 @@ get_voting_schedule(const or_options_t *options, time_t now, int severity)
/** Frees a voting_schedule_t. This should be used instead of the generic
* tor_free. */
void
static void
voting_schedule_free(voting_schedule_t *voting_schedule_to_free)
{
if (!voting_schedule_to_free)
@ -2857,18 +2857,9 @@ static voting_schedule_t voting_schedule;
/* Using the time <b>now</b>, return the next voting valid-after time. */
time_t
get_next_valid_after_time(time_t now)
dirvote_get_next_valid_after_time(void)
{
time_t next_valid_after_time;
const or_options_t *options = get_options();
voting_schedule_t *new_voting_schedule =
get_voting_schedule(options, now, LOG_INFO);
tor_assert(new_voting_schedule);
next_valid_after_time = new_voting_schedule->interval_starts;
voting_schedule_free(new_voting_schedule);
return next_valid_after_time;
return voting_schedule.interval_starts;
}
/** Set voting_schedule to hold the timing for the next vote we should be

View File

@ -170,18 +170,13 @@ typedef struct {
int have_published_consensus;
} voting_schedule_t;
voting_schedule_t *get_voting_schedule(const or_options_t *options,
time_t now, int severity);
void voting_schedule_free(voting_schedule_t *voting_schedule_to_free);
void dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out);
time_t dirvote_get_start_of_next_interval(time_t now,
int interval,
int offset);
void dirvote_recalculate_timing(const or_options_t *options, time_t now);
void dirvote_act(const or_options_t *options, time_t now);
time_t get_next_valid_after_time(time_t now);
time_t dirvote_get_next_valid_after_time(void);
/* invoked on timers and by outside triggers. */
struct pending_vote_t * dirvote_add_vote(const char *vote_body,

View File

@ -1333,13 +1333,7 @@ sr_act_post_consensus(const networkstatus_t *consensus)
}
/* Prepare our state so that it's ready for the next voting period. */
{
voting_schedule_t *voting_schedule =
get_voting_schedule(options,time(NULL), LOG_NOTICE);
time_t interval_starts = voting_schedule->interval_starts;
sr_state_update(interval_starts);
voting_schedule_free(voting_schedule);
}
sr_state_update(dirvote_get_next_valid_after_time());
}
/* Initialize shared random subsystem. This MUST be called early in the boot

View File

@ -139,25 +139,18 @@ get_voting_interval(void)
* the SR protocol. For example, if it's 23:47:08, the current round thus
* started at 23:47:00 for a voting interval of 10 seconds. */
STATIC time_t
get_start_time_of_current_round(time_t now)
get_start_time_of_current_round(void)
{
const or_options_t *options = get_options();
int voting_interval = get_voting_interval();
voting_schedule_t *new_voting_schedule =
get_voting_schedule(options, now, LOG_DEBUG);
tor_assert(new_voting_schedule);
/* First, get the start time of the next round */
time_t next_start = new_voting_schedule->interval_starts;
time_t next_start = dirvote_get_next_valid_after_time();
/* Now roll back next_start by a voting interval to find the start time of
the current round. */
time_t curr_start = dirvote_get_start_of_next_interval(
next_start - voting_interval - 1,
voting_interval,
options->TestingV3AuthVotingStartOffset);
voting_schedule_free(new_voting_schedule);
return curr_start;
}
@ -170,7 +163,7 @@ sr_state_get_start_time_of_current_protocol_run(time_t now)
int total_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
int voting_interval = get_voting_interval();
/* Find the time the current round started. */
time_t beginning_of_current_round = get_start_time_of_current_round(now);
time_t beginning_of_current_round = get_start_time_of_current_round();
/* Get current SR protocol round */
int current_round = (now / voting_interval) % total_rounds;
@ -208,7 +201,7 @@ get_state_valid_until_time(time_t now)
voting_interval = get_voting_interval();
/* Find the time the current round started. */
beginning_of_current_round = get_start_time_of_current_round(now);
beginning_of_current_round = get_start_time_of_current_round();
/* Find how many rounds are left till the end of the protocol run */
current_round = (now / voting_interval) % total_rounds;
@ -1370,7 +1363,7 @@ sr_state_init(int save_to_disk, int read_from_disk)
/* We have a state in memory, let's make sure it's updated for the current
* and next voting round. */
{
time_t valid_after = get_next_valid_after_time(now);
time_t valid_after = dirvote_get_next_valid_after_time();
sr_state_update(valid_after);
}
return 0;

View File

@ -130,7 +130,7 @@ unsigned int sr_state_get_protocol_run_duration(void);
STATIC int disk_state_load_from_disk_impl(const char *fname);
STATIC sr_phase_t get_sr_protocol_phase(time_t valid_after);
STATIC time_t get_start_time_of_current_round(time_t now);
STATIC time_t get_start_time_of_current_round(void);
STATIC time_t get_state_valid_until_time(time_t now);
STATIC const char *get_phase_str(sr_phase_t phase);

View File

@ -273,14 +273,9 @@ test_get_start_time_functions(void *arg)
tt_assert(start_time_of_protocol_run);
/* Check that the round start time of the beginning of the run, is itself */
tt_int_op(get_start_time_of_current_round(start_time_of_protocol_run), OP_EQ,
tt_int_op(get_start_time_of_current_round(), OP_EQ,
start_time_of_protocol_run);
/* Check that even if we increment the start time, we still get the start
time of the run as the beginning of the round. */
tt_int_op(get_start_time_of_current_round(start_time_of_protocol_run+1),
OP_EQ, start_time_of_protocol_run);
done: ;
}
@ -311,7 +306,7 @@ mock_networkstatus_get_live_consensus(time_t now)
return mock_consensus;
}
/** Test the get_next_valid_after_time() function. */
/** Test the dirvote_get_next_valid_after_time() function. */
static void
test_get_next_valid_after_time(void *arg)
{
@ -324,7 +319,7 @@ test_get_next_valid_after_time(void *arg)
{
/* Setup a fake consensus just to get the times out of it, since
get_next_valid_after_time() needs them. */
dirvote_get_next_valid_after_time() needs them. */
mock_consensus = tor_malloc_zero(sizeof(networkstatus_t));
retval = parse_rfc1123_time("Mon, 13 Jan 2016 16:00:00 UTC",
@ -344,7 +339,7 @@ test_get_next_valid_after_time(void *arg)
retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:00 UTC",
&current_time);
tt_int_op(retval, OP_EQ, 0);
valid_after_time = get_next_valid_after_time(current_time);
valid_after_time = dirvote_get_next_valid_after_time();
/* Compare it with the correct result */
format_iso_time(tbuf, valid_after_time);
@ -356,7 +351,7 @@ test_get_next_valid_after_time(void *arg)
retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:01 UTC",
&current_time);
tt_int_op(retval, OP_EQ, 0);
valid_after_time = get_next_valid_after_time(current_time);
valid_after_time = dirvote_get_next_valid_after_time();
/* Compare it with the correct result */
format_iso_time(tbuf, valid_after_time);
@ -367,7 +362,7 @@ test_get_next_valid_after_time(void *arg)
retval = parse_rfc1123_time("Mon, 20 Apr 2015 23:30:01 UTC",
&current_time);
tt_int_op(retval, OP_EQ, 0);
valid_after_time = get_next_valid_after_time(current_time);
valid_after_time = dirvote_get_next_valid_after_time();
/* Compare it with the correct result */
format_iso_time(tbuf, valid_after_time);