diff --git a/kitty/disk-cache.c b/kitty/disk-cache.c index 5cb213b98..bcab2fb5b 100644 --- a/kitty/disk-cache.c +++ b/kitty/disk-cache.c @@ -33,13 +33,12 @@ typedef struct { uint8_t encryption_key[64]; } CacheValue; - #define NAME cache_map #define KEY_TY CacheKey #define VAL_TY CacheValue* static uint64_t key_hash(KEY_TY k); #define HASH_FN key_hash -static bool keys_are_equal(KEY_TY a, KEY_TY b); +static bool keys_are_equal(CacheKey a, CacheKey b) { return a.hash_keylen == b.hash_keylen && memcmp(a.hash_key, b.hash_key, a.hash_keylen) == 0; } #define CMPR_FN keys_are_equal static void free_cache_value(CacheValue *cv) { free(cv->data); cv->data = NULL; free(cv); } static void free_cache_key(CacheKey cv) { free(cv.hash_key); cv.hash_key = NULL; } @@ -47,7 +46,7 @@ static void free_cache_key(CacheKey cv) { free(cv.hash_key); cv.hash_key = NULL; #define VAL_DTOR_FN free_cache_value #include "kitty-verstable.h" static uint64_t key_hash(CacheKey k) { return vt_hash_bytes(k.hash_key, k.hash_keylen); } -static bool keys_are_equal(CacheKey a, CacheKey b) { return a.hash_keylen == b.hash_keylen && memcmp(a.hash_key, b.hash_key, a.hash_keylen) == 0; } +#define cache_map_for_loop(i) vt_create_for_loop(cache_map_itr, i, &self->map) typedef struct Hole { off_t pos, size; @@ -57,6 +56,7 @@ typedef struct Hole { #define KEY_TY off_t #define VAL_TY off_t #include "kitty-verstable.h" +#define hole_pos_map_for_loop(i) vt_create_for_loop(hole_pos_map_itr, i, &self->holes.pos_map) typedef struct PosList { size_t count, capacity; off_t *positions; } PosList; #define NAME hole_size_map @@ -65,6 +65,7 @@ typedef struct PosList { size_t count, capacity; off_t *positions; } PosList; static void free_pos_list(PosList p) { free(p.positions); } #define VAL_DTOR_FN free_pos_list #include "kitty-verstable.h" +#define hole_size_map_for_loop(i) vt_create_for_loop(hole_size_map_itr, i, &holes->size_map) typedef struct Holes { hole_pos_map pos_map, end_pos_map; @@ -192,7 +193,7 @@ defrag(DiskCache *self) { defrag_entries = calloc(num_entries, sizeof(DefragEntry)); if (!defrag_entries) goto cleanup; size_t total_data_size = 0, num_entries_to_defrag = 0; - for (cache_map_itr i = vt_first(&self->map); !vt_is_end(i); i = vt_next(i)) { + cache_map_for_loop(i) { CacheValue *s = i.data->val; if (s->pos_in_cache_file > -1 && s->data_sz) { total_data_size += s->data_sz; @@ -258,7 +259,7 @@ add_hole_to_maps(Holes *holes, Hole h) { static void update_largest_hole_size(Holes *holes) { holes->largest_hole_size = 0; - for (hole_size_map_itr i = vt_first(&holes->size_map); !vt_is_end(i); i = vt_next(i)) { + hole_size_map_for_loop(i) { if (i.data->key > holes->largest_hole_size) holes->largest_hole_size = i.data->key; } } @@ -366,7 +367,7 @@ remove_from_disk(DiskCache *self, CacheValue *s) { static bool find_cache_entry_to_write(DiskCache *self) { if (needs_defrag(self)) defrag(self); - for (cache_map_itr i = vt_first(&self->map); !vt_is_end(i); i = vt_next(i)) { + cache_map_for_loop(i) { CacheValue *s = i.data->val; if (!s->written_to_disk) { if (s->data) { @@ -715,7 +716,7 @@ disk_cache_clear_from_ram(PyObject *self_, bool(matches)(void*, void *key, unsig size_t ans = 0; if (!ensure_state(self)) return ans; mutex(lock); - for (cache_map_itr i = vt_first(&self->map); !vt_is_end(i); i = vt_next(i)) { + cache_map_for_loop(i) { CacheValue *s = i.data->val; if (s->written_to_disk && s->data && matches(data, i.data->key.hash_key, i.data->key.hash_keylen)) { free(s->data); s->data = NULL; @@ -734,7 +735,7 @@ disk_cache_wait_for_write(PyObject *self_, monotonic_t timeout) { while (!timeout || monotonic() <= end_at) { bool pending = false; mutex(lock); - for (cache_map_itr i = vt_first(&self->map); !vt_is_end(i); i = vt_next(i)) { + cache_map_for_loop(i) { if (!i.data->val->written_to_disk) { pending = true; break; @@ -758,7 +759,7 @@ disk_cache_num_cached_in_ram(PyObject *self_) { unsigned long ans = 0; if (ensure_state(self)) { mutex(lock); - for (cache_map_itr i = vt_first(&self->map); !vt_is_end(i); i = vt_next(i)) { + cache_map_for_loop(i) { if (i.data->val->written_to_disk && i.data->val->data) ans++; } mutex(unlock); @@ -817,7 +818,7 @@ holes(PyObject *self_, PyObject *args UNUSED) { mutex(lock); RAII_PyObject(ans, PyFrozenSet_New(NULL)); if (ans) { - for (hole_pos_map_itr i = vt_first(&self->holes.pos_map); !vt_is_end(i); i = vt_next(i)) { + hole_pos_map_for_loop(i) { RAII_PyObject(t, Py_BuildValue("LL", (long long)i.data->key, (long long)i.data->val)); if (!t || PySet_Add(ans, t) != 0) break; } diff --git a/kitty/kitty-verstable.h b/kitty/kitty-verstable.h index bb54b7538..c8101a3ce 100644 --- a/kitty/kitty-verstable.h +++ b/kitty/kitty-verstable.h @@ -18,4 +18,6 @@ vt_hash_bytes(const void *data, const size_t size) { return hash; } +#define vt_create_for_loop(itr_type, itr, table) for (itr_type itr = vt_first(table); !vt_is_end(itr); itr = vt_next(itr)) + #endif diff --git a/kitty_tests/graphics.py b/kitty_tests/graphics.py index b2e797794..5de3971ff 100644 --- a/kitty_tests/graphics.py +++ b/kitty_tests/graphics.py @@ -321,22 +321,26 @@ class TestGraphics(BaseTest): dc.remove_from_ram(clear_predicate) self.assertEqual(dc.num_cached_in_ram(), 0) - reset(512) + reset(small_hole_threshold=512, defrag_factor=20) self.assertIsNone(add(1, '1' * 1024)) self.assertIsNone(add(2, '2' * 1024)) dc.wait_for_write() sz = dc.size_on_disk() remove(1) self.ae(sz, dc.size_on_disk()) + self.ae({x[1] for x in dc.holes()}, {1024}) self.assertIsNone(add(3, '3' * 800)) dc.wait_for_write() + self.assertFalse(dc.holes()) self.ae(sz, dc.size_on_disk()) self.assertIsNone(add(4, '4' * 100)) sz += 100 dc.wait_for_write() self.ae(sz, dc.size_on_disk()) check_data() + self.assertFalse(dc.holes()) remove(4) + self.assertFalse(dc.holes()) self.assertIsNone(add(5, '5' * 10)) sz += 10 dc.wait_for_write()