X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Fqache.c;h=3c4be273ab1c1bd0b24d100cc4439781da75a61c;hb=9c5d20f9afd457a9d16e681475c6ea59c33de2d0;hp=e965e47721a10b9ca55681c9980c15e6d4a6e193;hpb=ff935b2de2eee5512798b44f0cb52e3e72398d68;p=libucw.git diff --git a/lib/qache.c b/lib/qache.c index e965e477..3c4be273 100644 --- a/lib/qache.c +++ b/lib/qache.c @@ -7,12 +7,13 @@ #undef LOCAL_DEBUG #include "lib/lib.h" +#include "lib/bitops.h" #include "lib/fastbuf.h" #include "lib/qache.h" -#include #include #include +#include #include #include @@ -82,7 +83,7 @@ qache_msync(struct qache *q UNUSED, uns start UNUSED, uns len UNUSED) /* We don't need msyncing on Linux, since the mappings are guaranteed to be coherent */ len += (start % PAGE_SIZE); start -= start % PAGE_SIZE; - len = ALIGN(len, PAGE_SIZE); + len = ALIGN_TO(len, PAGE_SIZE); if (msync(q->mmap_data + start, len, MS_ASYNC | MS_INVALIDATE) < 0) log(L_ERROR, "Cache %s: msync failed: %m", q->file_name); #endif @@ -313,7 +314,7 @@ qache_create(struct qache *q, struct qache_params *par) 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); @@ -371,7 +372,7 @@ qache_create(struct qache *q, struct qache_params *par) 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); } @@ -383,12 +384,12 @@ qache_open(struct qache_params *par) q->file_name = xstrdup(par->file_name); ASSERT(par->block_size >= 8 && !(par->block_size & (par->block_size-1))); - par->cache_size = ALIGN(par->cache_size, par->block_size); + par->cache_size = ALIGN_TO(par->cache_size, par->block_size); 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; @@ -417,7 +418,7 @@ qache_hash_find(struct qache *q, qache_key_t *key, uns pos_hint) { 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); @@ -598,6 +599,41 @@ qache_insert(struct qache *q, qache_key_t *key, uns pos_hint, void *data, uns si 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) { @@ -609,36 +645,7 @@ qache_lookup(struct qache *q, qache_key_t *key, uns pos_hint, byte **datap, uns 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 @@ -649,6 +656,32 @@ qache_lookup(struct qache *q, qache_key_t *key, uns pos_hint, byte **datap, uns 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) {