mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Functionality to ensure there is space to add files to cache.
This commit is contained in:
@@ -530,3 +530,13 @@ storage_dir_remove_all(storage_dir_t *d)
|
||||
return storage_dir_shrink(d, 0, d->max_files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the largest number of non-temporary files we're willing to
|
||||
* store in <b>d</b>.
|
||||
*/
|
||||
int
|
||||
storage_dir_get_max_files(storage_dir_t *d)
|
||||
{
|
||||
return d->max_files;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ int storage_dir_shrink(storage_dir_t *d,
|
||||
uint64_t target_size,
|
||||
int min_to_remove);
|
||||
int storage_dir_remove_all(storage_dir_t *d);
|
||||
int storage_dir_get_max_files(storage_dir_t *d);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -399,6 +399,19 @@ consensus_cache_unmap_lazy(consensus_cache_t *cache, time_t cutoff)
|
||||
} SMARTLIST_FOREACH_END(ent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of currently unused filenames available in this cache.
|
||||
*/
|
||||
int
|
||||
consensus_cache_get_n_filenames_available(consensus_cache_t *cache)
|
||||
{
|
||||
tor_assert(cache);
|
||||
int max = storage_dir_get_max_files(cache->dir);
|
||||
int used = smartlist_len(storage_dir_list(cache->dir));
|
||||
tor_assert_nonfatal(max >= used);
|
||||
return max - used;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete every element of <b>cache</b> has been marked with
|
||||
* consensus_cache_entry_mark_for_removal. If <b>force</b> is false,
|
||||
|
||||
@@ -19,6 +19,7 @@ int consensus_cache_register_with_sandbox(consensus_cache_t *cache,
|
||||
void consensus_cache_unmap_lazy(consensus_cache_t *cache, time_t cutoff);
|
||||
void consensus_cache_delete_pending(consensus_cache_t *cache,
|
||||
int force);
|
||||
int consensus_cache_get_n_filenames_available(consensus_cache_t *cache);
|
||||
consensus_cache_entry_t *consensus_cache_add(consensus_cache_t *cache,
|
||||
const config_line_t *labels,
|
||||
const uint8_t *data,
|
||||
|
||||
@@ -107,6 +107,7 @@ static consdiff_cfg_t consdiff_cfg = {
|
||||
/* .cache_max_num = */ 128
|
||||
};
|
||||
|
||||
static int consdiffmgr_ensure_space_for_files(int n);
|
||||
static int consensus_diff_queue_diff_work(consensus_cache_entry_t *diff_from,
|
||||
consensus_cache_entry_t *diff_to);
|
||||
static void consdiffmgr_set_cache_flags(void);
|
||||
@@ -413,6 +414,8 @@ consdiffmgr_add_consensus(const char *consensus,
|
||||
}
|
||||
|
||||
/* We don't have it. Add it to the cache. */
|
||||
consdiffmgr_ensure_space_for_files(1);
|
||||
|
||||
{
|
||||
size_t bodylen = strlen(consensus);
|
||||
config_line_t *labels = NULL;
|
||||
@@ -852,6 +855,82 @@ consdiffmgr_rescan(void)
|
||||
cdm_cache_dirty = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: compare two files by their from-valid-after and valid-after labels,
|
||||
* trying to sort in ascending order by from-valid-after (when present) and
|
||||
* valid-after (when not). Place everything that has neither label first in
|
||||
* the list.
|
||||
*/
|
||||
static int
|
||||
compare_by_staleness_(const void **a, const void **b)
|
||||
{
|
||||
const consensus_cache_entry_t *e1 = *a;
|
||||
const consensus_cache_entry_t *e2 = *b;
|
||||
const char *va1, *fva1, *va2, *fva2;
|
||||
va1 = consensus_cache_entry_get_value(e1, LABEL_VALID_AFTER);
|
||||
va2 = consensus_cache_entry_get_value(e2, LABEL_VALID_AFTER);
|
||||
fva1 = consensus_cache_entry_get_value(e1, LABEL_FROM_VALID_AFTER);
|
||||
fva2 = consensus_cache_entry_get_value(e2, LABEL_FROM_VALID_AFTER);
|
||||
|
||||
if (fva1)
|
||||
va1 = fva1;
|
||||
if (fva2)
|
||||
va2 = fva2;
|
||||
|
||||
/* See note about iso-encoded values in compare_by_valid_after_. Also note
|
||||
* that missing dates will get placed first. */
|
||||
return strcmp_opt(va1, va2);
|
||||
}
|
||||
|
||||
/** If there are not enough unused filenames to store <b>n</b> files, then
|
||||
* delete old consensuses until there are. (We have to keep track of the
|
||||
* number of filenames because of the way that the seccomp2 cache works.)
|
||||
*
|
||||
* Return 0 on success, -1 on failure.
|
||||
**/
|
||||
static int
|
||||
consdiffmgr_ensure_space_for_files(int n)
|
||||
{
|
||||
consensus_cache_t *cache = cdm_cache_get();
|
||||
if (consensus_cache_get_n_filenames_available(cache) >= n) {
|
||||
// there are already enough unused filenames.
|
||||
return 0;
|
||||
}
|
||||
// Try a cheap deletion of stuff that's waiting to get deleted.
|
||||
consensus_cache_delete_pending(cache, 0);
|
||||
if (consensus_cache_get_n_filenames_available(cache) >= n) {
|
||||
// okay, _that_ made enough filenames available.
|
||||
return 0;
|
||||
}
|
||||
// Let's get more assertive: clean out unused stuff, and force-remove
|
||||
// the files.
|
||||
consdiffmgr_cleanup();
|
||||
consensus_cache_delete_pending(cache, 1);
|
||||
const int n_to_remove = n - consensus_cache_get_n_filenames_available(cache);
|
||||
if (n_to_remove <= 0) {
|
||||
// okay, finally!
|
||||
return 0;
|
||||
}
|
||||
|
||||
// At this point, we're going to have to throw out objects that will be
|
||||
// missed. Too bad!
|
||||
smartlist_t *objects = smartlist_new();
|
||||
consensus_cache_find_all(objects, cache, NULL, NULL);
|
||||
smartlist_sort(objects, compare_by_staleness_);
|
||||
int n_marked = 0;
|
||||
SMARTLIST_FOREACH_BEGIN(objects, consensus_cache_entry_t *, ent) {
|
||||
consensus_cache_entry_mark_for_removal(ent);
|
||||
if (++n_marked >= n_to_remove)
|
||||
break;
|
||||
} SMARTLIST_FOREACH_END(ent);
|
||||
|
||||
consensus_cache_delete_pending(cache, 1);
|
||||
if (BUG(n_marked < n_to_remove))
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set consensus cache flags on the objects in this consdiffmgr.
|
||||
*/
|
||||
@@ -1066,6 +1145,8 @@ consensus_diff_worker_replyfn(void *work_)
|
||||
/* Success! Store the results */
|
||||
log_info(LD_DIRSERV, "Adding consensus diff from %s to %s",
|
||||
lv_from_digest, lv_to_digest);
|
||||
|
||||
consdiffmgr_ensure_space_for_files(1);
|
||||
consensus_cache_entry_t *ent =
|
||||
consensus_cache_add(cdm_cache_get(), job->labels_out,
|
||||
job->body_out,
|
||||
|
||||
Reference in New Issue
Block a user