Add subsys functions for receiving/flushing states and options.

These functions are in the subsystem, not in the config_format_t,
since they are about how the format is _used_, not about _what it
is_.
This commit is contained in:
Nick Mathewson 2019-10-30 10:29:43 -04:00
parent 7ac4f9d5ec
commit 52c0ab4af3
5 changed files with 119 additions and 1 deletions

View File

@ -987,7 +987,8 @@ set_options(or_options_t *new_val, char **msg)
global_options = old_options;
return -1;
}
if (options_act(old_options) < 0) { /* acting on the options failed. die. */
if (subsystems_set_options(get_options_mgr(), new_val) < 0 ||
options_act(old_options) < 0) { /* acting on the options failed. die. */
if (! tor_event_loop_shutdown_is_pending()) {
log_err(LD_BUG,
"Acting on config options left us in a broken state. Dying.");

View File

@ -316,6 +316,9 @@ or_state_set(or_state_t *new_state)
tor_assert(new_state);
config_free(get_state_mgr(), global_state);
global_state = new_state;
if (subsystems_set_state(get_state_mgr(), global_state) < 0) {
ret = -1;
}
if (entry_guards_parse_state(global_state, 1, &err)<0) {
log_warn(LD_GENERAL,"%s",err);
tor_free(err);
@ -519,6 +522,7 @@ or_state_save(time_t now)
/* Call everything else that might dirty the state even more, in order
* to avoid redundant writes. */
(void) subsystems_flush_state(get_state_mgr(), global_state);
entry_guards_update_state(global_state);
rep_hist_update_state(global_state);
circuit_build_times_update_state(get_circuit_build_times(), global_state);

View File

@ -334,3 +334,79 @@ subsystems_register_state_formats(config_mgr_t *mgr)
}
return 0;
}
/**
* Call all appropriate set_options() methods to tell the various subsystems
* about a new set of torrc options. Return 0 on success, -1 on
* nonrecoverable failure.
**/
int
subsystems_set_options(const config_mgr_t *mgr, struct or_options_t *options)
{
/* XXXX This does not yet handle reversible option assignment; I'll
* do that later in this branch. */
for (unsigned i = 0; i < n_tor_subsystems; ++i) {
const subsys_fns_t *sys = tor_subsystems[i];
if (sys_status[i].options_idx >= 0 && sys->set_options) {
void *obj = config_mgr_get_obj_mutable(mgr, options,
sys_status[i].options_idx);
int rv = sys->set_options(obj);
if (rv < 0) {
log_err(LD_CONFIG, "Error when handling option for %s; "
"cannot proceed.", sys->name);
return -1;
}
}
}
return 0;
}
/**
* Call all appropriate set_state() methods to tell the various subsystems
* about an initial DataDir/state file. Return 0 on success, -1 on
* nonrecoverable failure.
**/
int
subsystems_set_state(const config_mgr_t *mgr, struct or_state_t *state)
{
for (unsigned i = 0; i < n_tor_subsystems; ++i) {
const subsys_fns_t *sys = tor_subsystems[i];
if (sys_status[i].state_idx >= 0 && sys->set_state) {
void *obj = config_mgr_get_obj_mutable(mgr, state,
sys_status[i].state_idx);
int rv = sys->set_state(obj);
if (rv < 0) {
log_err(LD_CONFIG, "Error when handling state for %s; "
"cannot proceed.", sys->name);
return -1;
}
}
}
return 0;
}
/**
* Call all appropriate flush_state() methods to tell the various subsystems
* to update the state objects in <b>state</b>. Return 0 on success,
* -1 on failure.
**/
int
subsystems_flush_state(const config_mgr_t *mgr, struct or_state_t *state)
{
int result = 0;
for (unsigned i = 0; i < n_tor_subsystems; ++i) {
const subsys_fns_t *sys = tor_subsystems[i];
if (sys_status[i].state_idx >= 0 && sys->flush_state) {
void *obj = config_mgr_get_obj_mutable(mgr, state,
sys_status[i].state_idx);
int rv = sys->flush_state(obj);
if (rv < 0) {
log_warn(LD_CONFIG, "Error when flushing state to state object for %s",
sys->name);
result = -1;
}
}
}
return result;
}

View File

@ -34,5 +34,13 @@ void subsystems_thread_cleanup(void);
struct config_mgr_t;
int subsystems_register_options_formats(struct config_mgr_t *mgr);
int subsystems_register_state_formats(struct config_mgr_t *mgr);
struct or_options_t;
struct or_state_t;
int subsystems_set_options(const struct config_mgr_t *mgr,
struct or_options_t *options);
int subsystems_set_state(const struct config_mgr_t *mgr,
struct or_state_t *state);
int subsystems_flush_state(const struct config_mgr_t *mgr,
struct or_state_t *state);
#endif /* !defined(TOR_SUBSYSMGR_T) */

View File

@ -101,6 +101,35 @@ typedef struct subsys_fns_t {
**/
const struct config_format_t *state_format;
/**
* Receive an options object as defined by options_format. Return 0
* on success, -1 on failure.
*
* It is safe to store the pointer to the object until set_options()
* is called again. */
int (*set_options)(void *);
/* XXXX Add an implementation for options_act_reversible() later in this
* branch. */
/**
* Receive a state object as defined by state_format. Return 0 on success,
* -1 on failure.
*
* It is safe to store the pointer to the object; set_state() is only
* called on startup.
**/
int (*set_state)(void *);
/**
* Update any information that needs to be stored in the provided state
* object (as defined by state_format). Return 0 on success, -1 on failure.
*
* The object provided here will be the same one as provided earlier to
* set_state(). This method is called when we are about to save the state
* to disk.
**/
int (*flush_state)(void *);
} subsys_fns_t;
/**