Mercurial > urweb
diff src/c/urweb.c @ 2234:2f7ed04332a0
Progress on LRU cache but still more known bugs to fix.
author | Ziv Scully <ziv@mit.edu> |
---|---|
date | Sun, 28 Jun 2015 12:46:51 -0700 |
parents | e10881cd92da |
children | 88cc0f44c940 |
line wrap: on
line diff
--- a/src/c/urweb.c Wed May 06 23:11:30 2015 -0400 +++ b/src/c/urweb.c Sun Jun 28 12:46:51 2015 -0700 @@ -22,6 +22,8 @@ #include "types.h" +#include "uthash.h" + uw_unit uw_unit_v = 0; @@ -4494,3 +4496,148 @@ void uw_set_remoteSock(uw_context ctx, int sock) { ctx->remoteSock = sock; } + + +// Sqlcache + +void listDelete(CacheList *list, CacheEntry *entry) { + if (list->first == entry) { + list->first = entry->next; + } + if (list->last == entry) { + list->last = entry->prev; + } + if (entry->prev) { + entry->prev->next = entry->next; + } + if (entry->next) { + entry->next->prev = entry->prev; + } + entry->prev = NULL; + entry->next = NULL; + --(list->size); +} + +void listAdd(CacheList *list, CacheEntry *entry) { + if (list->last) { + list->last->next = entry; + entry->prev = list->last; + list->last = entry; + } else { + list->first = entry; + list->last = entry; + } + ++(list->size); +} + +void listBump(CacheList *list, CacheEntry *entry) { + listDelete(list, entry); + listAdd(list, entry); +} + +// TODO: deal with time properly. + +time_t getTimeNow() { + return time(NULL); +} + +time_t timeMax(time_t x, time_t y) { + return difftime(x, y) > 0 ? x : y; +} + +void freeCacheValue(CacheValue *value) { + if (value) { + free(value->result); + free(value->output); + free(value); + } +} + +void delete(Cache *cache, CacheEntry* entry) { + //listDelete(cache->lru, entry); + HASH_DELETE(hh, cache->table, entry); + freeCacheValue(entry->value); + free(entry->key); + free(entry); +} + +CacheValue *checkHelper(Cache *cache, char **keys, int timeInvalid) { + char *key = keys[cache->height]; + CacheEntry *entry; + HASH_FIND(hh, cache->table, key, strlen(key), entry); + timeInvalid = timeMax(timeInvalid, cache->timeInvalid); + if (entry && difftime(entry->timeValid, timeInvalid) > 0) { + if (cache->height == 0) { + // At height 0, entry->value is the desired value. + //listBump(cache->lru, entry); + return entry->value; + } else { + // At height n+1, entry->value is a pointer to a cache at heignt n. + return checkHelper(entry->value, keys, timeInvalid); + } + } else { + return NULL; + } +} + +CacheValue *check(Cache *cache, char **keys) { + return checkHelper(cache, keys, 0); +} + +void storeHelper(Cache *cache, char **keys, CacheValue *value, int timeNow) { + CacheEntry *entry; + char *key = keys[cache->height]; + HASH_FIND(hh, cache->table, key, strlen(key), entry); + if (!entry) { + entry = malloc(sizeof(CacheEntry)); + entry->key = strdup(key); + entry->value = NULL; + HASH_ADD_KEYPTR(hh, cache->table, entry->key, strlen(entry->key), entry); + } + entry->timeValid = timeNow; + if (cache->height == 0) { + //listAdd(cache->lru, entry); + freeCacheValue(entry->value); + entry->value = value; + //if (cache->lru->size > MAX_SIZE) { + //delete(cache, cache->lru->first); + // TODO: return flushed value. + //} + } else { + if (!entry->value) { + Cache *newCache = malloc(sizeof(Cache)); + newCache->table = NULL; + newCache->timeInvalid = timeNow; + newCache->lru = cache->lru; + newCache->height = cache->height - 1; + entry->value = newCache; + } + storeHelper(entry->value, keys, value, timeNow); + } +} + +void store(Cache *cache, char **keys, CacheValue *value) { + storeHelper(cache, keys, value, getTimeNow()); +} + +void flushHelper(Cache *cache, char **keys, int timeNow) { + CacheEntry *entry; + char *key = keys[cache->height]; + if (key) { + HASH_FIND(hh, cache->table, key, strlen(key), entry); + if (entry) { + if (cache->height == 0) { + delete(cache, entry); + } else { + flushHelper(entry->value, keys, timeNow); + } + } + } else { + // Null key means invalidate the entire subtree. + cache->timeInvalid = timeNow; + } +} + +void flush(Cache *cache, char **keys) { + flushHelper(cache, keys, getTimeNow()); +}