From eb107f25b0675e45736fb352bd172306a7f97c43 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sun, 6 Mar 2005 12:26:13 +0000 Subject: [PATCH] First steps towards a universal shared memory cache, which will be used in the multiplexer and later probably also in the search server. --- lib/qache.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/qache.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 lib/qache.c create mode 100644 lib/qache.h diff --git a/lib/qache.c b/lib/qache.c new file mode 100644 index 00000000..9f50b3c0 --- /dev/null +++ b/lib/qache.c @@ -0,0 +1,51 @@ +/* + * Simple and Quick Shared Memory Cache + * + * (c) 2005 Martin Mares + */ + +#include "sherlock/sherlock.h" + +#include + +/* FIXME: do we really need to msync() the regions on Linux? */ + +/* + * On-disk format: + * qache_header + * qache_entry[max_entries] table of entries and their keys + * u32 qache_hash[hash_size] hash table pointing to keys + * padding to a multiple of block size + * blocks[] data blocks, each block starts with u32 next_ptr + */ + +struct qache_header { + u32 magic; /* QCACHE_MAGIC */ + u32 block_size; /* Parameters as in qache_params */ + u32 num_blocks; + u32 format_id; + u32 entry_table_start; /* Array of qache_entry's */ + u32 max_entries; + u32 hash_table_start; /* Hash table containing all keys */ + u32 hash_size; + u32 lru_first; /* First entry in the LRU */ + u32 first_free_entry; /* Head of the list of free entries */ + u32 first_free_block; /* Head of the list of free blocks */ +}; + +#define QACHE_MAGIC 0xb79f6d12 + +struct qache_entry { + u32 lru_prev, lru_next; + u32 data_len; /* ~0 if a free entry */ + u32 first_data_block; /* next free if a free entry */ + qache_key_t key; + u32 hash_next; +}; + +struct qache { + struct qache_header *hdr; + int fd; + byte *mmap_data; + uns file_size; +}; diff --git a/lib/qache.h b/lib/qache.h new file mode 100644 index 00000000..b5d65f19 --- /dev/null +++ b/lib/qache.h @@ -0,0 +1,42 @@ +/* + * Simple and Quick Shared Memory Cache + * + * (c) 2005 Martin Mares + */ + +#ifndef _UCW_QACHE_H +#define _UCW_QACHE_H + +struct qache_params { + byte *file_name; + uns block_size; /* Cache block size (a power of two) */ + uns cache_size; /* Size of the whole cache */ + int force_reset; /* Force creation of a new cache even if the old one seems usable, -1 if reset should never be done */ + uns format_id; /* Data format ID (old cache not used if formats differ) */ +}; + +typedef byte qache_key_t[16]; + +/* Create and destroy a cache */ +struct qache *qache_init(struct qache_params *p); +void qache_cleanup(struct qache *q, uns retain_data); + +/* Insert new item to the cache with a given key and data. If pos_hint is non-zero, it serves + * as a hint about the position of the entry (if it's known that an entry with the particular key + * was located there a moment ago. Returns position of the new entry. + */ +uns qache_insert(struct qache *q, qache_key_t *key, uns pos_hint, void *data, uns size); + +/* Look up data in the cache, given a key and a position hint (as above). If datap is non-NULL, data + * from the cache entry are copied either to *datap (if *datap is NULL, new memory is allocated by + * calling xmalloc and *datap is set to point to that memory). The *sizep contains the maximum number + * of bytes to be copied (~0U if unlimited) and it is replaced by the number of bytes available (so it + * can be greater than the original value requested). The start indicates starting offset inside the + * entry's data. + */ +uns qache_lookup(struct qache *q, qache_key_t *key, uns pos_hint, void **datap, uns **sizep, uns start); + +/* Delete data from the cache, given a key and a position hint. */ +uns qache_delete(struct qache *q, qache_key_t *key, uns pos_hint); + +#endif -- 2.39.5