Merge branch 'ticket25948_squashed'

This commit is contained in:
Nick Mathewson 2018-04-30 16:46:59 -04:00
commit 72124dc1ef
7 changed files with 63 additions and 16 deletions

9
changes/ticket25948 Normal file
View File

@ -0,0 +1,9 @@
o Minor features (mainloop):
- Move responsibility for
saving the state file to disk
from a once-per-second callback to a callback that is only scheduled as
needed. Once enough items are removed from our once-per-second
callback, we can eliminate it entirely to conserve CPU when idle.
Closes ticket
25948.

View File

@ -1355,6 +1355,7 @@ CALLBACK(retry_listeners);
CALLBACK(rotate_onion_key);
CALLBACK(rotate_x509_certificate);
CALLBACK(save_stability);
CALLBACK(save_state);
CALLBACK(write_bridge_ns);
CALLBACK(write_stats_file);
@ -1376,6 +1377,7 @@ STATIC periodic_event_item_t periodic_events[] = {
CALLBACK(reset_padding_counts, PERIODIC_EVENT_ROLE_ALL, 0),
CALLBACK(retry_listeners, PERIODIC_EVENT_ROLE_ALL,
PERIODIC_EVENT_FLAG_NEED_NET),
CALLBACK(save_state, PERIODIC_EVENT_ROLE_ALL, 0),
CALLBACK(rotate_x509_certificate, PERIODIC_EVENT_ROLE_ALL, 0),
CALLBACK(write_stats_file, PERIODIC_EVENT_ROLE_ALL, 0),
@ -1434,6 +1436,7 @@ static periodic_event_item_t *check_descriptor_event=NULL;
static periodic_event_item_t *fetch_networkstatus_event=NULL;
static periodic_event_item_t *launch_descriptor_fetches_event=NULL;
static periodic_event_item_t *check_dns_honesty_event=NULL;
static periodic_event_item_t *save_state_event=NULL;
/** Reset all the periodic events so we'll do all our actions again as if we
* just started up.
@ -1532,6 +1535,7 @@ initialize_periodic_events(void)
NAMED_CALLBACK(fetch_networkstatus);
NAMED_CALLBACK(launch_descriptor_fetches);
NAMED_CALLBACK(check_dns_honesty);
NAMED_CALLBACK(save_state);
struct timeval one_second = { 1, 0 };
initialize_periodic_events_event = tor_evtimer_new(
@ -1609,8 +1613,9 @@ periodic_events_on_new_options(const or_options_t *options)
void
reschedule_descriptor_update_check(void)
{
tor_assert(check_descriptor_event);
periodic_event_reschedule(check_descriptor_event);
if (check_descriptor_event) {
periodic_event_reschedule(check_descriptor_event);
}
}
/**
@ -1756,10 +1761,6 @@ run_scheduled_events(time_t now)
run_connection_housekeeping(i, now);
}
/* 8b. And if anything in our state is ready to get flushed to disk, we
* flush it. */
or_state_save(now);
/* 11b. check pending unconfigured managed proxies */
if (!net_is_disabled() && pt_proxies_configuration_pending())
pt_configure_remaining_proxies();
@ -1993,6 +1994,37 @@ check_expired_networkstatus_callback(time_t now, const or_options_t *options)
return CHECK_EXPIRED_NS_INTERVAL;
}
/**
* Scheduled callback: Save the state file to disk if appropriate.
*/
static int
save_state_callback(time_t now, const or_options_t *options)
{
(void) options;
(void) or_state_save(now); // only saves if appropriate
const time_t next_write = get_or_state()->next_write;
if (next_write == TIME_MAX) {
return 86400;
} else if (BUG(next_write <= now)) {
/* This can't happen due to clock jumps, since the value of next_write
* is based on the same "now" that we passed to or_state_save().
*/
return PERIODIC_EVENT_NO_UPDATE;
} else {
return next_write - now;
}
}
/** Reschedule the event for saving the state file.
*
* Run this when the state becomes dirty. */
void
reschedule_or_state_save(void)
{
tor_assert(save_state_event);
periodic_event_reschedule(save_state_event);
}
/**
* Periodic callback: Write statistics to disk if appropriate.
*/

View File

@ -61,6 +61,7 @@ void dns_servers_relaunch_checks(void);
void reset_all_main_loop_timers(void);
void reschedule_descriptor_update_check(void);
void reschedule_directory_downloads(void);
void reschedule_or_state_save(void);
void mainloop_schedule_postloop_cleanup(void);
void rescan_periodic_events(const or_options_t *options);

View File

@ -4746,15 +4746,6 @@ typedef struct {
time_t LastRotatedOnionKey;
} or_state_t;
/** Change the next_write time of <b>state</b> to <b>when</b>, unless the
* state is already scheduled to be written to disk earlier than <b>when</b>.
*/
static inline void or_state_mark_dirty(or_state_t *state, time_t when)
{
if (state->next_write > when)
state->next_write = when;
}
#define MAX_SOCKS_REPLY_LEN 1024
#define MAX_SOCKS_ADDR_LEN 256
#define SOCKS_NO_AUTH 0x00

View File

@ -85,8 +85,8 @@
#include "routerlist.h"
#include "ht.h"
#include "channelpadding.h"
#include "connection_or.h"
#include "statefile.h"
static void bw_arrays_init(void);
static void predicted_ports_alloc(void);

View File

@ -37,6 +37,7 @@
#include "control.h"
#include "entrynodes.h"
#include "hibernate.h"
#include "main.h"
#include "rephist.h"
#include "router.h"
#include "sandbox.h"
@ -680,6 +681,18 @@ save_transport_to_state(const char *transport,
tor_free(transport_addrport);
}
/** Change the next_write time of <b>state</b> to <b>when</b>, unless the
* state is already scheduled to be written to disk earlier than <b>when</b>.
*/
void
or_state_mark_dirty(or_state_t *state, time_t when)
{
if (state->next_write > when) {
state->next_write = when;
reschedule_or_state_save();
}
}
STATIC void
or_state_free_(or_state_t *state)
{

View File

@ -17,6 +17,7 @@ char *get_stored_bindaddr_for_server_transport(const char *transport);
int or_state_load(void);
int or_state_loaded(void);
void or_state_free_all(void);
void or_state_mark_dirty(or_state_t *state, time_t when);
#ifdef STATEFILE_PRIVATE
STATIC config_line_t *get_transport_in_state_by_name(const char *transport);