# HG changeset patch # User Ziv Scully # Date 1447339640 18000 # Node ID 19b233bb3176d927a00d9be6e8cc1722be63ab23 # Parent 75cb60a7f6f124d4f5aeb9856b3944f552735d78 Make cache flushes safe for transactions (not sure about LRU bump on read). diff -r 75cb60a7f6f1 -r 19b233bb3176 src/c/urweb.c --- a/src/c/urweb.c Thu Nov 12 09:15:50 2015 -0500 +++ b/src/c/urweb.c Thu Nov 12 09:47:20 2015 -0500 @@ -424,6 +424,12 @@ void (*free)(void*); } global; +typedef struct uw_Sqlcache_Inval { + uw_Sqlcache_Cache *cache; + char **keys; + struct uw_Sqlcache_Inval *next; +} uw_Sqlcache_Inval; + struct uw_context { uw_app *app; int id; @@ -491,6 +497,7 @@ // Sqlcache. int numRecording; int recordingOffset; + uw_Sqlcache_Inval *inval; int remoteSock; }; @@ -4661,7 +4668,7 @@ entry->value->timeValid = timeNow; } -void uw_Sqlcache_flush(uw_Sqlcache_Cache *cache, char **keys) { +void uw_Sqlcache_flushCommitOne(uw_Sqlcache_Cache *cache, char **keys) { size_t numKeys = cache->numKeys; char *key = uw_Sqlcache_allocKeyBuffer(keys, numKeys); char *buf = key; @@ -4691,3 +4698,43 @@ // All the keys were non-null and the relevant entry is present, so we delete it. uw_Sqlcache_delete(cache, entry); } + +void uw_Sqlcache_flushFree(void *data, int dontCare) { + uw_Sqlcache_Inval *inval = (uw_Sqlcache_Inval *)data; + while (inval) { + char** keys = inval->keys; + size_t numKeys = inval->cache->numKeys; + while (numKeys-- > 0) { + free(keys[numKeys]); + } + free(keys); + uw_Sqlcache_Inval *nextInval = inval->next; + free(inval); + inval = nextInval; + } +} + +void uw_Sqlcache_flushCommit(void *data) { + uw_Sqlcache_Inval *inval = (uw_Sqlcache_Inval *)data; + uw_Sqlcache_Inval *invalFirst = inval; + while (inval) { + uw_Sqlcache_Cache *cache = inval->cache; + char **keys = inval->keys; + uw_Sqlcache_flushCommitOne(cache, keys); + inval = inval->next; + } + uw_Sqlcache_flushFree(invalFirst, 0); +} + +void uw_Sqlcache_flush(uw_context ctx, uw_Sqlcache_Cache *cache, char **keys) { + uw_Sqlcache_Inval *inval = malloc(sizeof(uw_Sqlcache_Inval)); + inval->cache = cache; + inval->keys = keys; + inval->next = NULL; + if (ctx->inval) { + ctx->inval->next = inval; + } else { + uw_register_transactional(ctx, inval, uw_Sqlcache_flushCommit, NULL, uw_Sqlcache_flushFree); + } + ctx->inval = inval; +}