#undef LOCAL_DEBUG
#include "lib/lib.h"
+#include "lib/bitops.h"
#include "lib/fastbuf.h"
#include "lib/qache.h"
-#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
bzero(&h, sizeof(h));
h.magic = QACHE_MAGIC;
h.block_size = par->block_size;
- h.block_shift = fls(h.block_size);
+ h.block_shift = bit_fls(h.block_size);
h.num_blocks = par->cache_size >> h.block_shift;
h.format_id = par->format_id;
h.entry_table_start = sizeof(h);
log(L_INFO, "Cache %s: created (%d bytes, %d slots, %d buckets)", q->file_name, par->cache_size, h.max_entries, h.hash_size);
if ((q->mmap_data = mmap(NULL, par->cache_size, PROT_READ | PROT_WRITE, MAP_SHARED, q->fd, 0)) == MAP_FAILED)
- die("Cache %s: mmap failed (%m)", par->cache_size);
+ die("Cache %s: mmap failed (%m)", par->file_name);
q->file_size = par->cache_size;
qache_setup_pointers(q);
}
if (par->force_reset <= 0 && qache_open_existing(q, par))
;
else if (par->force_reset < 0)
- die("Cache %s: read-only access requested, but no data available");
+ die("Cache %s: read-only access requested, but no data available", q->file_name);
else
qache_create(q, par);
return q;
{
ASSERT(q->locked);
- if (pos_hint && pos_hint < q->hdr->max_entries && !memcmp(q->entry_table[pos_hint].key, key, sizeof(*key)))
+ if (pos_hint && pos_hint < q->hdr->max_entries && q->entry_table[pos_hint].data_len != ~0U && !memcmp(q->entry_table[pos_hint].key, key, sizeof(*key)))
return pos_hint;
uns h = qache_hash(q, key);
return e;
}
+static void
+copy_out(struct qache *q, struct qache_entry *entry, byte **datap, uns *sizep, uns start)
+{
+ if (sizep)
+ {
+ uns size = *sizep;
+ uns avail = (start > entry->data_len) ? 0 : entry->data_len - start;
+ uns xfer = MIN(size, avail);
+ *sizep = avail;
+ if (datap)
+ {
+ if (!*datap)
+ *datap = xmalloc(xfer);
+ uns blk = entry->first_data_block;
+ while (start >= q->hdr->block_size)
+ {
+ blk = q->next_table[blk];
+ start -= q->hdr->block_size;
+ }
+ byte *data = *datap;
+ while (xfer)
+ {
+ uns len = MIN(xfer, q->hdr->block_size - start);
+ memcpy(data, get_block_start(q, blk), len);
+ blk = q->next_table[blk];
+ data += len;
+ xfer -= len;
+ start = 0;
+ }
+ }
+ }
+ else
+ ASSERT(!datap);
+}
+
uns
qache_lookup(struct qache *q, qache_key_t *key, uns pos_hint, byte **datap, uns *sizep, uns start)
{
DBG("Lookup <%s>: found entry %d", format_key(key), e);
qache_lru_remove(q, e);
qache_lru_insert(q, e);
- if (sizep)
- {
- uns size = *sizep;
- uns avail = (start > entry->data_len) ? 0 : entry->data_len - start;
- uns xfer = MIN(size, avail);
- *sizep = avail;
- if (datap)
- {
- if (!*datap)
- *datap = xmalloc(xfer);
- uns blk = entry->first_data_block;
- while (start >= q->hdr->block_size)
- {
- blk = q->next_table[blk];
- start -= q->hdr->block_size;
- }
- byte *data = *datap;
- while (xfer)
- {
- uns len = MIN(xfer, q->hdr->block_size - start);
- memcpy(data, get_block_start(q, blk), len);
- blk = q->next_table[blk];
- data += len;
- xfer -= len;
- start = 0;
- }
- }
- }
- else
- ASSERT(!datap);
+ copy_out(q, entry, datap, sizep, start);
qache_unlock(q, 1); /* Yes, modified -- we update the LRU */
}
else
return e;
}
+uns
+qache_probe(struct qache *q, qache_key_t *key, uns pos, byte **datap, uns *sizep, uns start)
+{
+ if (!pos || pos >= q->hdr->max_entries)
+ {
+ DBG("Probe %d: Out of range", pos);
+ return ~0U;
+ }
+
+ qache_lock(q);
+ uns ret = 0;
+ struct qache_entry *entry = &q->entry_table[pos];
+ if (entry->data_len != ~0U)
+ {
+ DBG("Probe %d: Found key <%s>", format_key(entry->key));
+ if (key)
+ memcpy(key, entry->key, sizeof(qache_key_t));
+ copy_out(q, entry, datap, sizep, start);
+ ret = pos;
+ }
+ else
+ DBG("Probe %d: Empty", pos);
+ qache_unlock(q, 0);
+ return ret;
+}
+
uns
qache_delete(struct qache *q, qache_key_t *key, uns pos_hint)
{