Mercurial > urweb
comparison src/c/urweb.c @ 2291:50ad02829abd
Make cache flushes happen immediately instead of at end of transaction.
author | Ziv Scully <ziv@mit.edu> |
---|---|
date | Tue, 17 Nov 2015 02:44:37 -0500 |
parents | 98f96a976ede |
children | 5104e480b3e3 |
comparison
equal
deleted
inserted
replaced
2290:ab6ca12debeb | 2291:50ad02829abd |
---|---|
4583 | 4583 |
4584 // TODO: pick a number. | 4584 // TODO: pick a number. |
4585 static unsigned int uw_Sqlcache_maxSize = 1234567890; | 4585 static unsigned int uw_Sqlcache_maxSize = 1234567890; |
4586 | 4586 |
4587 static void uw_Sqlcache_delete(uw_Sqlcache_Cache *cache, uw_Sqlcache_Entry *entry) { | 4587 static void uw_Sqlcache_delete(uw_Sqlcache_Cache *cache, uw_Sqlcache_Entry *entry) { |
4588 HASH_DEL(cache->table, entry); | 4588 if (entry) { |
4589 uw_Sqlcache_freeEntry(entry); | 4589 HASH_DEL(cache->table, entry); |
4590 uw_Sqlcache_freeEntry(entry); | |
4591 } | |
4590 } | 4592 } |
4591 | 4593 |
4592 static uw_Sqlcache_Entry *uw_Sqlcache_find(uw_Sqlcache_Cache *cache, char *key, size_t len, int bump) { | 4594 static uw_Sqlcache_Entry *uw_Sqlcache_find(uw_Sqlcache_Cache *cache, char *key, size_t len, int bump) { |
4593 uw_Sqlcache_Entry *entry = NULL; | 4595 uw_Sqlcache_Entry *entry = NULL; |
4594 HASH_FIND(hh, cache->table, key, len, entry); | 4596 HASH_FIND(hh, cache->table, key, len, entry); |
4721 entry->value->timeValid = timeNow; | 4723 entry->value->timeValid = timeNow; |
4722 pthread_rwlock_unlock(&cache->lockIn); | 4724 pthread_rwlock_unlock(&cache->lockIn); |
4723 } | 4725 } |
4724 | 4726 |
4725 static void uw_Sqlcache_flushCommitOne(uw_Sqlcache_Cache *cache, char **keys) { | 4727 static void uw_Sqlcache_flushCommitOne(uw_Sqlcache_Cache *cache, char **keys) { |
4726 pthread_rwlock_wrlock(&cache->lockIn); | |
4727 size_t numKeys = cache->numKeys; | |
4728 if (numKeys == 0) { | |
4729 uw_Sqlcache_Entry *entry = cache->table; | |
4730 if (entry) { | |
4731 uw_Sqlcache_freeValue(entry->value); | |
4732 entry->value = NULL; | |
4733 } | |
4734 } else { | |
4735 char *key = uw_Sqlcache_allocKeyBuffer(keys, numKeys); | |
4736 char *buf = key; | |
4737 time_t timeNow = uw_Sqlcache_getTimeNow(cache); | |
4738 uw_Sqlcache_Entry *entry = NULL; | |
4739 while (numKeys-- > 0) { | |
4740 char *k = keys[numKeys]; | |
4741 if (!k) { | |
4742 if (entry) { | |
4743 entry->timeInvalid = timeNow; | |
4744 } else { | |
4745 // Haven't found an entry yet, so the first key was null. | |
4746 cache->timeInvalid = timeNow; | |
4747 } | |
4748 free(key); | |
4749 pthread_rwlock_unlock(&cache->lockIn); | |
4750 return; | |
4751 } | |
4752 buf = uw_Sqlcache_keyCopy(buf, k); | |
4753 size_t len = buf - key; | |
4754 entry = uw_Sqlcache_find(cache, key, len, 0); | |
4755 if (!entry) { | |
4756 // Nothing in the cache to flush. | |
4757 free(key); | |
4758 pthread_rwlock_unlock(&cache->lockIn); | |
4759 return; | |
4760 } | |
4761 } | |
4762 free(key); | |
4763 // All the keys were non-null and the relevant entry is present, so we delete it. | |
4764 uw_Sqlcache_delete(cache, entry); | |
4765 } | |
4766 pthread_rwlock_unlock(&cache->lockIn); | |
4767 } | 4728 } |
4768 | 4729 |
4769 static void uw_Sqlcache_commit(void *data) { | 4730 static void uw_Sqlcache_commit(void *data) { |
4770 uw_context ctx = (uw_context)data; | 4731 uw_context ctx = (uw_context)data; |
4771 uw_Sqlcache_Update *update = ctx->cacheUpdate; | 4732 uw_Sqlcache_Update *update = ctx->cacheUpdate; |
4851 } | 4812 } |
4852 ctx->cacheUpdateTail = update; | 4813 ctx->cacheUpdateTail = update; |
4853 } | 4814 } |
4854 | 4815 |
4855 void uw_Sqlcache_flush(uw_context ctx, uw_Sqlcache_Cache *cache, char **keys) { | 4816 void uw_Sqlcache_flush(uw_context ctx, uw_Sqlcache_Cache *cache, char **keys) { |
4856 // A flush is represented in the queue as storing NULL. | 4817 // A flush has to happen immediately so that subsequent stores in the same transaction fail. |
4857 uw_Sqlcache_store(ctx, cache, keys, NULL); | 4818 // This is safe to do because we will always call [uw_Sqlcache_wlock] earlier. |
4858 } | 4819 // If the transaction fails, the only harm done is a few extra cache misses. |
4820 pthread_rwlock_wrlock(&cache->lockIn); | |
4821 size_t numKeys = cache->numKeys; | |
4822 if (numKeys == 0) { | |
4823 uw_Sqlcache_Entry *entry = cache->table; | |
4824 if (entry) { | |
4825 uw_Sqlcache_freeValue(entry->value); | |
4826 entry->value = NULL; | |
4827 } | |
4828 } else { | |
4829 char *key = uw_Sqlcache_allocKeyBuffer(keys, numKeys); | |
4830 char *buf = key; | |
4831 time_t timeNow = uw_Sqlcache_getTimeNow(cache); | |
4832 while (numKeys-- > 0) { | |
4833 char *k = keys[numKeys]; | |
4834 if (!k) { | |
4835 size_t len = buf - key; | |
4836 if (len == 0) { | |
4837 // The first key was null. | |
4838 cache->timeInvalid = timeNow; | |
4839 } else { | |
4840 uw_Sqlcache_Entry *entry = uw_Sqlcache_find(cache, key, len, 0); | |
4841 if (entry) { | |
4842 entry->timeInvalid = timeNow; | |
4843 } | |
4844 } | |
4845 free(key); | |
4846 pthread_rwlock_unlock(&cache->lockIn); | |
4847 return; | |
4848 } | |
4849 buf = uw_Sqlcache_keyCopy(buf, k); | |
4850 } | |
4851 // All the keys were non-null, so we delete the pointed-to entry. | |
4852 size_t len = buf - key; | |
4853 uw_Sqlcache_Entry *entry = uw_Sqlcache_find(cache, key, len, 0); | |
4854 free(key); | |
4855 uw_Sqlcache_delete(cache, entry); | |
4856 } | |
4857 pthread_rwlock_unlock(&cache->lockIn); | |
4858 } |