From f6cc21874243b4d84a2db212e5c66058365bd7e7 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sat, 7 Aug 2004 02:46:16 +0000 Subject: Refactor ISO-style (yyyy-mm-dd hh:mm:ss) time parsing into util.c; rename format/parse_rfc1123_time; make rephist remember used bandwidth; published used bandwidth in descriptors in 15-minute chunks. Breaks unittests. svn:r2182 --- src/common/util.c | 40 ++++++++++++++++++++++++++++++++++++-- src/common/util.h | 7 +++++-- src/or/directory.c | 4 ++-- src/or/dirserv.c | 4 ++-- src/or/main.c | 2 +- src/or/or.h | 3 ++- src/or/rephist.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++--- src/or/router.c | 11 ++++++++--- src/or/routerparse.c | 42 +++------------------------------------- src/or/test.c | 9 +++++---- 10 files changed, 117 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/common/util.c b/src/common/util.c index 395e624ff..bc821fa59 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -9,6 +9,10 @@ * process control, and cross-platform portability. **/ +/* This is required on rh7 to make strptime not complain. + */ +#define _GNU_SOURCE + #include "orconfig.h" #ifdef MS_WINDOWS @@ -905,7 +909,7 @@ static const char *MONTH_NAMES[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; -void tor_format_rfc1123_time(char *buf, time_t t) { +void format_rfc1123_time(char *buf, time_t t) { struct tm *tm = gmtime(&t); strftime(buf, RFC1123_TIME_LEN+1, "XXX, %d XXX %Y %H:%M:%S GMT", tm); @@ -915,7 +919,7 @@ void tor_format_rfc1123_time(char *buf, time_t t) { memcpy(buf+8, MONTH_NAMES[tm->tm_mon], 3); } -int tor_parse_rfc1123_time(const char *buf, time_t *t) { +int parse_rfc1123_time(const char *buf, time_t *t) { struct tm tm; char month[4]; char weekday[4]; @@ -949,6 +953,38 @@ int tor_parse_rfc1123_time(const char *buf, time_t *t) { return 0; } +void format_iso_time(char *buf, time_t t) { + strftime(buf, ISO_TIME_LEN+1, "%Y-%m-%d %H:%M:%S", gmtime(&t)); +} + +int parse_iso_time(const char *cp, time_t *t) { + struct tm st_tm; +#ifdef HAVE_STRPTIME + if (!strptime(cp, "%Y-%m-%d %H:%M:%S", &st_tm)) { + log_fn(LOG_WARN, "Published time was unparseable"); return -1; + } +#else + unsigned int year=0, month=0, day=0, hour=100, minute=100, second=100; + if (sscanf(cp, "%u-%u-%u %u:%u:%u", &year, &month, + &day, &hour, &minute, &second) < 6) { + log_fn(LOG_WARN, "Published time was unparseable"); return -1; + } + if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || + hour > 23 || minute > 59 || second > 61) { + log_fn(LOG_WARN, "Published time was nonsensical"); return -1; + } + st_tm.tm_year = year; + st_tm.tm_mon = month-1; + st_tm.tm_mday = day; + st_tm.tm_hour = hour; + st_tm.tm_min = minute; + st_tm.tm_sec = second; +#endif + *t = tor_timegm(&st_tm); + return 0; +} + + /* * Low-level I/O. */ diff --git a/src/common/util.h b/src/common/util.h index 4dafccc52..792d5cffe 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -201,8 +201,11 @@ void tv_add(struct timeval *a, struct timeval *b); int tv_cmp(struct timeval *a, struct timeval *b); time_t tor_timegm(struct tm *tm); #define RFC1123_TIME_LEN 29 -void tor_format_rfc1123_time(char *buf, time_t t); -int tor_parse_rfc1123_time(const char *buf, time_t *t); +void format_rfc1123_time(char *buf, time_t t); +int parse_rfc1123_time(const char *buf, time_t *t); +#define ISO_TIME_LEN 19 +void format_iso_time(char *buf, time_t t); +int parse_iso_time(const char *buf, time_t *t); int write_all(int fd, const char *buf, size_t count, int isSocket); int read_all(int fd, char *buf, size_t count, int isSocket); diff --git a/src/or/directory.c b/src/or/directory.c index 5a2a85602..312646b6c 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -538,7 +538,7 @@ directory_handle_command_get(connection_t *conn, char *headers, return 0; } - tor_format_rfc1123_time(date, time(NULL)); + format_rfc1123_time(date, time(NULL)); snprintf(tmp, sizeof(tmp), "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\nContent-Type: text/plain\r\n\r\n", date, (int)dlen); @@ -563,7 +563,7 @@ directory_handle_command_get(connection_t *conn, char *headers, } switch(rend_cache_lookup_desc(url+strlen(rend_fetch_url), &descp, &desc_len)) { case 1: /* valid */ - tor_format_rfc1123_time(date, time(NULL)); + format_rfc1123_time(date, time(NULL)); snprintf(tmp, sizeof(tmp), "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\nContent-Type: application/octet-stream\r\n\r\n", date, desc_len); /* can't include descp here, because it's got nuls */ diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 57aacced6..15352ca4d 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -558,7 +558,7 @@ dirserv_dump_directory_to_string(char *s, unsigned int maxlen, return -1; dirserv_remove_old_servers(ROUTER_MAX_AGE); published_on = time(NULL); - strftime(published, 32, "%Y-%m-%d %H:%M:%S", gmtime(&published_on)); + format_iso_time(published, published_on); snprintf(s, maxlen, "signed-directory\n" "published %s\n" @@ -706,7 +706,7 @@ static int generate_runningrouters(crypto_pk_env_t *private_key) if (list_running_servers(&cp)) return -1; published_on = time(NULL); - strftime(published, 32, "%Y-%m-%d %H:%M:%S", gmtime(&published_on)); + format_iso_time(published, published_on); sprintf(s, "network-status\n" "published %s\n" "running-routers %s\n" diff --git a/src/or/main.c b/src/or/main.c index 2ebd02a91..93f6c239e 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -418,7 +418,7 @@ static void run_connection_housekeeping(int i, time_t now) { static int decide_if_publishable_server(time_t now) { int bw; - bw = rep_hist_bandwidth_assess(now); + bw = rep_hist_bandwidth_assess(); router_set_advertised_bandwidth(bw); if(options.ClientOnly) diff --git a/src/or/or.h b/src/or/or.h index df69cc28f..7303031d6 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1262,7 +1262,8 @@ void rep_hist_note_extend_failed(const char *from_name, const char *to_name); void rep_hist_dump_stats(time_t now, int severity); void rep_hist_note_bytes_read(int num_bytes, time_t when); void rep_hist_note_bytes_written(int num_bytes, time_t when); -int rep_hist_bandwidth_assess(time_t when); +int rep_hist_bandwidth_assess(void); +char *rep_hist_get_bandwidth_lines(void); /********************************* rendclient.c ***************************/ diff --git a/src/or/rephist.c b/src/or/rephist.c index 1935e1864..c766dd320 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -327,26 +327,37 @@ typedef struct bw_array_t { int total_obs; /**< Total for all members of obs except obs[cur_obs_idx] */ int max_total; /**< Largest value that total_obs has taken on in the current * period. */ + int total_in_period; /**< Total bytes transferred in the current period. */ /** When does the next period begin? */ time_t next_period; /** Where in 'maxima' should the maximum bandwidth usage for the current * period be stored? */ int next_max_idx; - /** Circular array of the maximum bandwidth usage for the last NUM_TOTALS - * periods */ + /** How many values in maxima/totals have been set ever? */ + int num_maxes_set; + /** Circular array of the maximum + * bandwidth-per-NUM_SECS_ROLLING_MEASURE usage for the last + * NUM_TOTALS periods */ int maxima[NUM_TOTALS]; + /** Circular array of the total bandwidth usage for the last NUM_TOTALS + * periods */ + int totals[NUM_TOTALS]; } bw_array_t; /** Shift the current period of b forward by one. */ static void commit_max(bw_array_t *b) { + /* Store total from current period. */ + b->totals[b->next_max_idx] = b->total_in_period; /* Store maximum from current period. */ b->maxima[b->next_max_idx++] = b->max_total; /* Advance next_period and next_max_idx */ b->next_period += NUM_SECS_BW_SUM_INTERVAL; if (b->next_max_idx == NUM_TOTALS) b->next_max_idx = 0; + if (b->num_maxes_set < NUM_TOTALS) + ++b->num_maxes_set; /* Reset max_total. */ b->max_total = 0; } @@ -388,6 +399,7 @@ static INLINE void add_obs(bw_array_t *b, time_t when, int n) { advance_obs(b); b->obs[b->cur_obs_idx] += n; + b->total_in_period += n; } /** Allocate, initialize, and return a new bw_array. @@ -463,7 +475,7 @@ static int find_largest_max(bw_array_t *b) * * Return the smaller of these sums, divided by NUM_SECS_ROLLING_MEASURE. */ -int rep_hist_bandwidth_assess(time_t when) { +int rep_hist_bandwidth_assess(void) { int w,r; r = find_largest_max(read_array); w = find_largest_max(write_array); @@ -475,6 +487,42 @@ int rep_hist_bandwidth_assess(time_t when) { return 0; } +/** + * DOCDOC + */ +char *rep_hist_get_bandwidth_lines(void) +{ + char *buf, *cp; + char t[ISO_TIME_LEN+1]; + int r, i, n; + bw_array_t *b; + size_t len; + + /* opt (read|write)history yyyy-mm-dd HH:MM:SS n,n,n,n,n... */ + len = (60+12*NUM_TOTALS)*2; + buf = tor_malloc_zero(len); + cp = buf; + for (r=0;r<2;++r) { + b = r?read_array:write_array; + format_iso_time(t, b->next_period-NUM_SECS_BW_SUM_INTERVAL); + sprintf(cp, "opt %s-history %s (%d s)", r?"read":"write", t, + NUM_SECS_BW_SUM_INTERVAL); + cp += strlen(cp); + for (i=b->num_maxes_set+1,n=0; nnum_maxes_set; ++n,++i) { + if (i >= NUM_TOTALS) i -= NUM_TOTALS; + if (n==(b->num_maxes_set-1)) + sprintf(cp, "%d", b->totals[i]); + else + sprintf(cp, "%d,", b->totals[i]); + cp += strlen(cp); + } + strcat(cp, "\n"); + ++cp; + } + return buf; +} + + /* Local Variables: mode:c diff --git a/src/or/router.c b/src/or/router.c index fb53c8a00..e5fbaff89 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -581,6 +581,7 @@ int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router, int written; int result=0; struct exit_policy_t *tmpe; + char *bandwidth_usage; #ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING char *s_tmp, *s_dup; const char *cp; @@ -615,8 +616,11 @@ int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router, } /* Encode the publication time. */ - strftime(published, 32, "%Y-%m-%d %H:%M:%S", gmtime(&router->published_on)); + format_iso_time(published, router->published_on); + /* How busy have we been? */ + bandwidth_usage = rep_hist_get_bandwidth_lines(); + /* Generate the easy portion of the router descriptor. */ result = snprintf(s, maxlen, "router %s %s %d %d %d\n" @@ -626,7 +630,7 @@ int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router, "opt uptime %ld\n" "bandwidth %d %d %d\n" "onion-key\n%s" - "signing-key\n%s", + "signing-key\n%s%s", router->nickname, router->address, router->or_port, @@ -642,7 +646,8 @@ int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router, (int) router->bandwidthrate, (int) router->bandwidthburst, (int) router->advertisedbandwidth, - onion_pkey, identity_pkey); + onion_pkey, identity_pkey, + bandwidth_usage); tor_free(onion_pkey); tor_free(identity_pkey); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 4995e765e..0a4d67778 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -8,10 +8,6 @@ * \brief Code to parse and validate router descriptors and directories. **/ -/* This is required on rh7 to make strptime not complain. - */ -#define _GNU_SOURCE - #include "or.h" /****************************************************************************/ @@ -164,38 +160,6 @@ int router_get_runningrouters_hash(const char *s, char *digest) "network-status","\ndirectory-signature"); } -/** Parse a date of the format "YYYY-MM-DD hh:mm:ss" and store the result into - * *t. - */ -/* XXX this should go in util.c, yes? -RD */ -static int parse_time(const char *cp, time_t *t) -{ - struct tm st_tm; -#ifdef HAVE_STRPTIME - if (!strptime(cp, "%Y-%m-%d %H:%M:%S", &st_tm)) { - log_fn(LOG_WARN, "Published time was unparseable"); return -1; - } -#else - unsigned int year=0, month=0, day=0, hour=100, minute=100, second=100; - if (sscanf(cp, "%u-%u-%u %u:%u:%u", &year, &month, - &day, &hour, &minute, &second) < 6) { - log_fn(LOG_WARN, "Published time was unparseable"); return -1; - } - if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || - hour > 23 || minute > 59 || second > 61) { - log_fn(LOG_WARN, "Published time was nonsensical"); return -1; - } - st_tm.tm_year = year; - st_tm.tm_mon = month-1; - st_tm.tm_mday = day; - st_tm.tm_hour = hour; - st_tm.tm_min = minute; - st_tm.tm_sec = second; -#endif - *t = tor_timegm(&st_tm); - return 0; -} - /** * Find the first instance of "recommended-software ...\n" at the start of * a line; return a newly allocated string containing the "..." portion. @@ -405,7 +369,7 @@ router_parse_routerlist_from_directory(const char *str, } tor_assert(tok->n_args == 1); - if (parse_time(tok->args[0], &published_on) < 0) { + if (parse_iso_time(tok->args[0], &published_on) < 0) { goto err; } @@ -517,7 +481,7 @@ router_parse_runningrouters(const char *str) goto err; } tor_assert(tok->n_args == 1); - if (parse_time(tok->args[0], &published_on) < 0) { + if (parse_iso_time(tok->args[0], &published_on) < 0) { goto err; } @@ -783,7 +747,7 @@ routerinfo_t *router_parse_entry_from_string(const char *s, log_fn(LOG_WARN, "Missing published time"); goto err; } tor_assert(tok->n_args == 1); - if (parse_time(tok->args[0], &router->published_on) < 0) + if (parse_iso_time(tok->args[0], &router->published_on) < 0) goto err; if (!(tok = find_first_by_keyword(tokens, K_ONION_KEY))) { diff --git a/src/or/test.c b/src/or/test.c index dd3951370..0a993fbf9 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -482,13 +482,13 @@ test_util() { a_time.tm_mday = 10; test_eq((time_t) 1076393695UL, tor_timegm(&a_time)); - tor_format_rfc1123_time(timestr, 0); + format_rfc1123_time(timestr, 0); test_streq("Thu, 01 Jan 1970 00:00:00 GMT", timestr); - tor_format_rfc1123_time(timestr, (time_t)1091580502UL); + format_rfc1123_time(timestr, (time_t)1091580502UL); test_streq("Wed, 04 Aug 2004 00:48:22 GMT", timestr); t_res = 0; - i = tor_parse_rfc1123_time(timestr, &t_res); + i = parse_rfc1123_time(timestr, &t_res); test_eq(i,0); test_eq(t_res, (time_t)1091580502UL); @@ -923,8 +923,9 @@ main(int c, char**v){ #endif crypto_seed_rng(); - setup_directory(); + rep_hist_init(); + // puts("========================== Buffers ========================="); // test_buffers(); puts("\n========================== Crypto =========================="); -- cgit v1.2.3