aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/c/urweb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/c/urweb.c')
-rw-r--r--src/c/urweb.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/c/urweb.c b/src/c/urweb.c
index 6d3836f1..66fedfa2 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;
@@ -483,6 +485,9 @@ struct uw_context {
char *output_buffer;
size_t output_buffer_size;
+ // For caching.
+ char *recording;
+
int remoteSock;
};
@@ -567,6 +572,8 @@ uw_context uw_init(int id, uw_loggers *lg) {
ctx->output_buffer = malloc(1);
ctx->output_buffer_size = 1;
+ ctx->recording = 0;
+
ctx->remoteSock = -1;
return ctx;
@@ -1681,6 +1688,14 @@ void uw_write(uw_context ctx, const char* s) {
*ctx->page.front = 0;
}
+void uw_recordingStart(uw_context ctx) {
+ ctx->recording = ctx->page.front;
+}
+
+char *uw_recordingRead(uw_context ctx) {
+ return strdup(ctx->recording);
+}
+
char *uw_Basis_attrifyInt(uw_context ctx, uw_Basis_int n) {
char *result;
int len;
@@ -4479,3 +4494,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_freeuw_sqlcache_CacheValue(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_freeuw_sqlcache_CacheValue(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_freeuw_sqlcache_CacheValue(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());
+}