diff options
Diffstat (limited to 'src/c')
-rw-r--r-- | src/c/openssl.c | 2 | ||||
-rw-r--r-- | src/c/urweb.c | 172 |
2 files changed, 173 insertions, 1 deletions
diff --git a/src/c/openssl.c b/src/c/openssl.c index 206a3bc8..981d48da 100644 --- a/src/c/openssl.c +++ b/src/c/openssl.c @@ -79,7 +79,7 @@ void uw_init_crypto() { if (access(uw_sig_file, F_OK)) { random_password(); - + if ((fd = open(uw_sig_file, O_WRONLY | O_CREAT, 0700)) < 0) { fprintf(stderr, "Can't open signature file %s\n", uw_sig_file); perror("open"); diff --git a/src/c/urweb.c b/src/c/urweb.c index 6d3836f1..957f158c 100644 --- a/src/c/urweb.c +++ b/src/c/urweb.c @@ -22,6 +22,8 @@ #include "types.h" +#include "uthash.h" + uw_unit uw_unit_v = 0; @@ -70,6 +72,9 @@ void uw_buffer_free(uw_buffer *b) { void uw_buffer_reset(uw_buffer *b) { b->front = b->start; + if (b->front != b->back) { + *b->front = 0; + } } int uw_buffer_check(uw_buffer *b, size_t extra) { @@ -483,6 +488,10 @@ struct uw_context { char *output_buffer; size_t output_buffer_size; + // For caching. + int numRecording; + int recordingOffset; + int remoteSock; }; @@ -567,6 +576,9 @@ uw_context uw_init(int id, uw_loggers *lg) { ctx->output_buffer = malloc(1); ctx->output_buffer_size = 1; + ctx->numRecording = 0; + ctx->recordingOffset = 0; + ctx->remoteSock = -1; return ctx; @@ -1681,6 +1693,21 @@ void uw_write(uw_context ctx, const char* s) { *ctx->page.front = 0; } +void uw_recordingStart(uw_context ctx) { + if (ctx->numRecording++ == 0) { + ctx->recordingOffset = ctx->page.front - ctx->page.start; + } +} + +char *uw_recordingRead(uw_context ctx) { + // Only the outermost recorder can read unless the recording is empty. + char *recording = ctx->page.start + ctx->recordingOffset; + if (--ctx->numRecording > 0 && recording != ctx->page.front) { + return NULL; + } + return strdup(recording); +} + char *uw_Basis_attrifyInt(uw_context ctx, uw_Basis_int n) { char *result; int len; @@ -4479,3 +4506,148 @@ int uw_remoteSock(uw_context ctx) { void uw_set_remoteSock(uw_context ctx, int sock) { ctx->remoteSock = sock; } + + +// Sqlcache + +void uw_Sqlcache_listDelete(uw_Sqlcache_CacheList *list, uw_Sqlcache_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 uw_Sqlcache_listAdd(uw_Sqlcache_CacheList *list, uw_Sqlcache_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 uw_Sqlcache_listBump(uw_Sqlcache_CacheList *list, uw_Sqlcache_CacheEntry *entry) { + uw_Sqlcache_listDelete(list, entry); + uw_Sqlcache_listAdd(list, entry); +} + +// TODO: deal with time properly. + +time_t uw_Sqlcache_getTimeNow() { + return time(NULL); +} + +time_t uw_Sqlcache_timeMax(time_t x, time_t y) { + return difftime(x, y) > 0 ? x : y; +} + +void uw_Sqlcache_free(uw_Sqlcache_CacheValue *value) { + if (value) { + free(value->result); + free(value->output); + free(value); + } +} + +void uw_Sqlcache_delete(uw_Sqlcache_Cache *cache, uw_Sqlcache_CacheEntry* entry) { + //uw_Sqlcache_listUw_Sqlcache_Delete(cache->lru, entry); + HASH_DELETE(hh, cache->table, entry); + uw_Sqlcache_free(entry->value); + free(entry->key); + free(entry); +} + +uw_Sqlcache_CacheValue *uw_Sqlcache_checkHelper(uw_Sqlcache_Cache *cache, char **keys, int timeInvalid) { + char *key = keys[cache->height]; + uw_Sqlcache_CacheEntry *entry; + HASH_FIND(hh, cache->table, key, strlen(key), entry); + timeInvalid = uw_Sqlcache_timeMax(timeInvalid, cache->timeInvalid); + if (entry && difftime(entry->timeValid, timeInvalid) > 0) { + if (cache->height == 0) { + // At height 0, entry->value is the desired value. + //uw_Sqlcache_listBump(cache->lru, entry); + return entry->value; + } else { + // At height n+1, entry->value is a pointer to a cache at heignt n. + return uw_Sqlcache_checkHelper(entry->value, keys, timeInvalid); + } + } else { + return NULL; + } +} + +uw_Sqlcache_CacheValue *uw_Sqlcache_check(uw_Sqlcache_Cache *cache, char **keys) { + return uw_Sqlcache_checkHelper(cache, keys, 0); +} + +void uw_Sqlcache_storeHelper(uw_Sqlcache_Cache *cache, char **keys, uw_Sqlcache_CacheValue *value, int timeNow) { + uw_Sqlcache_CacheEntry *entry; + char *key = keys[cache->height]; + HASH_FIND(hh, cache->table, key, strlen(key), entry); + if (!entry) { + entry = malloc(sizeof(uw_Sqlcache_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) { + //uw_Sqlcache_listAdd(cache->lru, entry); + uw_Sqlcache_free(entry->value); + entry->value = value; + //if (cache->lru->size > MAX_SIZE) { + //uw_Sqlcache_delete(cache, cache->lru->first); + // TODO: return flushed value. + //} + } else { + if (!entry->value) { + uw_Sqlcache_Cache *newuw_Sqlcache_Cache = malloc(sizeof(uw_Sqlcache_Cache)); + newuw_Sqlcache_Cache->table = NULL; + newuw_Sqlcache_Cache->timeInvalid = timeNow; + newuw_Sqlcache_Cache->lru = cache->lru; + newuw_Sqlcache_Cache->height = cache->height - 1; + entry->value = newuw_Sqlcache_Cache; + } + uw_Sqlcache_storeHelper(entry->value, keys, value, timeNow); + } +} + +void uw_Sqlcache_store(uw_Sqlcache_Cache *cache, char **keys, uw_Sqlcache_CacheValue *value) { + uw_Sqlcache_storeHelper(cache, keys, value, uw_Sqlcache_getTimeNow()); +} + +void uw_Sqlcache_flushHelper(uw_Sqlcache_Cache *cache, char **keys, int timeNow) { + uw_Sqlcache_CacheEntry *entry; + char *key = keys[cache->height]; + if (key) { + HASH_FIND(hh, cache->table, key, strlen(key), entry); + if (entry) { + if (cache->height == 0) { + uw_Sqlcache_delete(cache, entry); + } else { + uw_Sqlcache_flushHelper(entry->value, keys, timeNow); + } + } + } else { + // Null key means invalidate the entire subtree. + cache->timeInvalid = timeNow; + } +} + +void uw_Sqlcache_flush(uw_Sqlcache_Cache *cache, char **keys) { + uw_Sqlcache_flushHelper(cache, keys, uw_Sqlcache_getTimeNow()); +} |