/** Invoked once per second. Checks whether it is time to hibernate, * record bandwidth used, etc. */ void accounting_run_housekeeping(time_t now) { if (now >= interval_end_time) { configure_accounting(now); } if (time_to_record_bandwidth_usage(now)) { if (accounting_record_bandwidth_usage(now, get_or_state())) { log_warn(LD_FS, "Couldn't record bandwidth usage to disk."); } } }
/** If we aren't currently dormant, close all connections and become * dormant. */ static void hibernate_go_dormant(time_t now) { connection_t *conn; if (hibernate_state == HIBERNATE_STATE_DORMANT) return; else if (hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH) hibernate_state = HIBERNATE_STATE_DORMANT; else hibernate_begin(HIBERNATE_STATE_DORMANT, now); log_notice(LD_ACCT,"Going dormant. Blowing away remaining connections."); /* Close all OR/AP/exit conns. Leave dir conns because we still want * to be able to upload server descriptors so people know we're still * running, and download directories so we can detect if we're obsolete. * Leave control conns because we still want to be controllable. */ while ((conn = connection_get_by_type(CONN_TYPE_OR)) || (conn = connection_get_by_type(CONN_TYPE_AP)) || (conn = connection_get_by_type(CONN_TYPE_EXIT))) { if (CONN_IS_EDGE(conn)) connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_HIBERNATING); log_info(LD_NET,"Closing conn type %d", conn->type); if (conn->type == CONN_TYPE_AP) /* send socks failure if needed */ connection_mark_unattached_ap(TO_ENTRY_CONN(conn), END_STREAM_REASON_HIBERNATING); else if (conn->type == CONN_TYPE_OR) { if (TO_OR_CONN(conn)->chan) { channel_mark_for_close(TLS_CHAN_TO_BASE(TO_OR_CONN(conn)->chan)); } else { connection_mark_for_close(conn); } } else connection_mark_for_close(conn); } if (now < interval_wakeup_time) hibernate_end_time = interval_wakeup_time; else hibernate_end_time = interval_end_time; accounting_record_bandwidth_usage(now, get_or_state()); or_state_mark_dirty(get_or_state(), get_options()->AvoidDiskWrites ? now+600 : 0); }
/** Called when we get a SIGINT, or when bandwidth soft limit is * reached. Puts us into "loose hibernation": we don't accept new * connections, but we continue handling old ones. */ static void hibernate_begin(hibernate_state_t new_state, time_t now) { connection_t *conn; or_options_t *options = get_options(); if (new_state == HIBERNATE_STATE_EXITING && hibernate_state != HIBERNATE_STATE_LIVE) { log_notice(LD_GENERAL,"SIGINT received %s; exiting now.", hibernate_state == HIBERNATE_STATE_EXITING ? "a second time" : "while hibernating"); tor_cleanup(); exit(0); } /* close listeners. leave control listener(s). */ while ((conn = connection_get_by_type(CONN_TYPE_OR_LISTENER)) || (conn = connection_get_by_type(CONN_TYPE_AP_LISTENER)) || (conn = connection_get_by_type(CONN_TYPE_AP_TRANS_LISTENER)) || (conn = connection_get_by_type(CONN_TYPE_AP_DNS_LISTENER)) || (conn = connection_get_by_type(CONN_TYPE_AP_NATD_LISTENER)) || (conn = connection_get_by_type(CONN_TYPE_DIR_LISTENER))) { log_info(LD_NET,"Closing listener type %d", conn->type); connection_mark_for_close(conn); } /* XXX kill intro point circs */ /* XXX upload rendezvous service descriptors with no intro points */ if (new_state == HIBERNATE_STATE_EXITING) { log_notice(LD_GENERAL,"Interrupt: will shut down in %d seconds. Interrupt " "again to exit now.", options->ShutdownWaitLength); shutdown_time = time(NULL) + options->ShutdownWaitLength; } else { /* soft limit reached */ hibernate_end_time = interval_end_time; } hibernate_state = new_state; accounting_record_bandwidth_usage(now, get_or_state()); or_state_mark_dirty(get_or_state(), get_options()->AvoidDiskWrites ? now+600 : 0); }
/** Called when we get a SIGINT, or when bandwidth soft limit is * reached. Puts us into "loose hibernation": we don't accept new * connections, but we continue handling old ones. */ static void hibernate_begin(hibernate_state_t new_state, time_t now) { const or_options_t *options = get_options(); if (new_state == HIBERNATE_STATE_EXITING && hibernate_state != HIBERNATE_STATE_LIVE) { log_notice(LD_GENERAL,"SIGINT received %s; exiting now.", hibernate_state == HIBERNATE_STATE_EXITING ? "a second time" : "while hibernating"); tor_cleanup(); exit(0); } if (new_state == HIBERNATE_STATE_LOWBANDWIDTH && hibernate_state == HIBERNATE_STATE_LIVE) { soft_limit_hit_at = now; n_seconds_to_hit_soft_limit = n_seconds_active_in_interval; n_bytes_at_soft_limit = MAX(n_bytes_read_in_interval, n_bytes_written_in_interval); } /* close listeners. leave control listener(s). */ connection_mark_all_noncontrol_listeners(); /* XXX kill intro point circs */ /* XXX upload rendezvous service descriptors with no intro points */ if (new_state == HIBERNATE_STATE_EXITING) { log_notice(LD_GENERAL,"Interrupt: we have stopped accepting new " "connections, and will shut down in %d seconds. Interrupt " "again to exit now.", options->ShutdownWaitLength); shutdown_time = time(NULL) + options->ShutdownWaitLength; } else { /* soft limit reached */ hibernate_end_time = interval_end_time; } hibernate_state = new_state; accounting_record_bandwidth_usage(now, get_or_state()); or_state_mark_dirty(get_or_state(), get_options()->AvoidDiskWrites ? now+600 : 0); }