This commit is contained in:
Kovid Goyal
2024-07-16 10:45:46 +05:30
parent c056df223e
commit 2ba28171ab
3 changed files with 18 additions and 11 deletions

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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()