Archived
1
0
Fork 0

proc-cache.c: use hash-table code from hash.c

This commit is contained in:
Henrik Hautakoski 2012-04-12 07:46:28 +02:00
parent 5193e8453c
commit 4f05a5ae4f
2 changed files with 51 additions and 134 deletions

View file

@ -11,7 +11,7 @@ install : $(PROGRAMS)
cp $^ $(HOME)/bin/ cp $^ $(HOME)/bin/
dlight : dlight.o buffer.o env.o http.o rss.o lockfile.o filter.o cconf.o \ dlight : dlight.o buffer.o env.o http.o rss.o lockfile.o filter.o cconf.o \
sha1_io.o proc-cache.o dlhist.o error.o sha1_io.o proc-cache.o dlhist.o hash.o error.o
dlight-compile : compile.o buffer.o env.o lockfile.o filter.o cconf.o \ dlight-compile : compile.o buffer.o env.o lockfile.o filter.o cconf.o \
sha1_io.o error.o sha1_io.o error.o
dlight-read-config : read-config.o buffer.o env.o cconf.o sha1_io.o error.o dlight-read-config : read-config.o buffer.o env.o cconf.o sha1_io.o error.o

View file

@ -28,6 +28,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <time.h> #include <time.h>
#include "env.h" #include "env.h"
#include "hash.h"
#include "lockfile.h" #include "lockfile.h"
#include "proc-cache.h" #include "proc-cache.h"
@ -35,10 +36,6 @@
#define SIGNATURE 0xAF445043 #define SIGNATURE 0xAF445043
#define STORAGE_FILE "proc-cache" #define STORAGE_FILE "proc-cache"
#define TABLE_MIN_SIZE 128
#define HASH_TABLE_LOAD(c, s) ((double) (c) / ((s) ? (s) : 1))
struct header { struct header {
unsigned int signature; unsigned int signature;
unsigned int version; unsigned int version;
@ -54,18 +51,13 @@ union hash {
* NOTE: be sure to change this constant if the struct's size changes. * NOTE: be sure to change this constant if the struct's size changes.
*/ */
#define HE_SZ (sizeof(union hash) + sizeof(unsigned)) #define HE_SZ (sizeof(union hash) + sizeof(unsigned))
struct hash_entry { struct proc_cache_entry {
union hash hash; union hash hash;
unsigned int time; unsigned int time;
}; };
#define he_empty(x) (!(x) || (x)->hash.index == 0)
static struct lockfile lock = LOCKFILE_INIT; static struct lockfile lock = LOCKFILE_INIT;
static struct hash_table table = HASH_TABLE_INIT;
static struct hash_entry *table;
static unsigned int table_size;
static unsigned int table_count;
static void hash(union hash *h, const char *s) { static void hash(union hash *h, const char *s) {
@ -84,110 +76,41 @@ static void hash(union hash *h, const char *s) {
SHA1((unsigned char *)s, n, h->sha1); SHA1((unsigned char *)s, n, h->sha1);
} }
static struct hash_entry* translate(union hash *he) { static struct proc_cache_entry* lookup(const char *key) {
unsigned int offset = he->index % table_size;
/* linear probing */
while(!he_empty(table + offset)) {
if (!memcmp(table[offset].hash.sha1, he->sha1, 20))
break;
offset = (offset + 1) % table_size;
}
return table + offset;
}
static struct hash_entry* lookup(const char *key) {
union hash h; union hash h;
hash(&h, key); hash(&h, key);
return translate(&h); return hash_lookup(&table, h.index);
} }
static inline void he_set(struct hash_entry *he, const char *key) { static void he_insert(struct proc_cache_entry *entry) {
if (!he_empty(he)) struct proc_cache_entry *dest;
return;
hash(&he->hash, key); dest = hash_insert(&table, entry->hash.index, entry);
table_count++; if (dest) {
memcpy(dest, entry, sizeof(*entry));
free(entry);
} }
static int he_insert(struct hash_entry *he) {
struct hash_entry *dest = translate(&he->hash);
if (he_empty(dest)) {
memcpy(dest, he, sizeof(*he));
table_count++;
return 1;
}
return 0;
}
static void he_remove(struct hash_entry *he) {
memset(he, 0, sizeof(*he));
table_count--;
}
static unsigned calculate_size(unsigned count) {
/*
* set size to a load factor that is in the
* middle in the valid range.
*/
unsigned size = count / 0.625;
if (size < TABLE_MIN_SIZE)
size = TABLE_MIN_SIZE;
return size;
}
static void resize_table() {
double load;
unsigned int i, old_size = table_size;
struct hash_entry *old = table;
load = HASH_TABLE_LOAD(table_count, table_size);
/* check if resize should be done */
if ((load < 0.5 && table_size <= TABLE_MIN_SIZE) ||
(load >= 0.5 && load <= 0.75))
return;
table_size = calculate_size(table_count);
table_count = 0;
table = calloc(sizeof(*table), table_size);
for(i=0; i < old_size; i++) {
struct hash_entry *he = old + i;
if (!he_empty(he))
he_insert(he);
}
free(old);
} }
static void build_table(const char *buf, size_t entries) { static void build_table(const char *buf, size_t entries) {
size_t i, offset = 0; size_t i, offset = 0;
table_size = calculate_size(entries);
table = calloc(sizeof(*table), table_size);
for(i=0; i < entries; i++) { for(i=0; i < entries; i++) {
struct hash_entry entry; struct proc_cache_entry *entry = calloc(1, sizeof(*entry));
memcpy(&entry.hash, buf + offset, sizeof(entry.hash)); memcpy(&entry->hash, buf + offset, sizeof(entry->hash));
offset += sizeof(entry.hash); offset += sizeof(entry->hash);
memcpy(&entry.time, buf + offset, sizeof(entry.time)); memcpy(&entry->time, buf + offset, sizeof(entry->time));
offset += sizeof(entry.time); offset += sizeof(entry->time);
entry.hash.index = ntohl(entry.hash.index); entry->hash.index = ntohl(entry->hash.index);
entry.time = ntohl(entry.time); entry->time = ntohl(entry->time);
he_insert(&entry); he_insert(entry);
} }
} }
@ -257,48 +180,41 @@ error:
int proc_cache_lookup(const char *url) { int proc_cache_lookup(const char *url) {
if (table_size) { return lookup(url) != NULL;
struct hash_entry *he = lookup(url);
return !he_empty(he);
}
return 0;
} }
void proc_cache_update(const char *url) { void proc_cache_update(const char *url) {
struct hash_entry *he; struct proc_cache_entry *entry = lookup(url);
if (table_size < 1) if (!entry) {
return; entry = calloc(1, sizeof(*entry));
hash(&entry->hash, url);
/* he_insert(entry);
* set time and key before resize,
* hash_entry pointer is invalid after that operation.
*/
he = lookup(url);
he->time = time(NULL);
if (he_empty(he)) {
he_set(he, url);
resize_table();
} }
entry->time = time(NULL);
} }
void proc_cache_purge(unsigned int timestamp) { void proc_cache_purge(unsigned int timestamp) {
unsigned int i, t = 0, now = time(NULL); unsigned int i, t, now = time(NULL);
if (now < timestamp) if (now < timestamp)
return; return;
t = now - timestamp; t = now - timestamp;
for(i=0; i < table_size; i++) { for(i=0; i < table.size; i++) {
struct hash_entry *entry = table + i; struct proc_cache_entry *entry = hash_entry(&table, i);
if (!he_empty(entry) && entry->time <= t) if (!entry)
he_remove(entry); continue;
if (entry->time <= t) {
entry = hash_remove(&table, entry->hash.index);
if (entry)
free(entry);
}
} }
resize_table();
} }
void proc_cache_flush() { void proc_cache_flush() {
@ -307,24 +223,21 @@ void proc_cache_flush() {
struct header hdr; struct header hdr;
int fd = lock.fd; int fd = lock.fd;
if (table_size < 1) if (table.size < 1)
return; return;
ftruncate(fd, 0);
lseek(fd, 0, SEEK_SET);
/* Write header */ /* Write header */
hdr.signature = htonl(SIGNATURE); hdr.signature = htonl(SIGNATURE);
hdr.version = htonl(1); hdr.version = htonl(1);
hdr.entries = htonl(table_count); hdr.entries = htonl(table.count);
write(fd, &hdr, sizeof(hdr)); write(fd, &hdr, sizeof(hdr));
/* Write hash entries */ /* Write hash entries */
for(i=0; i < table_size; i++) { for(i=0; i < table.size; i++) {
struct hash_entry ondisk, *entry = table + i; struct proc_cache_entry ondisk, *entry = hash_entry(&table, i);
if (he_empty(entry)) if (!entry)
continue; continue;
memcpy(&ondisk.hash, &entry->hash, 20); memcpy(&ondisk.hash, &entry->hash, 20);
@ -341,12 +254,16 @@ void proc_cache_flush() {
void proc_cache_close() { void proc_cache_close() {
int i;
proc_cache_flush(); proc_cache_flush();
release_lock(&lock); release_lock(&lock);
if (table) for(i=0; i < table.size; i++) {
free(table); struct proc_cache_entry *entry = hash_entry(&table, i);
table = NULL; if (entry)
table_count = table_size = 0; free(entry);
}
hash_free(&table);
} }