--- /dev/null
+/*
+ * Simple and Quick Shared Memory Cache
+ *
+ * (c) 2005 Martin Mares <mj@ucw.cz>
+ */
+
+#include "sherlock/sherlock.h"
+
+#include <sys/mman.h>
+
+/* 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;
+};
--- /dev/null
+/*
+ * Simple and Quick Shared Memory Cache
+ *
+ * (c) 2005 Martin Mares <mj@ucw.cz>
+ */
+
+#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