Mercurial > urweb
comparison 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 |
comparison
equal
deleted
inserted
replaced
2233:af1585e7d645 | 2234:2f7ed04332a0 |
---|---|
19 #include <math.h> | 19 #include <math.h> |
20 | 20 |
21 #include <pthread.h> | 21 #include <pthread.h> |
22 | 22 |
23 #include "types.h" | 23 #include "types.h" |
24 | |
25 #include "uthash.h" | |
24 | 26 |
25 uw_unit uw_unit_v = 0; | 27 uw_unit uw_unit_v = 0; |
26 | 28 |
27 | 29 |
28 // Socket extras | 30 // Socket extras |
4492 } | 4494 } |
4493 | 4495 |
4494 void uw_set_remoteSock(uw_context ctx, int sock) { | 4496 void uw_set_remoteSock(uw_context ctx, int sock) { |
4495 ctx->remoteSock = sock; | 4497 ctx->remoteSock = sock; |
4496 } | 4498 } |
4499 | |
4500 | |
4501 // Sqlcache | |
4502 | |
4503 void listDelete(CacheList *list, CacheEntry *entry) { | |
4504 if (list->first == entry) { | |
4505 list->first = entry->next; | |
4506 } | |
4507 if (list->last == entry) { | |
4508 list->last = entry->prev; | |
4509 } | |
4510 if (entry->prev) { | |
4511 entry->prev->next = entry->next; | |
4512 } | |
4513 if (entry->next) { | |
4514 entry->next->prev = entry->prev; | |
4515 } | |
4516 entry->prev = NULL; | |
4517 entry->next = NULL; | |
4518 --(list->size); | |
4519 } | |
4520 | |
4521 void listAdd(CacheList *list, CacheEntry *entry) { | |
4522 if (list->last) { | |
4523 list->last->next = entry; | |
4524 entry->prev = list->last; | |
4525 list->last = entry; | |
4526 } else { | |
4527 list->first = entry; | |
4528 list->last = entry; | |
4529 } | |
4530 ++(list->size); | |
4531 } | |
4532 | |
4533 void listBump(CacheList *list, CacheEntry *entry) { | |
4534 listDelete(list, entry); | |
4535 listAdd(list, entry); | |
4536 } | |
4537 | |
4538 // TODO: deal with time properly. | |
4539 | |
4540 time_t getTimeNow() { | |
4541 return time(NULL); | |
4542 } | |
4543 | |
4544 time_t timeMax(time_t x, time_t y) { | |
4545 return difftime(x, y) > 0 ? x : y; | |
4546 } | |
4547 | |
4548 void freeCacheValue(CacheValue *value) { | |
4549 if (value) { | |
4550 free(value->result); | |
4551 free(value->output); | |
4552 free(value); | |
4553 } | |
4554 } | |
4555 | |
4556 void delete(Cache *cache, CacheEntry* entry) { | |
4557 //listDelete(cache->lru, entry); | |
4558 HASH_DELETE(hh, cache->table, entry); | |
4559 freeCacheValue(entry->value); | |
4560 free(entry->key); | |
4561 free(entry); | |
4562 } | |
4563 | |
4564 CacheValue *checkHelper(Cache *cache, char **keys, int timeInvalid) { | |
4565 char *key = keys[cache->height]; | |
4566 CacheEntry *entry; | |
4567 HASH_FIND(hh, cache->table, key, strlen(key), entry); | |
4568 timeInvalid = timeMax(timeInvalid, cache->timeInvalid); | |
4569 if (entry && difftime(entry->timeValid, timeInvalid) > 0) { | |
4570 if (cache->height == 0) { | |
4571 // At height 0, entry->value is the desired value. | |
4572 //listBump(cache->lru, entry); | |
4573 return entry->value; | |
4574 } else { | |
4575 // At height n+1, entry->value is a pointer to a cache at heignt n. | |
4576 return checkHelper(entry->value, keys, timeInvalid); | |
4577 } | |
4578 } else { | |
4579 return NULL; | |
4580 } | |
4581 } | |
4582 | |
4583 CacheValue *check(Cache *cache, char **keys) { | |
4584 return checkHelper(cache, keys, 0); | |
4585 } | |
4586 | |
4587 void storeHelper(Cache *cache, char **keys, CacheValue *value, int timeNow) { | |
4588 CacheEntry *entry; | |
4589 char *key = keys[cache->height]; | |
4590 HASH_FIND(hh, cache->table, key, strlen(key), entry); | |
4591 if (!entry) { | |
4592 entry = malloc(sizeof(CacheEntry)); | |
4593 entry->key = strdup(key); | |
4594 entry->value = NULL; | |
4595 HASH_ADD_KEYPTR(hh, cache->table, entry->key, strlen(entry->key), entry); | |
4596 } | |
4597 entry->timeValid = timeNow; | |
4598 if (cache->height == 0) { | |
4599 //listAdd(cache->lru, entry); | |
4600 freeCacheValue(entry->value); | |
4601 entry->value = value; | |
4602 //if (cache->lru->size > MAX_SIZE) { | |
4603 //delete(cache, cache->lru->first); | |
4604 // TODO: return flushed value. | |
4605 //} | |
4606 } else { | |
4607 if (!entry->value) { | |
4608 Cache *newCache = malloc(sizeof(Cache)); | |
4609 newCache->table = NULL; | |
4610 newCache->timeInvalid = timeNow; | |
4611 newCache->lru = cache->lru; | |
4612 newCache->height = cache->height - 1; | |
4613 entry->value = newCache; | |
4614 } | |
4615 storeHelper(entry->value, keys, value, timeNow); | |
4616 } | |
4617 } | |
4618 | |
4619 void store(Cache *cache, char **keys, CacheValue *value) { | |
4620 storeHelper(cache, keys, value, getTimeNow()); | |
4621 } | |
4622 | |
4623 void flushHelper(Cache *cache, char **keys, int timeNow) { | |
4624 CacheEntry *entry; | |
4625 char *key = keys[cache->height]; | |
4626 if (key) { | |
4627 HASH_FIND(hh, cache->table, key, strlen(key), entry); | |
4628 if (entry) { | |
4629 if (cache->height == 0) { | |
4630 delete(cache, entry); | |
4631 } else { | |
4632 flushHelper(entry->value, keys, timeNow); | |
4633 } | |
4634 } | |
4635 } else { | |
4636 // Null key means invalidate the entire subtree. | |
4637 cache->timeInvalid = timeNow; | |
4638 } | |
4639 } | |
4640 | |
4641 void flush(Cache *cache, char **keys) { | |
4642 flushHelper(cache, keys, getTimeNow()); | |
4643 } |