Change networkstatus dl logic: try to have all networkstatuses live; insist on having all of them live or tried-at-least-once. Also, answer a XXXX comment.

svn:r6297
This commit is contained in:
Nick Mathewson 2006-04-02 23:02:52 +00:00
parent d663bfa306
commit 4130460f8e

View File

@ -2102,10 +2102,9 @@ router_set_networkstatus(const char *s, time_t arrived_at,
if (!trusted_dir) {
if (!skewed && get_options()->DirPort) {
/* XXX This is great as a first cut, but it looks like
* any old person can give us an untrusted network-status and
* we'll write it to disk as the newest one we have?
* Also, there is no limit on the number that we'll store? -RD */
/* We got a non-trusted networkstatus, and we're a directory cache.
* This means that we asked an authority, and it told us about another
* authority we didn't recognize. */
add_networkstatus_to_cache(s, source, ns);
networkstatus_free(ns);
}
@ -2335,19 +2334,21 @@ update_networkstatus_cache_downloads(time_t now)
static void
update_networkstatus_client_downloads(time_t now)
{
int n_live = 0, needed = 0, n_running_dirservers, n_dirservers, i;
int n_live = 0, n_dirservers, n_running_dirservers, needed = 0;
int fetch_latest = 0;
int most_recent_idx = -1;
trusted_dir_server_t *most_recent = NULL;
time_t most_recent_received = 0;
char *resource, *cp;
size_t resource_len;
smartlist_t *missing;
if (connection_get_by_type_purpose(CONN_TYPE_DIR,
DIR_PURPOSE_FETCH_NETWORKSTATUS))
return;
/* This is a little tricky. We want to download enough network-status
* objects so that we have at least half of them under
* objects so that we have all of them under
* NETWORKSTATUS_MAX_AGE publication time. We want to download a new
* *one* if the most recent one's publication time is under
* NETWORKSTATUS_CLIENT_DL_INTERVAL.
@ -2355,77 +2356,82 @@ update_networkstatus_client_downloads(time_t now)
if (!trusted_dir_servers || !smartlist_len(trusted_dir_servers))
return;
n_dirservers = n_running_dirservers = smartlist_len(trusted_dir_servers);
missing = smartlist_create();
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
{
networkstatus_t *ns = networkstatus_get_by_digest(ds->digest);
if (!ns)
continue;
if (ds->n_networkstatus_failures > NETWORKSTATUS_N_ALLOWABLE_FAILURES) {
--n_running_dirservers;
continue;
}
if (ns->published_on > now-NETWORKSTATUS_MAX_AGE)
if (ns && ns->published_on > now-NETWORKSTATUS_MAX_AGE)
++n_live;
if (!most_recent || ns->received_on > most_recent_received) {
else
smartlist_add(missing, ds->digest);
if (ns && (!most_recent || ns->received_on > most_recent_received)) {
most_recent_idx = ds_sl_idx; /* magic variable from FOREACH */
most_recent = ds;
most_recent_received = ns->received_on;
}
});
/* Download enough so we have at least half live, but no more than all the
* trusted dirservers we know.
*/
if (n_live < (n_dirservers/2)+1)
needed = (n_dirservers/2)+1-n_live;
if (needed > n_running_dirservers)
needed = n_running_dirservers;
if (needed)
log_info(LD_DIR, "For %d/%d running directory servers, we have %d live"
" network-status documents. Downloading %d.",
n_running_dirservers, n_dirservers, n_live, needed);
/* Also, download at least 1 every NETWORKSTATUS_CLIENT_DL_INTERVAL. */
if (n_running_dirservers &&
most_recent_received < now-NETWORKSTATUS_CLIENT_DL_INTERVAL &&
needed < 1) {
if (!smartlist_len(missing) &&
most_recent_received < now-NETWORKSTATUS_CLIENT_DL_INTERVAL) {
log_info(LD_DIR, "Our most recent network-status document (from %s) "
"is %d seconds old; downloading another.",
most_recent?most_recent->description:"nobody",
(int)(now-most_recent_received));
fetch_latest = 1;
needed = 1;
}
if (!needed)
} else if (smartlist_len(missing)) {
log_info(LD_DIR, "For %d/%d running directory servers, we have %d live"
" network-status documents. Downloading %d.",
n_running_dirservers, n_dirservers, n_live,
smartlist_len(missing));
needed = smartlist_len(missing);
} else {
smartlist_free(missing);
return;
}
/* If no networkstatus was found, choose a dirserver at random as "most
* recent". */
if (most_recent_idx<0)
most_recent_idx = crypto_rand_int(n_dirservers);
if (fetch_latest) {
int i;
for (i = most_recent_idx + 1; i; ++i) {
trusted_dir_server_t *ds;
if (i >= n_dirservers)
i = 0;
ds = smartlist_get(trusted_dir_servers, i);
if (ds->n_networkstatus_failures > NETWORKSTATUS_N_ALLOWABLE_FAILURES)
continue;
smartlist_add(missing, ds->digest);
break;
}
}
/* Build a request string for all the resources we want. */
resource_len = needed * (HEX_DIGEST_LEN+1) + 6;
resource_len = smartlist_len(missing) * (HEX_DIGEST_LEN+1) + 6;
resource = tor_malloc(resource_len);
memcpy(resource, "fp/", 3);
cp = resource+3;
for (i = most_recent_idx+1; needed; ++i) {
trusted_dir_server_t *ds;
if (i >= n_dirservers)
i = 0;
ds = smartlist_get(trusted_dir_servers, i);
if (ds->n_networkstatus_failures > NETWORKSTATUS_N_ALLOWABLE_FAILURES)
continue;
base16_encode(cp, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
cp += HEX_DIGEST_LEN;
--needed;
if (needed)
*cp++ = '+';
}
needed = smartlist_len(missing);
SMARTLIST_FOREACH(missing, const char *, d,
{
base16_encode(cp, HEX_DIGEST_LEN+1, d, DIGEST_LEN);
cp += HEX_DIGEST_LEN;
--needed;
if (needed)
*cp++ = '+';
});
memcpy(cp, ".z", 3);
directory_get_from_dirserver(DIR_PURPOSE_FETCH_NETWORKSTATUS, resource, 1);
tor_free(resource);
smartlist_free(missing);
}
/** Launch requests for networkstatus documents as appropriate. */
@ -3525,7 +3531,8 @@ int
router_have_minimum_dir_info(void)
{
int tot = 0, num_running = 0;
int n_ns, n_authorities, res, avg;
int n_ns, n_tried, n_authorities, res, avg;
static int have_ever_tried_all = 0;
static int have_enough = 0;
if (!networkstatus_list || !routerlist) {
res = 0;
@ -3540,6 +3547,20 @@ router_have_minimum_dir_info(void)
res = 0;
goto done;
}
if (!have_ever_tried_all) {
n_tried=n_ns;
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
if (ds->n_networkstatus_failures) ++n_tried);
if (n_tried < n_authorities) {
log_info(LD_DIR,
"We have only tried downloading %d/%d network statuses.",
n_tried, n_authorities);
res = 0;
goto done;
} else {
have_ever_tried_all = 1;
}
}
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
tot += smartlist_len(ns->entries));
avg = tot / n_ns;