proc-cache.c: lazy delete
Use lazy delete mechanism to remove the need for linked list delete. This removes the need for a sentinel node at the beginning.
This commit is contained in:
parent
51f7286ab8
commit
ae91737fb1
1 changed files with 26 additions and 29 deletions
55
proc-cache.c
55
proc-cache.c
|
|
@ -48,6 +48,9 @@ union hash {
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* hash entry flags */
|
||||||
|
#define HE_FLAG_VALID (1 << 0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
@ -55,9 +58,12 @@ union hash {
|
||||||
struct proc_cache_entry {
|
struct proc_cache_entry {
|
||||||
union hash hash;
|
union hash hash;
|
||||||
unsigned int time;
|
unsigned int time;
|
||||||
|
unsigned int flags;
|
||||||
struct llist list;
|
struct llist list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define he_empty(x) (!(x) || !((x)->flags & HE_FLAG_VALID))
|
||||||
|
|
||||||
static struct lockfile lock = LOCKFILE_INIT;
|
static struct lockfile lock = LOCKFILE_INIT;
|
||||||
static struct hash_table table = HASH_TABLE_INIT;
|
static struct hash_table table = HASH_TABLE_INIT;
|
||||||
|
|
||||||
|
|
@ -93,7 +99,7 @@ static struct proc_cache_entry* lookup(const char *key) {
|
||||||
llist_foreach(it, entry->list.next) {
|
llist_foreach(it, entry->list.next) {
|
||||||
e = llist_entry(it, struct proc_cache_entry, list);
|
e = llist_entry(it, struct proc_cache_entry, list);
|
||||||
|
|
||||||
if (!memcmp(e->hash.sha1, h.sha1, 20))
|
if (!he_empty(e) && !memcmp(e->hash.sha1, h.sha1, 20))
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -102,32 +108,26 @@ static struct proc_cache_entry* lookup(const char *key) {
|
||||||
|
|
||||||
static void he_insert(struct proc_cache_entry *entry) {
|
static void he_insert(struct proc_cache_entry *entry) {
|
||||||
|
|
||||||
struct proc_cache_entry *dest, *s;
|
struct proc_cache_entry *dest;
|
||||||
|
|
||||||
s = calloc(1, sizeof(*s));
|
dest = hash_insert(&table, entry->hash.index, entry);
|
||||||
|
|
||||||
dest = hash_insert(&table, entry->hash.index, s);
|
|
||||||
if (dest) {
|
if (dest) {
|
||||||
struct llist *it;
|
struct llist *it;
|
||||||
struct proc_cache_entry *e;
|
struct proc_cache_entry *e;
|
||||||
|
|
||||||
free(s);
|
llist_foreach(it, &dest->list) {
|
||||||
|
|
||||||
llist_foreach(it, dest->list.next) {
|
|
||||||
|
|
||||||
e = llist_entry(it, struct proc_cache_entry, list);
|
e = llist_entry(it, struct proc_cache_entry, list);
|
||||||
|
|
||||||
if (!memcmp(entry->hash.sha1, e->hash.sha1, 20)) {
|
if (!he_empty(e) &&
|
||||||
|
!memcmp(e->hash.sha1, entry->hash.sha1, 20)) {
|
||||||
free(entry);
|
free(entry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
llist_add(&dest->list, &entry->list);
|
llist_add(&dest->list, &entry->list);
|
||||||
} else {
|
|
||||||
s->hash.index = entry->hash.index;
|
|
||||||
llist_add(&s->list, &entry->list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entry->flags |= HE_FLAG_VALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void build_table(const char *buf, size_t entries) {
|
static void build_table(const char *buf, size_t entries) {
|
||||||
|
|
@ -240,24 +240,16 @@ void proc_cache_purge(unsigned int timestamp) {
|
||||||
|
|
||||||
t = now - timestamp;
|
t = now - timestamp;
|
||||||
for(i=0; i < table.size; i++) {
|
for(i=0; i < table.size; i++) {
|
||||||
struct llist *it, *n;
|
struct llist *it;
|
||||||
struct proc_cache_entry *e, *entry = hash_entry(&table, i);
|
struct proc_cache_entry *e, *entry = hash_entry(&table, i);
|
||||||
|
|
||||||
if (!entry)
|
if (!entry)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
llist_foreach_safe(it, n, entry->list.next) {
|
llist_foreach(it, &entry->list) {
|
||||||
e = llist_entry(it, struct proc_cache_entry, list);
|
e = llist_entry(it, struct proc_cache_entry, list);
|
||||||
if (e->time <= t) {
|
if (!he_empty(e) && e->time <= t)
|
||||||
llist_del(&entry->list, it);
|
e->flags &= ~HE_FLAG_VALID;
|
||||||
free(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (llist_empty(&entry->list)) {
|
|
||||||
e = hash_remove(&table, entry->hash.index);
|
|
||||||
if (e)
|
|
||||||
free(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -298,9 +290,14 @@ void proc_cache_close() {
|
||||||
if (!entry)
|
if (!entry)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
llist_foreach(it, entry->list.next) {
|
llist_foreach(it, &entry->list) {
|
||||||
write_entry(fd, llist_entry(it, struct proc_cache_entry, list));
|
struct proc_cache_entry *e;
|
||||||
hdr.entries++;
|
|
||||||
|
e = llist_entry(it, struct proc_cache_entry, list);
|
||||||
|
if (!he_empty(e)) {
|
||||||
|
write_entry(fd, e);
|
||||||
|
hdr.entries++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Reference in a new issue