Comments for nearly all non-tricky files
[tor.git] / src / or / rephist.c
blob7ab0a723969fd5ab2b030359b8fc0c70906a4059
1 /* Copyright 2004 Roger Dingledine */
2 /* See LICENSE for licensing information */
3 /* $Id$ */
5 /*****
6 * rephist.c: Basic history functionality for reputation module.
7 *****/
9 #include "or.h"
11 /* History of an or->or link. */
12 typedef struct link_history_t {
13 /* When did we start tracking this list? */
14 time_t since;
15 /* How many times did extending from OR1 to OR2 succeeed? */
16 unsigned long n_extend_ok;
17 /* How many times did extending from OR1 to OR2 fail? */
18 unsigned long n_extend_fail;
19 } link_history_t;
21 /* History of an OR. */
22 typedef struct or_history_t {
23 /* When did we start tracking this OR? */
24 time_t since;
25 /* How many times did we successfully connect? */
26 unsigned long n_conn_ok;
27 /*How many times did we try to connect and fail?*/
28 unsigned long n_conn_fail;
29 /* How many seconds have we been connected to this OR before
30 * 'up_since'? */
31 unsigned long uptime;
32 /* How many seconds have we been unable to connect to this OR before
33 * 'down_since'? */
34 unsigned long downtime;
35 /* If nonzero, we have been connected since this time. */
36 time_t up_since;
37 /* If nonzero, we have been unable to connect since this time. */
38 time_t down_since;
39 /* Map from lowercased OR2 name to a link_history_t for the link
40 * from this OR to OR2. */
41 strmap_t *link_history_map;
42 } or_history_t;
44 /* Map from lowercased OR nickname to or_history_t. */
45 static strmap_t *history_map = NULL;
47 /* Return the or_history_t for the named OR, creating it if necessary.
49 static or_history_t *get_or_history(const char* nickname)
51 or_history_t *hist;
52 hist = (or_history_t*) strmap_get(history_map, nickname);
53 if (!hist) {
54 hist = tor_malloc_zero(sizeof(or_history_t));
55 hist->link_history_map = strmap_new();
56 hist->since = time(NULL);
57 strmap_set(history_map, nickname, hist);
59 return hist;
62 /* Return the link_history_t for the link from the first named OR to
63 * the second, creating it if necessary.
65 static link_history_t *get_link_history(const char *from_name,
66 const char *to_name)
68 or_history_t *orhist;
69 link_history_t *lhist;
70 orhist = get_or_history(from_name);
71 lhist = (link_history_t*) strmap_get(orhist->link_history_map, to_name);
72 if (!lhist) {
73 lhist = tor_malloc_zero(sizeof(link_history_t));
74 lhist->since = time(NULL);
75 strmap_set(orhist->link_history_map, to_name, lhist);
77 return lhist;
80 /* Update an or_history_t object so that its uptime/downtime count is
81 * up-to-date as of 'when'.
83 static void update_or_history(or_history_t *hist, time_t when)
85 tor_assert(hist);
86 if (hist->up_since) {
87 tor_assert(!hist->down_since);
88 hist->uptime += (when - hist->up_since);
89 hist->up_since = when;
90 } else if (hist->down_since) {
91 hist->downtime += (when - hist->down_since);
92 hist->down_since = when;
96 /* Initialize the static data structures for tracking history.
98 void rep_hist_init(void)
100 history_map = strmap_new();
103 /* Remember that an attempt to connect to the OR 'nickname' failed at
104 * 'when'.
106 void rep_hist_note_connect_failed(const char* nickname, time_t when)
108 or_history_t *hist;
109 hist = get_or_history(nickname);
110 ++hist->n_conn_fail;
111 if (hist->up_since) {
112 hist->uptime += (when - hist->up_since);
113 hist->up_since = 0;
115 if (!hist->down_since)
116 hist->down_since = when;
119 /* Remember that an attempt to connect to the OR 'nickname' succeeded
120 * at 'when'.
122 void rep_hist_note_connect_succeeded(const char* nickname, time_t when)
124 or_history_t *hist;
125 hist = get_or_history(nickname);
126 ++hist->n_conn_ok;
127 if (hist->down_since) {
128 hist->downtime += (when - hist->down_since);
129 hist->down_since = 0;
131 if (!hist->up_since)
132 hist->up_since = when;
135 /* Remember that we intentionally closed our connection to the OR
136 * 'nickname' at 'when'.
138 void rep_hist_note_disconnect(const char* nickname, time_t when)
140 or_history_t *hist;
141 hist = get_or_history(nickname);
142 ++hist->n_conn_ok;
143 if (hist->up_since) {
144 hist->uptime += (when - hist->up_since);
145 hist->up_since = 0;
149 /* Remember that our connection to the OR 'nickname' had an error and
150 * stopped working at 'when'.
152 void rep_hist_note_connection_died(const char* nickname, time_t when)
154 or_history_t *hist;
155 if(!nickname) {
156 /* XXX
157 * If conn has no nickname, it's either an OP, or it is an OR
158 * which didn't complete its handshake (or did and was unapproved).
159 * Ignore it. Is there anything better we could do?
161 return;
163 hist = get_or_history(nickname);
164 if (hist->up_since) {
165 hist->uptime += (when - hist->up_since);
166 hist->up_since = 0;
168 if (!hist->down_since)
169 hist->down_since = when;
172 /* Remember that we successfully extended from the OR 'from_name' to
173 * the OR 'to_name'.
175 void rep_hist_note_extend_succeeded(const char *from_name,
176 const char *to_name)
178 link_history_t *hist;
179 /* log_fn(LOG_WARN, "EXTEND SUCCEEDED: %s->%s",from_name,to_name); */
180 hist = get_link_history(from_name, to_name);
181 ++hist->n_extend_ok;
184 /* Remember that we tried to extend from the OR 'from_name' to the OR
185 * 'to_name', but failed.
187 void rep_hist_note_extend_failed(const char *from_name, const char *to_name)
189 link_history_t *hist;
190 /* log_fn(LOG_WARN, "EXTEND FAILED: %s->%s",from_name,to_name); */
191 hist = get_link_history(from_name, to_name);
192 ++hist->n_extend_fail;
195 /* Log all the reliability data we have rememberred, with the chosen
196 * severity.
198 void rep_hist_dump_stats(time_t now, int severity)
200 strmap_iter_t *lhist_it;
201 strmap_iter_t *orhist_it;
202 const char *name1, *name2;
203 or_history_t *or_history;
204 link_history_t *link_history;
205 void *or_history_p, *link_history_p;
206 double uptime;
207 char buffer[2048];
208 int len;
209 unsigned long upt, downt;
211 log(severity, "--------------- Dumping history information:");
213 for (orhist_it = strmap_iter_init(history_map); !strmap_iter_done(orhist_it);
214 orhist_it = strmap_iter_next(history_map,orhist_it)) {
215 strmap_iter_get(orhist_it, &name1, &or_history_p);
216 or_history = (or_history_t*) or_history_p;
218 update_or_history(or_history, now);
219 upt = or_history->uptime;
220 downt = or_history->downtime;
221 if (upt+downt) {
222 uptime = ((double)upt) / (upt+downt);
223 } else {
224 uptime=1.0;
226 log(severity,
227 "OR %s: %ld/%ld good connections; uptime %ld/%ld sec (%.2f%%)",
228 name1,
229 or_history->n_conn_ok, or_history->n_conn_fail+or_history->n_conn_ok,
230 upt, upt+downt, uptime*100.0);
232 strcpy(buffer, " Good extend attempts: ");
233 len = strlen(buffer);
234 for (lhist_it = strmap_iter_init(or_history->link_history_map);
235 !strmap_iter_done(lhist_it);
236 lhist_it = strmap_iter_next(or_history->link_history_map, lhist_it)) {
237 strmap_iter_get(lhist_it, &name2, &link_history_p);
238 link_history = (link_history_t*) link_history_p;
239 len += snprintf(buffer+len, 2048-len, "%s(%ld/%ld); ", name2,
240 link_history->n_extend_ok,
241 link_history->n_extend_ok+link_history->n_extend_fail);
242 if (len >= 2048) {
243 buffer[2047]='\0';
244 break;
247 log(severity, buffer);
252 Local Variables:
253 mode:c
254 indent-tabs-mode:nil
255 c-basic-offset:2
256 End: