diff options
Diffstat (limited to 'src/or/microdesc.c')
-rw-r--r-- | src/or/microdesc.c | 60 |
1 files changed, 46 insertions, 14 deletions
diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 0a4c8ea4c7..e014cd0761 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -319,26 +319,32 @@ microdesc_cache_reload(microdesc_cache_t *cache) return 0; } -/** DOCDOC */ +/** By default, we remove any microdescriptors that have gone at least this + * long without appearing in a current consensus. */ #define TOLERATE_MICRODESC_AGE (7*24*60*60) -/** DOCDOC */ +/** Remove all microdescriptors from <b>cache</b> that haven't been listed for + * a long time. Does not rebuild the cache on disk. If <b>cutoff</b> is + * positive, specifically remove microdescriptors that have been unlisted + * since <b>cutoff</b>. If <b>force</b> is true, remove microdescriptors even + * if we have no current live microdescriptor consensus. + */ void -microdesc_cache_clean(microdesc_cache_t *cache) +microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force) { - networkstatus_t *consensus; - time_t cutoff; microdesc_t **mdp, *victim; int dropped=0, kept=0; size_t bytes_dropped = 0; time_t now = time(NULL); - /* If we don't know a consensus, never believe last_listed values */ - consensus = networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC); - if (consensus == NULL) - return; + /* If we don't know a live consensus, don't believe last_listed values: we + * might be starting up after being down for a while. */ + if (! force && + ! networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC)) + return; - cutoff = now - TOLERATE_MICRODESC_AGE; + if (cutoff <= 0) + cutoff = now - TOLERATE_MICRODESC_AGE; for (mdp = HT_START(microdesc_map, &cache->map); mdp != NULL; ) { if ((*mdp)->last_listed < cutoff) { @@ -376,8 +382,10 @@ microdesc_cache_rebuild(microdesc_cache_t *cache) log_info(LD_DIR, "Rebuilding the microdescriptor cache..."); - microdesc_cache_clean(cache); + /* Remove dead descriptors */ + microdesc_cache_clean(cache, 0/*cutoff*/, 0/*force*/); + /* Calculate starting disk usage */ orig_size = (int)(cache->cache_content ? cache->cache_content->size : 0); orig_size += (int)cache->journal_len; @@ -401,6 +409,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache) /* log? return -1? die? coredump the universe? */ continue; } + tor_assert(((size_t)size) == annotation_len + md->bodylen); md->off = off + annotation_len; off += size; if (md->saved_location != SAVED_IN_CACHE) { @@ -425,7 +434,21 @@ microdesc_cache_rebuild(microdesc_cache_t *cache) SMARTLIST_FOREACH_BEGIN(wrote, microdesc_t *, md) { tor_assert(md->saved_location == SAVED_IN_CACHE); md->body = (char*)cache->cache_content->data + md->off; - tor_assert(!memcmp(md->body, "onion-key", 9)); + if (PREDICT_UNLIKELY( + md->bodylen < 9 || memcmp(md->body, "onion-key", 9) != 0)) { + /* XXXX023 once bug 2022 is solved, we can kill this block and turn it + * into just the tor_assert(!memcmp) */ + off_t avail = cache->cache_content->size - md->off; + char *bad_str; + tor_assert(avail >= 0); + bad_str = tor_strndup(md->body, MIN(128, (size_t)avail)); + log_err(LD_BUG, "After rebuilding microdesc cache, offsets seem wrong. " + " At offset %d, I expected to find a microdescriptor starting " + " with \"onion-key\". Instead I got %s.", + (int)md->off, escaped(bad_str)); + tor_free(bad_str); + tor_assert(!memcmp(md->body, "onion-key", 9)); + } } SMARTLIST_FOREACH_END(md); smartlist_free(wrote); @@ -529,7 +552,13 @@ microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache, return result; } -/** DOCDOC */ +/** Launch download requests for mircodescriptors as appropriate. + * + * Specifically, we should launch download requests if we are configured to + * download mirodescriptors, and there are some microdescriptors listed the + * current microdesc consensus that we don't have, and either we never asked + * for them, or we failed to download them but we're willing to retry. + */ void update_microdesc_downloads(time_t now) { @@ -568,7 +597,10 @@ update_microdesc_downloads(time_t now) smartlist_free(missing); } -/** DOCDOC */ +/** For every microdescriptor listed in the current microdecriptor consensus, + * update its last_listed field to be at least as recent as the publication + * time of the current microdescriptor consensus. + */ void update_microdescs_from_networkstatus(time_t now) { |