1 /* Copyright 2004 Roger Dingledine */
2 /* See LICENSE for licensing information */
6 * rephist.c: Basic history functionality for reputation module.
11 /* History of an or->or link. */
12 typedef struct link_history_t
{
13 /* When did we start tracking this list? */
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
;
21 /* History of an OR. */
22 typedef struct or_history_t
{
23 /* When did we start tracking this OR? */
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
32 /* How many seconds have we been unable to connect to this OR before
34 unsigned long downtime
;
35 /* If nonzero, we have been connected since this time. */
37 /* If nonzero, we have been unable to connect since this time. */
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
;
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
)
52 hist
= (or_history_t
*) strmap_get(history_map
, nickname
);
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
);
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
,
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
);
73 lhist
= tor_malloc_zero(sizeof(link_history_t
));
74 lhist
->since
= time(NULL
);
75 strmap_set(orhist
->link_history_map
, to_name
, 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
)
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
106 void rep_hist_note_connect_failed(const char* nickname
, time_t when
)
109 hist
= get_or_history(nickname
);
111 if (hist
->up_since
) {
112 hist
->uptime
+= (when
- hist
->up_since
);
115 if (!hist
->down_since
)
116 hist
->down_since
= when
;
119 /* Remember that an attempt to connect to the OR 'nickname' succeeded
122 void rep_hist_note_connect_succeeded(const char* nickname
, time_t when
)
125 hist
= get_or_history(nickname
);
127 if (hist
->down_since
) {
128 hist
->downtime
+= (when
- hist
->down_since
);
129 hist
->down_since
= 0;
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
)
141 hist
= get_or_history(nickname
);
143 if (hist
->up_since
) {
144 hist
->uptime
+= (when
- hist
->up_since
);
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
)
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?
163 hist
= get_or_history(nickname
);
164 if (hist
->up_since
) {
165 hist
->uptime
+= (when
- hist
->up_since
);
168 if (!hist
->down_since
)
169 hist
->down_since
= when
;
172 /* Remember that we successfully extended from the OR 'from_name' to
175 void rep_hist_note_extend_succeeded(const char *from_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
);
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
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
;
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
;
222 uptime
= ((double)upt
) / (upt
+downt
);
227 "OR %s: %ld/%ld good connections; uptime %ld/%ld sec (%.2f%%)",
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
);
247 log(severity
, buffer
);