123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801 |
- const char rephist_c_id[] =
- "$Id$";
- #include "or.h"
- static void bw_arrays_init(void);
- static void predicted_ports_init(void);
- uint64_t rephist_total_alloc=0;
- uint32_t rephist_total_num=0;
- typedef struct link_history_t {
-
- time_t since;
-
- time_t changed;
-
- unsigned long n_extend_ok;
-
- unsigned long n_extend_fail;
- } link_history_t;
- typedef struct or_history_t {
-
- time_t since;
-
- time_t changed;
-
- unsigned long n_conn_ok;
-
- unsigned long n_conn_fail;
-
- unsigned long uptime;
-
- unsigned long downtime;
-
- time_t up_since;
-
- time_t down_since;
-
- digestmap_t *link_history_map;
- } or_history_t;
- static digestmap_t *history_map = NULL;
- static or_history_t *
- get_or_history(const char* id)
- {
- or_history_t *hist;
- if (!memcmp(id, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", DIGEST_LEN))
- return NULL;
- hist = digestmap_get(history_map, id);
- if (!hist) {
- hist = tor_malloc_zero(sizeof(or_history_t));
- rephist_total_alloc += sizeof(or_history_t);
- rephist_total_num++;
- hist->link_history_map = digestmap_new();
- hist->since = hist->changed = time(NULL);
- digestmap_set(history_map, id, hist);
- }
- return hist;
- }
- static link_history_t *
- get_link_history(const char *from_id, const char *to_id)
- {
- or_history_t *orhist;
- link_history_t *lhist;
- orhist = get_or_history(from_id);
- if (!orhist)
- return NULL;
- if (!memcmp(to_id, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", DIGEST_LEN))
- return NULL;
- lhist = (link_history_t*) digestmap_get(orhist->link_history_map, to_id);
- if (!lhist) {
- lhist = tor_malloc_zero(sizeof(link_history_t));
- rephist_total_alloc += sizeof(link_history_t);
- lhist->since = lhist->changed = time(NULL);
- digestmap_set(orhist->link_history_map, to_id, lhist);
- }
- return lhist;
- }
- static void
- _free_link_history(void *val)
- {
- rephist_total_alloc -= sizeof(link_history_t);
- tor_free(val);
- }
- static void
- free_or_history(void *_hist)
- {
- or_history_t *hist = _hist;
- digestmap_free(hist->link_history_map, _free_link_history);
- rephist_total_alloc -= sizeof(or_history_t);
- rephist_total_num--;
- tor_free(hist);
- }
- static void
- update_or_history(or_history_t *hist, time_t when)
- {
- tor_assert(hist);
- if (hist->up_since) {
- tor_assert(!hist->down_since);
- hist->uptime += (when - hist->up_since);
- hist->up_since = when;
- } else if (hist->down_since) {
- hist->downtime += (when - hist->down_since);
- hist->down_since = when;
- }
- }
- void
- rep_hist_init(void)
- {
- history_map = digestmap_new();
- bw_arrays_init();
- predicted_ports_init();
- }
- void
- rep_hist_note_connect_failed(const char* id, time_t when)
- {
- or_history_t *hist;
- hist = get_or_history(id);
- if (!hist)
- return;
- ++hist->n_conn_fail;
- if (hist->up_since) {
- hist->uptime += (when - hist->up_since);
- hist->up_since = 0;
- }
- if (!hist->down_since)
- hist->down_since = when;
- hist->changed = when;
- }
- void
- rep_hist_note_connect_succeeded(const char* id, time_t when)
- {
- or_history_t *hist;
- hist = get_or_history(id);
- if (!hist)
- return;
- ++hist->n_conn_ok;
- if (hist->down_since) {
- hist->downtime += (when - hist->down_since);
- hist->down_since = 0;
- }
- if (!hist->up_since)
- hist->up_since = when;
- hist->changed = when;
- }
- void
- rep_hist_note_disconnect(const char* id, time_t when)
- {
- or_history_t *hist;
- hist = get_or_history(id);
- if (!hist)
- return;
- ++hist->n_conn_ok;
- if (hist->up_since) {
- hist->uptime += (when - hist->up_since);
- hist->up_since = 0;
- }
- hist->changed = when;
- }
- void
- rep_hist_note_connection_died(const char* id, time_t when)
- {
- or_history_t *hist;
- if (!id) {
-
-
- return;
- }
- hist = get_or_history(id);
- if (!hist)
- return;
- if (hist->up_since) {
- hist->uptime += (when - hist->up_since);
- hist->up_since = 0;
- }
- if (!hist->down_since)
- hist->down_since = when;
- hist->changed = when;
- }
- void
- rep_hist_note_extend_succeeded(const char *from_id, const char *to_id)
- {
- link_history_t *hist;
-
- hist = get_link_history(from_id, to_id);
- if (!hist)
- return;
- ++hist->n_extend_ok;
- hist->changed = time(NULL);
- }
- void
- rep_hist_note_extend_failed(const char *from_id, const char *to_id)
- {
- link_history_t *hist;
-
- hist = get_link_history(from_id, to_id);
- if (!hist)
- return;
- ++hist->n_extend_fail;
- hist->changed = time(NULL);
- }
- void
- rep_hist_dump_stats(time_t now, int severity)
- {
- digestmap_iter_t *lhist_it;
- digestmap_iter_t *orhist_it;
- const char *name1, *name2, *digest1, *digest2;
- char hexdigest1[HEX_DIGEST_LEN+1];
- or_history_t *or_history;
- link_history_t *link_history;
- void *or_history_p, *link_history_p;
- double uptime;
- char buffer[2048];
- size_t len;
- int ret;
- unsigned long upt, downt;
- routerinfo_t *r;
- rep_history_clean(now - get_options()->RephistTrackTime);
- log(severity, LD_GENERAL, "--------------- Dumping history information:");
- for (orhist_it = digestmap_iter_init(history_map);
- !digestmap_iter_done(orhist_it);
- orhist_it = digestmap_iter_next(history_map,orhist_it)) {
- digestmap_iter_get(orhist_it, &digest1, &or_history_p);
- or_history = (or_history_t*) or_history_p;
- if ((r = router_get_by_digest(digest1)))
- name1 = r->nickname;
- else
- name1 = "(unknown)";
- base16_encode(hexdigest1, sizeof(hexdigest1), digest1, DIGEST_LEN);
- update_or_history(or_history, now);
- upt = or_history->uptime;
- downt = or_history->downtime;
- if (upt+downt) {
- uptime = ((double)upt) / (upt+downt);
- } else {
- uptime=1.0;
- }
- log(severity, LD_GENERAL,
- "OR %s [%s]: %ld/%ld good connections; uptime %ld/%ld sec (%.2f%%)",
- name1, hexdigest1,
- or_history->n_conn_ok, or_history->n_conn_fail+or_history->n_conn_ok,
- upt, upt+downt, uptime*100.0);
- if (!digestmap_isempty(or_history->link_history_map)) {
- strlcpy(buffer, " Extend attempts: ", sizeof(buffer));
- len = strlen(buffer);
- for (lhist_it = digestmap_iter_init(or_history->link_history_map);
- !digestmap_iter_done(lhist_it);
- lhist_it = digestmap_iter_next(or_history->link_history_map,
- lhist_it)) {
- digestmap_iter_get(lhist_it, &digest2, &link_history_p);
- if ((r = router_get_by_digest(digest2)))
- name2 = r->nickname;
- else
- name2 = "(unknown)";
- link_history = (link_history_t*) link_history_p;
- ret = tor_snprintf(buffer+len, 2048-len, "%s(%ld/%ld); ", name2,
- link_history->n_extend_ok,
- link_history->n_extend_ok+link_history->n_extend_fail);
- if (ret<0)
- break;
- else
- len += ret;
- }
- log(severity, LD_GENERAL, "%s", buffer);
- }
- }
- }
- void
- rep_history_clean(time_t before)
- {
- or_history_t *or_history;
- link_history_t *link_history;
- void *or_history_p, *link_history_p;
- digestmap_iter_t *orhist_it, *lhist_it;
- const char *d1, *d2;
- orhist_it = digestmap_iter_init(history_map);
- while (!digestmap_iter_done(orhist_it)) {
- digestmap_iter_get(orhist_it, &d1, &or_history_p);
- or_history = or_history_p;
- if (or_history->changed < before) {
- orhist_it = digestmap_iter_next_rmv(history_map, orhist_it);
- free_or_history(or_history);
- continue;
- }
- for (lhist_it = digestmap_iter_init(or_history->link_history_map);
- !digestmap_iter_done(lhist_it); ) {
- digestmap_iter_get(lhist_it, &d2, &link_history_p);
- link_history = link_history_p;
- if (link_history->changed < before) {
- lhist_it = digestmap_iter_next_rmv(or_history->link_history_map,
- lhist_it);
- rephist_total_alloc -= sizeof(link_history_t);
- tor_free(link_history);
- continue;
- }
- lhist_it = digestmap_iter_next(or_history->link_history_map,lhist_it);
- }
- orhist_it = digestmap_iter_next(history_map, orhist_it);
- }
- }
- #define NUM_SECS_ROLLING_MEASURE 10
- #define NUM_SECS_BW_SUM_IS_VALID (24*60*60)
- #define NUM_SECS_BW_SUM_INTERVAL (15*60)
- #define NUM_TOTALS (NUM_SECS_BW_SUM_IS_VALID/NUM_SECS_BW_SUM_INTERVAL)
- typedef struct bw_array_t {
-
- int obs[NUM_SECS_ROLLING_MEASURE];
- int cur_obs_idx;
- time_t cur_obs_time;
- int total_obs;
- int max_total;
- uint64_t total_in_period;
-
- time_t next_period;
-
- int next_max_idx;
-
- int num_maxes_set;
-
- int maxima[NUM_TOTALS];
-
- uint64_t totals[NUM_TOTALS];
- } bw_array_t;
- static void
- commit_max(bw_array_t *b)
- {
-
- b->totals[b->next_max_idx] = b->total_in_period;
-
- b->maxima[b->next_max_idx++] = b->max_total;
-
- 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;
-
- b->max_total = 0;
-
- b->total_in_period = 0;
- }
- static INLINE void
- advance_obs(bw_array_t *b)
- {
- int nextidx;
- int total;
-
- total = b->total_obs + b->obs[b->cur_obs_idx];
- if (total > b->max_total)
- b->max_total = total;
- nextidx = b->cur_obs_idx+1;
- if (nextidx == NUM_SECS_ROLLING_MEASURE)
- nextidx = 0;
- b->total_obs = total - b->obs[nextidx];
- b->obs[nextidx]=0;
- b->cur_obs_idx = nextidx;
- if (++b->cur_obs_time >= b->next_period)
- commit_max(b);
- }
- static INLINE void
- add_obs(bw_array_t *b, time_t when, int n)
- {
-
- if (when<b->cur_obs_time)
- return;
-
- while (when>b->cur_obs_time)
- advance_obs(b);
- b->obs[b->cur_obs_idx] += n;
- b->total_in_period += n;
- }
- static bw_array_t *
- bw_array_new(void)
- {
- bw_array_t *b;
- time_t start;
- b = tor_malloc_zero(sizeof(bw_array_t));
- rephist_total_alloc += sizeof(bw_array_t);
- start = time(NULL);
- b->cur_obs_time = start;
- b->next_period = start + NUM_SECS_BW_SUM_INTERVAL;
- return b;
- }
- static bw_array_t *read_array = NULL;
- static bw_array_t *write_array = NULL;
- static void
- bw_arrays_init(void)
- {
- read_array = bw_array_new();
- write_array = bw_array_new();
- }
- void
- rep_hist_note_bytes_written(int num_bytes, time_t when)
- {
- add_obs(write_array, when, num_bytes);
- }
- void
- rep_hist_note_bytes_read(int num_bytes, time_t when)
- {
- add_obs(read_array, when, num_bytes);
- }
- static int
- find_largest_max(bw_array_t *b)
- {
- int i,max;
- max=0;
- for (i=0; i<NUM_TOTALS; ++i) {
- if (b->maxima[i]>max)
- max = b->maxima[i];
- }
- return max;
- }
- int
- rep_hist_bandwidth_assess(void)
- {
- int w,r;
- r = find_largest_max(read_array);
- w = find_largest_max(write_array);
- if (r>w)
- return (int)(w/(double)NUM_SECS_ROLLING_MEASURE);
- else
- return (int)(r/(double)NUM_SECS_ROLLING_MEASURE);
- return 0;
- }
- 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;
-
- len = (60+20*NUM_TOTALS)*2;
- buf = tor_malloc_zero(len);
- cp = buf;
- for (r=0;r<2;++r) {
- b = r?read_array:write_array;
- tor_assert(b);
- format_iso_time(t, b->next_period-NUM_SECS_BW_SUM_INTERVAL);
- tor_snprintf(cp, len-(cp-buf), "opt %s %s (%d s) ",
- r ? "read-history" : "write-history", t,
- NUM_SECS_BW_SUM_INTERVAL);
- cp += strlen(cp);
- if (b->num_maxes_set <= b->next_max_idx)
-
- i = 0;
- else
-
- i = b->next_max_idx;
- for (n=0; n<b->num_maxes_set; ++n,++i) {
- while (i >= NUM_TOTALS) i -= NUM_TOTALS;
- if (n==(b->num_maxes_set-1))
- tor_snprintf(cp, len-(cp-buf), U64_FORMAT,
- U64_PRINTF_ARG(b->totals[i]));
- else
- tor_snprintf(cp, len-(cp-buf), U64_FORMAT",",
- U64_PRINTF_ARG(b->totals[i]));
- cp += strlen(cp);
- }
- strlcat(cp, "\n", len-(cp-buf));
- ++cp;
- }
- return buf;
- }
- static smartlist_t *predicted_ports_list=NULL;
- static smartlist_t *predicted_ports_times=NULL;
- static void
- add_predicted_port(uint16_t port, time_t now)
- {
-
- uint16_t *tmp_port = tor_malloc(sizeof(uint16_t));
- time_t *tmp_time = tor_malloc(sizeof(time_t));
- *tmp_port = port;
- *tmp_time = now;
- rephist_total_alloc += sizeof(uint16_t) + sizeof(time_t);
- smartlist_add(predicted_ports_list, tmp_port);
- smartlist_add(predicted_ports_times, tmp_time);
- }
- static void
- predicted_ports_init(void)
- {
- predicted_ports_list = smartlist_create();
- predicted_ports_times = smartlist_create();
- add_predicted_port(80, time(NULL));
- }
- static void
- predicted_ports_free(void)
- {
- rephist_total_alloc -= smartlist_len(predicted_ports_list)*sizeof(uint16_t);
- SMARTLIST_FOREACH(predicted_ports_list, char *, cp, tor_free(cp));
- smartlist_free(predicted_ports_list);
- rephist_total_alloc -= smartlist_len(predicted_ports_times)*sizeof(time_t);
- SMARTLIST_FOREACH(predicted_ports_times, char *, cp, tor_free(cp));
- smartlist_free(predicted_ports_times);
- }
- void
- rep_hist_note_used_port(uint16_t port, time_t now)
- {
- int i;
- uint16_t *tmp_port;
- time_t *tmp_time;
- tor_assert(predicted_ports_list);
- tor_assert(predicted_ports_times);
- if (!port)
- return;
- for (i = 0; i < smartlist_len(predicted_ports_list); ++i) {
- tmp_port = smartlist_get(predicted_ports_list, i);
- tmp_time = smartlist_get(predicted_ports_times, i);
- if (*tmp_port == port) {
- *tmp_time = now;
- return;
- }
- }
-
- add_predicted_port(port, now);
- }
- #define PREDICTED_CIRCS_RELEVANCE_TIME (3600)
- smartlist_t *
- rep_hist_get_predicted_ports(time_t now)
- {
- int i;
- uint16_t *tmp_port;
- time_t *tmp_time;
- tor_assert(predicted_ports_list);
- tor_assert(predicted_ports_times);
-
- for (i = 0; i < smartlist_len(predicted_ports_list); ++i) {
- tmp_time = smartlist_get(predicted_ports_times, i);
- if (*tmp_time + PREDICTED_CIRCS_RELEVANCE_TIME < now) {
- tmp_port = smartlist_get(predicted_ports_list, i);
- debug(LD_CIRC, "Expiring predicted port %d", *tmp_port);
- smartlist_del(predicted_ports_list, i);
- smartlist_del(predicted_ports_times, i);
- rephist_total_alloc -= sizeof(uint16_t)+sizeof(time_t);
- tor_free(tmp_port);
- tor_free(tmp_time);
- i--;
- }
- }
- return predicted_ports_list;
- }
- void
- rep_hist_note_used_resolve(time_t now)
- {
- rep_hist_note_used_port(80, now);
- }
- #if 0
- int
- rep_hist_get_predicted_resolve(time_t now)
- {
- return 0;
- }
- #endif
- static time_t predicted_internal_time = 0;
- static time_t predicted_internal_uptime_time = 0;
- static time_t predicted_internal_capacity_time = 0;
- void
- rep_hist_note_used_internal(time_t now, int need_uptime, int need_capacity)
- {
- predicted_internal_time = now;
- if (need_uptime)
- predicted_internal_uptime_time = now;
- if (need_capacity)
- predicted_internal_capacity_time = now;
- }
- int
- rep_hist_get_predicted_internal(time_t now, int *need_uptime,
- int *need_capacity)
- {
- if (!predicted_internal_time) {
- predicted_internal_time = now;
- predicted_internal_uptime_time = now;
- predicted_internal_capacity_time = now;
- }
- if (predicted_internal_time + PREDICTED_CIRCS_RELEVANCE_TIME < now)
- return 0;
- if (predicted_internal_uptime_time + PREDICTED_CIRCS_RELEVANCE_TIME < now)
- *need_uptime = 1;
- if (predicted_internal_capacity_time + PREDICTED_CIRCS_RELEVANCE_TIME < now)
- *need_capacity = 1;
- return 1;
- }
- void
- rep_hist_free_all(void)
- {
- digestmap_free(history_map, free_or_history);
- tor_free(read_array);
- tor_free(write_array);
- predicted_ports_free();
- }
|