30#define HIBERNATE_PRIVATE
55# if defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__)
59# define __INCLUDE_LEVEL__ 2
61#include <systemd/sd-daemon.h>
81 UNIT_MONTH=1, UNIT_WEEK=2, UNIT_DAY=3,
169 case HIBERNATE_STATE_EXITING:
return "EXITING";
170 case HIBERNATE_STATE_LOWBANDWIDTH:
return "SOFT";
171 case HIBERNATE_STATE_DORMANT:
return "HARD";
172 case HIBERNATE_STATE_INITIAL:
173 case HIBERNATE_STATE_LIVE:
176 log_warn(
LD_BUG,
"unknown hibernate state %d", state);
201 if (!validate_only) {
212 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK,0);
213 if (smartlist_len(items)<2) {
214 log_warn(
LD_CONFIG,
"Too few arguments to AccountingStart");
217 s = smartlist_get(items,0);
218 if (0==strcasecmp(s,
"month")) {
220 }
else if (0==strcasecmp(s,
"week")) {
222 }
else if (0==strcasecmp(s,
"day")) {
226 "Unrecognized accounting unit '%s': only 'month', 'week',"
227 " and 'day' are supported.", s);
235 log_warn(
LD_CONFIG,
"Weekly accounting must begin on a day between "
236 "1 (Monday) and 7 (Sunday)");
243 log_warn(
LD_CONFIG,
"Monthly accounting must begin on a day between "
258 idx = unit==UNIT_DAY?1:2;
259 if (smartlist_len(items) != (idx+1)) {
260 log_warn(
LD_CONFIG,
"Accounting unit '%s' requires %d argument%s.",
261 s, idx, (idx>1)?
"s":
"");
264 s = smartlist_get(items, idx);
267 log_warn(
LD_CONFIG,
"Accounting start time not parseable: bad hour.");
270 if (!cp || *cp!=
':') {
272 "Accounting start time not parseable: not in HH:MM format");
277 log_warn(
LD_CONFIG,
"Accounting start time not parseable: bad minute");
280 if (!cp || *cp!=
'\0') {
282 "Accounting start time not parseable: not in HH:MM format");
286 if (!validate_only) {
289 cfg_start_hour = (int)h;
290 cfg_start_min = (int)m;
293 smartlist_free(items);
297 smartlist_free(items);
352 before = tm.tm_hour < cfg_start_hour ||
353 (tm.tm_hour == cfg_start_hour && tm.tm_min < cfg_start_min);
376 int delta = (7+tm.tm_wday-wday)%7;
379 if (delta == 0 && before)
396 tm.tm_hour = cfg_start_hour;
397 tm.tm_min = cfg_start_min;
442 log_info(
LD_ACCT,
"Starting new accounting interval.");
445 log_info(
LD_ACCT,
"Continuing accounting interval.");
452 if (-0.50 <= delta && delta <= 0.50) {
457 log_info(
LD_ACCT,
"Accounting interval moved by %.02f%%; "
458 "that's fine.", delta*100);
460 }
else if (delta >= 0.99) {
463 log_info(
LD_ACCT,
"Accounting interval elapsed; starting a new one");
467 "Mismatched accounting interval: moved by %.02f%%. "
468 "Starting a fresh one.", delta*100);
484 else if (
get_options()->AccountingRule == ACCT_OUT)
507#define MIN_TIME_FOR_MEASUREMENT (1800)
534 if (expected > max_configured)
535 expected = max_configured;
546 log_info(
LD_ACCT,
"Starting new accounting interval.");
563#define NOTE_INTERVAL (600)
565#define NOTE_BYTES (20*1024*1024)
566 static uint64_t last_read_bytes_noted = 0;
567 static uint64_t last_written_bytes_noted = 0;
568 static time_t last_time_noted = 0;
570 if (last_time_noted + NOTE_INTERVAL <= now ||
574 last_time_noted = now;
592 log_warn(
LD_FS,
"Couldn't record bandwidth usage to disk.");
604 uint64_t time_to_exhaust_bw;
605 int time_to_consider;
609 log_err(
LD_BUG,
"Error initializing keys");
615 char buf[ISO_TIME_LEN+1];
619 log_err(
LD_BUG,
"Error getting our key's digest.");
633 char buf1[ISO_TIME_LEN+1];
634 char buf2[ISO_TIME_LEN+1];
640 "Configured hibernation. This interval begins at %s "
641 "and ends at %s. We have no prior estimate for bandwidth, so "
642 "we will start out awake and hibernate when we exhaust our quota.",
649 if (time_to_exhaust_bw > INT_MAX) {
650 time_to_exhaust_bw = INT_MAX;
651 time_to_consider = 0;
654 (int)time_to_exhaust_bw;
657 if (time_to_consider<=0) {
672 char buf1[ISO_TIME_LEN+1];
673 char buf2[ISO_TIME_LEN+1];
674 char buf3[ISO_TIME_LEN+1];
675 char buf4[ISO_TIME_LEN+1];
678 down_time = TIME_MAX;
689 "Configured hibernation. This interval began at %s; "
690 "the scheduled wake-up time %s %s; "
691 "we expect%s to exhaust our quota for this interval around %s; "
692 "the next interval begins at %s (all times local)",
695 time(NULL)<down_time?
"":
"ed", buf3,
701#define ROUND_UP(x) (((x) + 0x3ff) & ~0x3ff)
710 state->AccountingBytesWrittenInInterval =
734 char *fname = get_datadir_fname(
"bw_accounting");
738 if (res != 0 && errno != ENOENT) {
740 "Failed to unlink %s: %s",
741 fname, strerror(errno));
750 log_info(
LD_ACCT,
"Reading bandwidth accounting data from state file");
773 char tbuf1[ISO_TIME_LEN+1];
774 char tbuf2[ISO_TIME_LEN+1];
779 "Successfully read bandwidth accounting info from state written at %s "
780 "for interval starting at %s. We have been active for %lu seconds in "
781 "this interval. At the start of the interval, we expected to use "
782 "about %lu KB per second. (%"PRIu64
" bytes read so far, "
783 "%"PRIu64
" bytes written so far)",
811#define SOFT_LIM_PCT (.95)
812#define SOFT_LIM_BYTES (500*1024*1024)
813#define SOFT_LIM_MINUTES (3*60)
820 uint64_t soft_limit = (uint64_t) (acct_max * SOFT_LIM_PCT);
821 if (acct_max > SOFT_LIM_BYTES && acct_max - SOFT_LIM_BYTES > soft_limit) {
822 soft_limit = acct_max - SOFT_LIM_BYTES;
825 const uint64_t expected_usage =
827 if (acct_max > expected_usage && acct_max - expected_usage > soft_limit)
828 soft_limit = acct_max - expected_usage;
844 if (new_state == HIBERNATE_STATE_EXITING &&
846 log_notice(
LD_GENERAL,
"SIGINT received %s; exiting now.",
848 "a second time" :
"while hibernating");
853 if (new_state == HIBERNATE_STATE_LOWBANDWIDTH &&
866 if (new_state == HIBERNATE_STATE_EXITING) {
867 log_notice(
LD_GENERAL,
"Interrupt: we have stopped accepting new "
868 "connections, and will shut down in %d seconds. Interrupt "
894 sd_notifyf(0,
"EXTEND_TIMEOUT_USEC=%" PRIu64,
918 log_notice(
LD_ACCT,
"Hibernation period ended. Resuming normal activity.");
966 log_notice(
LD_ACCT,
"Going dormant. Blowing away remaining connections.");
979 log_info(
LD_NET,
"Closing conn type %d", conn->
type);
983 END_STREAM_REASON_HIBERNATING);
988 connection_mark_for_close(conn);
991 connection_mark_for_close(conn);
1019 struct timeval delay = { 0, 0 };
1021 if (now >= end_time) {
1026 delay.tv_sec = (end_time - now);
1046 const time_t now = time(NULL);
1067 char buf[ISO_TIME_LEN+1];
1083 "Accounting period ended. Commencing hibernation until "
1088 "Accounting period ended. This period, we will hibernate"
1089 " until %s UTC",buf);
1101 char buf[ISO_TIME_LEN+1];
1110 log_notice(
LD_BUG,
"Mainloop did not catch shutdown event; exiting.");
1134 "Bandwidth soft limit reached; commencing hibernation. "
1135 "No new connections will be accepted");
1140 "Commencing hibernation. We will wake up at %s local time.",
1149 if (!accounting_enabled) {
1171 const char *question,
char **answer,
1172 const char **errmsg)
1176 if (!strcmp(question,
"accounting/enabled")) {
1178 }
else if (!strcmp(question,
"accounting/hibernating")) {
1181 }
else if (!strcmp(question,
"accounting/bytes")) {
1185 }
else if (!strcmp(question,
"accounting/bytes-left")) {
1188 uint64_t total_left = 0;
1190 if (total_bytes < limit)
1191 total_left = limit - total_bytes;
1193 (total_left), (total_left));
1194 }
else if (
get_options()->AccountingRule == ACCT_IN) {
1195 uint64_t read_left = 0;
1199 (read_left), (limit));
1200 }
else if (
get_options()->AccountingRule == ACCT_OUT) {
1201 uint64_t write_left = 0;
1205 (limit), (write_left));
1207 uint64_t read_left = 0, write_left = 0;
1213 (read_left), (write_left));
1215 }
else if (!strcmp(question,
"accounting/interval-start")) {
1216 *answer = tor_malloc(ISO_TIME_LEN+1);
1218 }
else if (!strcmp(question,
"accounting/interval-wake")) {
1219 *answer = tor_malloc(ISO_TIME_LEN+1);
1221 }
else if (!strcmp(question,
"accounting/interval-end")) {
1222 *answer = tor_malloc(ISO_TIME_LEN+1);
1239 "HIBERNATION_STATUS STATUS=%s",
1247 if (prev_state != HIBERNATE_STATE_INITIAL) {
1262#ifdef TOR_UNIT_TESTS
1268hibernate_set_state_for_testing_(hibernate_state_t newstate)
static uint32_t get_uint32(const void *cp)
Header file for channel.c.
Header file for channeltls.c.
mainloop_event_t * mainloop_event_postloop_new(void(*cb)(mainloop_event_t *, void *), void *userdata)
int mainloop_event_schedule(mainloop_event_t *event, const struct timeval *tv)
Header for compat_libevent.c.
const or_options_t * get_options(void)
Header file for config.c.
void connection_mark_all_noncontrol_listeners(void)
connection_t * connection_get_by_type(int type)
Header file for connection.c.
int connection_edge_end(edge_connection_t *conn, uint8_t reason)
entry_connection_t * TO_ENTRY_CONN(connection_t *c)
edge_connection_t * TO_EDGE_CONN(connection_t *c)
Header file for connection_edge.c.
or_connection_t * TO_OR_CONN(connection_t *c)
void connection_or_close_normally(or_connection_t *orconn, int flush)
Header file for connection_or.c.
int control_event_server_status(int severity, const char *format,...)
Header file for control_events.c.
void crypto_digest_get_digest(crypto_digest_t *digest, char *out, size_t out_len)
#define crypto_digest_free(d)
void crypto_digest_add_bytes(crypto_digest_t *digest, const char *data, size_t len)
crypto_digest_t * crypto_digest_new(void)
void crypto_rand(char *to, size_t n)
Common functions for using (pseudo-)random number generators.
int crypto_pk_get_digest(const crypto_pk_t *pk, char *digest_out)
time_t accounting_get_end_time(void)
static time_t start_of_accounting_period_containing(time_t now)
int accounting_parse_options(const or_options_t *options, int validate_only)
static void wakeup_event_callback(mainloop_event_t *ev, void *data)
static void on_hibernate_state_change(hibernate_state_t prev_state)
int getinfo_helper_accounting(control_connection_t *conn, const char *question, char **answer, const char **errmsg)
int accounting_record_bandwidth_usage(time_t now, or_state_t *state)
static time_t interval_end_time
static void accounting_set_wakeup_time(void)
static uint32_t n_seconds_active_in_interval
static uint64_t expected_bandwidth_usage
static time_t shutdown_time
static time_t interval_start_time
static void hibernate_begin(hibernate_state_t new_state, time_t now)
void accounting_add_bytes(size_t n_read, size_t n_written, int seconds)
void consider_hibernation(time_t now)
int we_are_fully_hibernating(void)
void configure_accounting(time_t now)
static long length_of_accounting_period_containing(time_t now)
static mainloop_event_t * wakeup_event
static uint64_t n_bytes_at_soft_limit
int accounting_is_enabled(const or_options_t *options)
static hibernate_state_t hibernate_state
static int read_bandwidth_usage(void)
static void hibernate_end(hibernate_state_t new_state)
static void hibernate_schedule_wakeup_event(time_t now, time_t end_time)
static time_t start_of_accounting_period_after(time_t now)
static int hibernate_soft_limit_reached(void)
void accounting_free_all(void)
void accounting_run_housekeeping(time_t now)
int we_are_hibernating(void)
static time_t hibernate_end_time
static time_t edge_of_accounting_period_containing(time_t now, int get_end)
static const char * hibernate_state_to_string(hibernate_state_t state)
static void hibernate_end_time_elapsed(time_t now)
static time_t interval_wakeup_time
static int time_to_record_bandwidth_usage(time_t now)
static void reset_accounting(time_t now)
static int n_seconds_to_hit_soft_limit
static uint64_t n_bytes_written_in_interval
static int hibernate_hard_limit_reached(void)
void hibernate_begin_shutdown(void)
uint64_t get_accounting_bytes(void)
static void hibernate_go_dormant(time_t now)
static time_unit_t cfg_unit
static void update_expected_bandwidth(void)
static time_t soft_limit_hit_at
static uint64_t n_bytes_read_in_interval
int accounting_get_interval_length(void)
Header file for hibernate.c.
void mainloop_schedule_shutdown(int delay_sec)
void tor_shutdown_event_loop_and_exit(int exitcode)
void rescan_periodic_events(const or_options_t *options)
Header file for mainloop.c.
Master header file for Tor-specific functionality.
The or_state_t structure, which represents Tor's state file.
long tor_parse_long(const char *s, int base, long min, long max, int *ok, char **next)
int tor_asprintf(char **strp, const char *fmt,...)
int tor_snprintf(char *str, size_t size, const char *format,...)
int server_identity_key_is_set(void)
Header file for router.c.
smartlist_t * smartlist_new(void)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)
void or_state_mark_dirty(or_state_t *state, time_t when)
or_state_t * get_or_state(void)
uint64_t RelayBandwidthRate
time_t AccountingIntervalStart
#define MOCK_IMPL(rv, funcname, arglist)
Definitions for timing-related constants.
void format_iso_time(char *buf, time_t t)
void format_local_iso_time(char *buf, time_t t)
struct tm * tor_localtime_r(const time_t *timep, struct tm *result)
void tor_strlower(char *s)