Cache eviction

This commit is contained in:
Jordan Bancino 2022-11-18 20:42:08 +00:00
parent e7ad166877
commit 045c6d8644
2 changed files with 75 additions and 8 deletions

View file

@ -15,7 +15,7 @@ Due: January 1, 2023
[~] Data abstraction layer [~] Data abstraction layer
[ ] Database upgrades/migration path [ ] Database upgrades/migration path
[x] Caching [x] Caching
[ ] Cache eviction [x] Cache eviction
[x] Make memory info access O(1) [x] Make memory info access O(1)
[x] Make config option 'id' optional; print warning if not present started as root. [x] Make config option 'id' optional; print warning if not present started as root.
[x] Write install and uninstall scripts [x] Write install and uninstall scripts

View file

@ -32,11 +32,14 @@
struct Db struct Db
{ {
char *dir; char *dir;
size_t cacheSize;
size_t maxCache;
pthread_mutex_t lock; pthread_mutex_t lock;
size_t cacheSize;
size_t maxCache;
HashMap *cache; HashMap *cache;
DbRef *mostRecent;
DbRef *leastRecent;
}; };
struct DbRef struct DbRef
@ -49,6 +52,9 @@ struct DbRef
char *prefix; char *prefix;
char *key; char *key;
DbRef *prev;
DbRef *next;
}; };
static ssize_t DbComputeSize(HashMap *); static ssize_t DbComputeSize(HashMap *);
@ -175,6 +181,33 @@ DbFileName(Db * db, char *prefix, char *key)
return tmp5; return tmp5;
} }
static void
DbCacheEvict(Db * db)
{
DbRef *ref = db->leastRecent;
while (ref && db->cacheSize > db->maxCache)
{
char *hash = DbHashKey(ref->prefix, ref->key);
JsonFree(ref->json);
pthread_mutex_destroy(&ref->lock);
HashMapDelete(db->cache, hash);
Free(hash);
Free(ref->prefix);
Free(ref->key);
db->cacheSize -= ref->size;
db->leastRecent = ref->next;
db->leastRecent->prev = NULL;
Free(ref);
ref = db->leastRecent;
}
}
Db * Db *
DbOpen(char *dir, size_t cache) DbOpen(char *dir, size_t cache)
{ {
@ -209,6 +242,9 @@ DbOpen(char *dir, size_t cache)
db->cache = NULL; db->cache = NULL;
} }
db->mostRecent = NULL;
db->leastRecent = NULL;
return db; return db;
} }
@ -330,6 +366,30 @@ DbLock(Db * db, char *prefix, char *key)
ref->json = json; ref->json = json;
ref->ts = diskTs; ref->ts = diskTs;
ref->size = DbComputeSize(ref->json); ref->size = DbComputeSize(ref->json);
if (db->cache)
{
/* Float this ref to mostRecent */
if (ref->next)
{
ref->next->prev = ref->prev;
ref->prev->next = ref->next;
if (!ref->prev)
{
db->leastRecent = ref->next;
}
ref->prev = db->mostRecent;
ref->next = NULL;
db->mostRecent = ref;
}
/* The file on disk may be larger than what we have in
* memory, which may require items in cache to be
* evicted. */
DbCacheEvict(db);
}
} }
} }
else else
@ -372,11 +432,13 @@ DbLock(Db * db, char *prefix, char *key)
HashMapSet(db->cache, hash, ref); HashMapSet(db->cache, hash, ref);
db->cacheSize += ref->size; db->cacheSize += ref->size;
/* Cache is full; evict old items */ ref->next = NULL;
if (db->cacheSize > db->maxCache) ref->prev = db->mostRecent;
{ db->mostRecent = ref;
/* TODO */
} /* Adding this item to the cache may case it to grow too
* large, requiring some items to be evicted */
DbCacheEvict(db);
} }
} }
@ -435,6 +497,11 @@ DbUnlock(Db * db, DbRef * ref)
db->cacheSize -= ref->size; db->cacheSize -= ref->size;
ref->size = DbComputeSize(ref->json); ref->size = DbComputeSize(ref->json);
db->cacheSize += ref->size; db->cacheSize += ref->size;
/* If this ref has grown significantly since we last computed
* its size, it may have filled the cache and require some
* items to be evicted. */
DbCacheEvict(db);
} }
pthread_mutex_unlock(&db->lock); pthread_mutex_unlock(&db->lock);