From 676190e895a94978fbda82527f7ba2dbf8ccda80 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 28 Apr 2011 23:44:48 -0400 Subject: [PATCH 1/9] Update hacking file with terse notes on formatting changelog --- doc/HACKING | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/doc/HACKING b/doc/HACKING index b612953743..6407ff23eb 100644 --- a/doc/HACKING +++ b/doc/HACKING @@ -414,10 +414,43 @@ Here are the steps Roger takes when putting out a new Tor release: and as a directory authority. See if it has any obvious bugs, and resolve those. +1.5) As applicable, merge the maint-X branch into the release-X branch. + 2) Gather the changes/* files into a changelog entry, rewriting many of them and reordering to focus on what users and funders would find interesting and understandable. + 2.1) Make sure that everything that wants a bug number has one. + 2.2) Concatenate them. + 2.3) Sort them by section. Within each section, try to make the + first entry or two and the last entry most interesting: they're + the ones that skimmers tend to read. + + 2.4) Clean them up + + Standard idioms: + "Fixes bug 9999; Bugfix on 0.3.3.3-alpha." + + One period after a space. + + Make stuff very terse + + Describe the user-visible problem right away + + Mention relevant config options by name. If they're rare or unusual, + remind people what they're for + + Avoid starting lines with open-paren + + Present and imperative tense: not past. + + 2.5) Merge them in. + + 2.6) Clean everything one last time. + + 2.7) Run it through fmt to make it pretty. + + 3) Compose a short release blurb to highlight the user-facing changes. Insert said release blurb into the ChangeLog stanza. If it's a stable release, add it to the ReleaseNotes file too. If we're adding From 93b0183d3cae436732b48d36aa9b54964854a0a4 Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Fri, 29 Apr 2011 01:35:21 -0400 Subject: [PATCH 2/9] add another heuristic for changes stanzas --- doc/HACKING | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/HACKING b/doc/HACKING index 6407ff23eb..633623217d 100644 --- a/doc/HACKING +++ b/doc/HACKING @@ -444,6 +444,10 @@ interesting and understandable. Present and imperative tense: not past. + If a given changes stanza showed up in a different release (e.g. + maint-0.2.1), be sure to make the stanzas identical (so people can + distinguish if these are the same change). + 2.5) Merge them in. 2.6) Clean everything one last time. From dbd73b9689e8008adc149472ca5c02692a49923d Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 29 Apr 2011 11:14:53 -0400 Subject: [PATCH 3/9] Clean up a warning a bit --- src/or/config.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/or/config.c b/src/or/config.c index 867182224f..666a1bdc34 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -3488,10 +3488,9 @@ options_validate(or_options_t *old_options, or_options_t *options, } if (options->CookieAuthFileGroupReadable && !options->CookieAuthFile) { - log_warn(LD_CONFIG, "You set the CookieAuthFileGroupReadable but did " - "not configure a the path for the cookie file via " - "CookieAuthFile. This means your cookie will not be group " - "readable."); + log_warn(LD_CONFIG, "CookieAuthFileGroupReadable is set, but will have " + "no effect: you must specify an explicit CookieAuthFile to " + "have it group-readable."); } if (options->UseEntryGuards && ! options->NumEntryGuards) From 033c27ac5ea02fa1a44651c5a324cb78e787f1a3 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 2 May 2011 14:45:44 -0400 Subject: [PATCH 4/9] Add a couple of notes to doc/HACKING based on 0.2.2.25-alpha process --- doc/HACKING | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/HACKING b/doc/HACKING index 633623217d..86d4a98784 100644 --- a/doc/HACKING +++ b/doc/HACKING @@ -472,6 +472,9 @@ in their approved versions list. 7) Sign and push the tarball to the website in the dist/ directory. Sign and push the git tag. + (That's either "git tag -u tor-0.2.x.y-status", then + "git push origin tag tor-0.2.x.y-status". To sign the + tarball, "gpg -ba ") 8) Edit include/versions.wmi to note the new version. Rebuild and push the website. @@ -490,3 +493,5 @@ the date in the ChangeLog. packages are up (for a stable release), and mail the release blurb and changelog to tor-talk or tor-announce. + (We might be moving to faster announcements, but don't announce until + the website is at least updated.) From 698fa0fc67118bea2ea7720455ebbdee705c8c1a Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 3 May 2011 16:22:31 -0400 Subject: [PATCH 5/9] Add missing code to set cache->journal_len when reading microdesc journal This could be one reason that authorities' journals would grow without bound; related to bug 2230. Bugfix on 0.2.2.6-alpha. Fix by "cypherpunks". --- changes/bug2230_part1 | 7 +++++++ src/or/microdesc.c | 1 + 2 files changed, 8 insertions(+) create mode 100644 changes/bug2230_part1 diff --git a/changes/bug2230_part1 b/changes/bug2230_part1 new file mode 100644 index 0000000000..79f725410d --- /dev/null +++ b/changes/bug2230_part1 @@ -0,0 +1,7 @@ + o Minor bugfixes + - When loading the microdesc journal, remember its current size. + In 0.2.2, this helps prevent the microdesc journal from growing + without limit on authorities (who are the only ones to use it in + 0.2.2). Fixes a part of bug 2230; bugfix on 0.2.2.6-alpha. + Fix posted by "cypherpunks." + diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 2c4b3435f7..356627700d 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -261,6 +261,7 @@ microdesc_cache_reload(microdesc_cache_t *cache) journal_content = read_file_to_str(cache->journal_fname, RFTS_IGNORE_MISSING, &st); if (journal_content) { + cache->journal_len = (size_t) st.st_size; added = microdescs_add_to_cache(cache, journal_content, journal_content+st.st_size, SAVED_IN_JOURNAL, 0); From 970715dd8f52a79bbaddfcfa5af1f11608ddacf9 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 3 May 2011 16:29:39 -0400 Subject: [PATCH 6/9] Fix a check for when to rebuild the microdesc cache. (Backport from 0.2.3. --- changes/bug2230_part2 | 5 +++++ src/or/microdesc.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changes/bug2230_part2 diff --git a/changes/bug2230_part2 b/changes/bug2230_part2 new file mode 100644 index 0000000000..2664ecc1a0 --- /dev/null +++ b/changes/bug2230_part2 @@ -0,0 +1,5 @@ + o Minor bugfixes + - The microdesc journal is supposed to get rebuilt only if it is + at least _half_ the length of the store, not _twice_ the length + of the store. Bugfix on 0.2.2.6-alpha; fixes part of bug 2230. + diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 356627700d..0ceb134a61 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -208,7 +208,7 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache, size_t old_content_len = cache->cache_content ? cache->cache_content->size : 0; if (cache->journal_len > 16384 + old_content_len && - cache->journal_len > old_content_len * 2) { + cache->journal_len > old_content_len / 2) { microdesc_cache_rebuild(cache); } } From 56fbd728c2df7f189390b9a417b4c3ecc3690ede Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 3 May 2011 16:45:15 -0400 Subject: [PATCH 7/9] Backport microdesc_cache_clean to 0.2.2 Otherwise we have no way to keep authorities' microdesc caches in 0.2.2 from growing without bound. --- changes/bug2230_clean_1 | 4 ++++ src/or/microdesc.c | 51 +++++++++++++++++++++++++++++++++++++++++ src/or/microdesc.h | 1 + 3 files changed, 56 insertions(+) create mode 100644 changes/bug2230_clean_1 diff --git a/changes/bug2230_clean_1 b/changes/bug2230_clean_1 new file mode 100644 index 0000000000..a4edf9439e --- /dev/null +++ b/changes/bug2230_clean_1 @@ -0,0 +1,4 @@ + o Minor features + - Backport code from 0.2.3.x to allow directory authorities to clean + their microdescriptor caches. + diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 0ceb134a61..58fbe370ab 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -23,6 +23,8 @@ struct microdesc_cache_t { tor_mmap_t *cache_content; /** Number of bytes used in the journal file. */ size_t journal_len; + /** Number of bytes in descriptors removed as too old. */ + size_t bytes_dropped; /** Total bytes of microdescriptor bodies we have added to this cache */ uint64_t total_len_seen; @@ -276,6 +278,51 @@ microdesc_cache_reload(microdesc_cache_t *cache) return 0; } +/** 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) + +/** Remove all microdescriptors from cache that haven't been listed for + * a long time. Does not rebuild the cache on disk. If cutoff is + * positive, specifically remove microdescriptors that have been unlisted + * since cutoff. If force is true, remove microdescriptors even + * if we have no current live microdescriptor consensus. + */ +void +microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force) +{ + microdesc_t **mdp, *victim; + int dropped=0, kept=0; + size_t bytes_dropped = 0; + time_t now = time(NULL); + + (void) force; + /* In 0.2.2, we let this proceed unconditionally: only authorities have + * microdesc caches. */ + + if (cutoff <= 0) + cutoff = now - TOLERATE_MICRODESC_AGE; + + for (mdp = HT_START(microdesc_map, &cache->map); mdp != NULL; ) { + if ((*mdp)->last_listed < cutoff) { + ++dropped; + victim = *mdp; + mdp = HT_NEXT_RMV(microdesc_map, &cache->map, mdp); + bytes_dropped += victim->bodylen; + microdesc_free(victim); + } else { + ++kept; + mdp = HT_NEXT(microdesc_map, &cache->map, mdp); + } + } + + if (dropped) { + log_notice(LD_DIR, "Removed %d/%d microdescriptors as old.", + dropped,dropped+kept); + cache->bytes_dropped += bytes_dropped; + } +} + /** Regenerate the main cache file for cache, clear the journal file, * and update every microdesc_t in the cache with pointers to its new * location. */ @@ -291,6 +338,10 @@ microdesc_cache_rebuild(microdesc_cache_t *cache) int orig_size, new_size; log_info(LD_DIR, "Rebuilding the microdescriptor cache..."); + + /* Remove dead descriptors */ + microdesc_cache_clean(cache, 0/*cutoff*/, 0/*force*/); + orig_size = (int)(cache->cache_content ? cache->cache_content->size : 0); orig_size += (int)cache->journal_len; diff --git a/src/or/microdesc.h b/src/or/microdesc.h index b3e12f8ef0..30cb25d52f 100644 --- a/src/or/microdesc.h +++ b/src/or/microdesc.h @@ -21,6 +21,7 @@ smartlist_t *microdescs_add_list_to_cache(microdesc_cache_t *cache, smartlist_t *descriptors, saved_location_t where, int no_save); +void microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force); int microdesc_cache_rebuild(microdesc_cache_t *cache); int microdesc_cache_reload(microdesc_cache_t *cache); void microdesc_cache_clear(microdesc_cache_t *cache); From cb6c909664f97f751fe78c0aa3205a9042760c53 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 3 May 2011 17:03:49 -0400 Subject: [PATCH 8/9] Rebuild the microdesc cache when a sufficient number of bytes are dropped Previously on 0.2.2, we'd never clean the cache. Now that we can clean it, we want to add a condition to rebuild it: that should happen whenever we have dropped enough microdescriptors that we could save a lot of space. No changes file, since 0.2.3 doesn't need one and 0.2.2 already has some changes files for the backport of the microdesc_clean_cahce() function. --- src/or/microdesc.c | 45 +++++++++++++++++++++++++++++++++------------ src/or/microdesc.h | 2 +- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 58fbe370ab..c6bb3c61f6 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -177,6 +177,8 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache, if (md2->last_listed < md->last_listed) md2->last_listed = md->last_listed; microdesc_free(md); + if (where != SAVED_NOWHERE) + cache->bytes_dropped += size; continue; } @@ -206,14 +208,7 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache, if (f) finish_writing_to_file(open_file); /*XXX Check me.*/ - { - size_t old_content_len = - cache->cache_content ? cache->cache_content->size : 0; - if (cache->journal_len > 16384 + old_content_len && - cache->journal_len > old_content_len / 2) { - microdesc_cache_rebuild(cache); - } - } + microdesc_cache_rebuild(cache, 0/* only as needed */); return added; } @@ -275,6 +270,9 @@ microdesc_cache_reload(microdesc_cache_t *cache) } log_notice(LD_DIR, "Reloaded microdescriptor cache. Found %d descriptors.", total); + + microdesc_cache_clean(cache, 0, 0); + return 0; } @@ -323,11 +321,30 @@ microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force) } } +static int +should_rebuild_md_cache(microdesc_cache_t *cache) +{ + const size_t old_len = + cache->cache_content ? cache->cache_content->size : 0; + const size_t journal_len = cache->journal_len; + const size_t dropped = cache->bytes_dropped; + + if (journal_len < 16384) + return 0; /* Don't bother, not enough has happened yet. */ + if (dropped > (journal_len + old_len) / 3) + return 1; /* We could save 1/3 or more of the currently used space. */ + if (journal_len > old_len / 2) + return 1; /* We should append to the regular file */ + + return 0; +} + /** Regenerate the main cache file for cache, clear the journal file, * and update every microdesc_t in the cache with pointers to its new - * location. */ + * location. If force is true, do this unconditionally. If + * force is false, do it only if we expect to save space on disk. */ int -microdesc_cache_rebuild(microdesc_cache_t *cache) +microdesc_cache_rebuild(microdesc_cache_t *cache, int force) { open_file_t *open_file; FILE *f; @@ -337,11 +354,14 @@ microdesc_cache_rebuild(microdesc_cache_t *cache) off_t off = 0; int orig_size, new_size; - log_info(LD_DIR, "Rebuilding the microdescriptor cache..."); - /* Remove dead descriptors */ microdesc_cache_clean(cache, 0/*cutoff*/, 0/*force*/); + if (!force && !should_rebuild_md_cache(cache)) + return 0; + + log_info(LD_DIR, "Rebuilding the microdescriptor cache..."); + orig_size = (int)(cache->cache_content ? cache->cache_content->size : 0); orig_size += (int)cache->journal_len; @@ -396,6 +416,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache) write_str_to_file(cache->journal_fname, "", 1); cache->journal_len = 0; + cache->bytes_dropped = 0; new_size = (int)cache->cache_content->size; log_info(LD_DIR, "Done rebuilding microdesc cache. " diff --git a/src/or/microdesc.h b/src/or/microdesc.h index 30cb25d52f..77ce8536bc 100644 --- a/src/or/microdesc.h +++ b/src/or/microdesc.h @@ -22,7 +22,7 @@ smartlist_t *microdescs_add_list_to_cache(microdesc_cache_t *cache, int no_save); void microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force); -int microdesc_cache_rebuild(microdesc_cache_t *cache); +int microdesc_cache_rebuild(microdesc_cache_t *cache, int force); int microdesc_cache_reload(microdesc_cache_t *cache); void microdesc_cache_clear(microdesc_cache_t *cache); From 68ae5afa5a172fbc485eda7e6bfd4750fa6a69f5 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 3 May 2011 17:28:28 -0400 Subject: [PATCH 9/9] Change who calls microdesc_cache_rebuild(). Previously we ensured that it would get called periodically by doing it from inside the code that added microdescriptors. That won't work though: it would interfere with our code that tried to read microdescs from disk initially. Instead, we should consider rebuilding the cache periodically, and on startup. --- changes/bug2230_part4 | 6 ++++++ src/or/main.c | 2 ++ src/or/microdesc.c | 11 ++++++++--- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 changes/bug2230_part4 diff --git a/changes/bug2230_part4 b/changes/bug2230_part4 new file mode 100644 index 0000000000..f7721fad34 --- /dev/null +++ b/changes/bug2230_part4 @@ -0,0 +1,6 @@ + o Minor bugfixes: + - Authorities now clean their microdesc cache periodically and when + reading from disk initially, not only when adding new descriptors. + This prevents a bug where we could lose microdescriptors. Bugfix + on 0.2.2.6-alpha. + diff --git a/src/or/main.c b/src/or/main.c index a26be39fdf..462b51e783 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1075,6 +1075,8 @@ run_scheduled_events(time_t now) rep_history_clean(now - options->RephistTrackTime); rend_cache_clean(); rend_cache_clean_v2_descs_as_dir(); + if (authdir_mode_v3(options)) + microdesc_cache_rebuild(NULL, 0); #define CLEAN_CACHES_INTERVAL (30*60) time_to_clean_caches = now + CLEAN_CACHES_INTERVAL; } diff --git a/src/or/microdesc.c b/src/or/microdesc.c index c6bb3c61f6..73d2285009 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -208,8 +208,6 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache, if (f) finish_writing_to_file(open_file); /*XXX Check me.*/ - microdesc_cache_rebuild(cache, 0/* only as needed */); - return added; } @@ -230,6 +228,7 @@ microdesc_cache_clear(microdesc_cache_t *cache) } cache->total_len_seen = 0; cache->n_seen = 0; + cache->bytes_dropped = 0; } /** Reload the contents of cache from disk. If it is empty, load it @@ -271,7 +270,7 @@ microdesc_cache_reload(microdesc_cache_t *cache) log_notice(LD_DIR, "Reloaded microdescriptor cache. Found %d descriptors.", total); - microdesc_cache_clean(cache, 0, 0); + microdesc_cache_rebuild(cache, 0 /* don't force */); return 0; } @@ -354,6 +353,12 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force) off_t off = 0; int orig_size, new_size; + if (cache == NULL) { + cache = the_microdesc_cache; + if (cache == NULL) + return 0; + } + /* Remove dead descriptors */ microdesc_cache_clean(cache, 0/*cutoff*/, 0/*force*/);