fp_pair_map_iter_t * fp_pair_map_iter_next(fp_pair_map_t *map, fp_pair_map_iter_t *iter) { tor_assert(map); tor_assert(iter); return HT_NEXT(fp_pair_map_impl, &(map->head), iter); }
/** Clear history of connecting clients used by entry and bridge stats. */ static void client_history_clear(void) { clientmap_entry_t **ent, **next, *this; for (ent = HT_START(clientmap, &client_history); ent != NULL; ent = next) { if ((*ent)->action == GEOIP_CLIENT_CONNECT) { this = *ent; next = HT_NEXT_RMV(clientmap, &client_history, ent); tor_free(this); } else { next = HT_NEXT(clientmap, &client_history, ent); } } }
/** Return a newly allocated comma-separated string containing statistics * on network status downloads. The string contains the number of completed * requests, timeouts, and still running requests as well as the download * times by deciles and quartiles. Return NULL if we have not observed * requests for long enough. */ static char * geoip_get_dirreq_history(geoip_client_action_t action, dirreq_type_t type) { char *result = NULL; smartlist_t *dirreq_completed = NULL; uint32_t complete = 0, timeouts = 0, running = 0; int bufsize = 1024, written; dirreq_map_entry_t **ptr, **next, *ent; struct timeval now; tor_gettimeofday(&now); if (action != GEOIP_CLIENT_NETWORKSTATUS && action != GEOIP_CLIENT_NETWORKSTATUS_V2) return NULL; dirreq_completed = smartlist_new(); for (ptr = HT_START(dirreqmap, &dirreq_map); ptr; ptr = next) { ent = *ptr; if (ent->action != action || ent->type != type) { next = HT_NEXT(dirreqmap, &dirreq_map, ptr); continue; } else { if (ent->completed) { smartlist_add(dirreq_completed, ent); complete++; next = HT_NEXT_RMV(dirreqmap, &dirreq_map, ptr); } else { if (tv_mdiff(&ent->request_time, &now) / 1000 > DIRREQ_TIMEOUT) timeouts++; else running++; next = HT_NEXT_RMV(dirreqmap, &dirreq_map, ptr); tor_free(ent); } } } #define DIR_REQ_GRANULARITY 4 complete = round_uint32_to_next_multiple_of(complete, DIR_REQ_GRANULARITY); timeouts = round_uint32_to_next_multiple_of(timeouts, DIR_REQ_GRANULARITY); running = round_uint32_to_next_multiple_of(running, DIR_REQ_GRANULARITY); result = tor_malloc_zero(bufsize); written = tor_snprintf(result, bufsize, "complete=%u,timeout=%u," "running=%u", complete, timeouts, running); if (written < 0) { tor_free(result); goto done; } #define MIN_DIR_REQ_RESPONSES 16 if (complete >= MIN_DIR_REQ_RESPONSES) { uint32_t *dltimes; /* We may have rounded 'completed' up. Here we want to use the * real value. */ complete = smartlist_len(dirreq_completed); dltimes = tor_malloc_zero(sizeof(uint32_t) * complete); SMARTLIST_FOREACH_BEGIN(dirreq_completed, dirreq_map_entry_t *, ent) { uint32_t bytes_per_second; uint32_t time_diff = (uint32_t) tv_mdiff(&ent->request_time, &ent->completion_time); if (time_diff == 0) time_diff = 1; /* Avoid DIV/0; "instant" answers are impossible * by law of nature or something, but a milisecond * is a bit greater than "instantly" */ bytes_per_second = (uint32_t)(1000 * ent->response_size / time_diff); dltimes[ent_sl_idx] = bytes_per_second; } SMARTLIST_FOREACH_END(ent);