CacheDigest * cacheDigestClone(const CacheDigest * cd) { CacheDigest *clone; assert(cd); clone = cacheDigestCreate(cd->capacity, cd->bits_per_entry); clone->count = cd->count; clone->del_count = cd->del_count; assert(cd->mask_size == clone->mask_size); xmemcpy(clone->mask, cd->mask, cd->mask_size); return clone; }
void storeDigestInit(void) { #if USE_CACHE_DIGESTS const int cap = storeDigestCalcCap(); if (!Config.onoff.digest_generation) { store_digest = NULL; debug(71, 3) ("Local cache digest generation disabled\n"); return; } store_digest = cacheDigestCreate(cap, Config.digest.bits_per_entry); debug(71, 1) ("Local cache digest enabled; rebuild/rewrite every %d/%d sec\n", (int) Config.digest.rebuild_period, (int) Config.digest.rewrite_period); memset(&sd_state, 0, sizeof(sd_state)); cachemgrRegister("store_digest", "Store Digest", storeDigestReport, 0, 1); #else store_digest = NULL; debug(71, 3) ("Local cache digest is 'off'\n"); #endif }
/* re-digests currently hashed entries */ static void cacheResetDigest(Cache * cache) { CacheEntry *e = NULL; hash_table *hash; struct timeval t_start, t_end; assert(cache); fprintf(stderr, "%s: init-ing digest with %d entries\n", cache->name, cache->count); if (cache->digest) cacheDigestDestroy(cache->digest); hash = cache->hash; cache->digest = cacheDigestCreate(cache->count + 1, 6); if (!cache->count) return; gettimeofday(&t_start, NULL); hash_first(hash); while (e = hash_next(hash)) { cacheDigestAdd(cache->digest, e->key); } gettimeofday(&t_end, NULL); assert(cache->digest->count == cache->count); fprintf(stderr, "%s: init-ed digest with %d entries\n", cache->name, cache->digest->count); fprintf(stderr, "%s: init took: %f sec, %f sec/M\n", cache->name, tvSubDsec(t_start, t_end), (double) 1e6 * tvSubDsec(t_start, t_end) / cache->count); /* check how long it takes to traverse the hash */ gettimeofday(&t_start, NULL); for (e = hash_first(hash); e; e = hash_next(hash)) { } gettimeofday(&t_end, NULL); fprintf(stderr, "%s: hash scan took: %f sec, %f sec/M\n", cache->name, tvSubDsec(t_start, t_end), (double) 1e6 * tvSubDsec(t_start, t_end) / cache->count); }
static int peerDigestSetCBlock(PeerDigest * pd, const char *buf) { StoreDigestCBlock cblock; int freed_size = 0; const char *host = strBuf(pd->host); xmemcpy(&cblock, buf, sizeof(cblock)); /* network -> host conversions */ cblock.ver.current = ntohs(cblock.ver.current); cblock.ver.required = ntohs(cblock.ver.required); cblock.capacity = ntohl(cblock.capacity); cblock.count = ntohl(cblock.count); cblock.del_count = ntohl(cblock.del_count); cblock.mask_size = ntohl(cblock.mask_size); debug(72, 2) ("got digest cblock from %s; ver: %d (req: %d)\n", host, (int) cblock.ver.current, (int) cblock.ver.required); debug(72, 2) ("\t size: %d bytes, e-cnt: %d, e-util: %d%%\n", cblock.mask_size, cblock.count, xpercentInt(cblock.count, cblock.capacity)); /* check version requirements (both ways) */ if (cblock.ver.required > CacheDigestVer.current) { debug(72, 1) ("%s digest requires version %d; have: %d\n", host, cblock.ver.required, CacheDigestVer.current); return 0; } if (cblock.ver.current < CacheDigestVer.required) { debug(72, 1) ("%s digest is version %d; we require: %d\n", host, cblock.ver.current, CacheDigestVer.required); return 0; } /* check consistency */ if (cblock.ver.required > cblock.ver.current || cblock.mask_size <= 0 || cblock.capacity <= 0 || cblock.bits_per_entry <= 0 || cblock.hash_func_count <= 0) { debug(72, 0) ("%s digest cblock is corrupted.\n", host); return 0; } /* check consistency further */ if (cblock.mask_size != cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry)) { debug(72, 0) ("%s digest cblock is corrupted (mask size mismatch: %d ? %d).\n", host, cblock.mask_size, cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry)); return 0; } /* there are some things we cannot do yet */ if (cblock.hash_func_count != CacheDigestHashFuncCount) { debug(72, 0) ("%s digest: unsupported #hash functions: %d ? %d.\n", host, cblock.hash_func_count, CacheDigestHashFuncCount); return 0; } /* * no cblock bugs below this point */ /* check size changes */ if (pd->cd && cblock.mask_size != pd->cd->mask_size) { debug(72, 2) ("%s digest changed size: %d -> %d\n", host, cblock.mask_size, pd->cd->mask_size); freed_size = pd->cd->mask_size; cacheDigestDestroy(pd->cd); pd->cd = NULL; } if (!pd->cd) { debug(72, 2) ("creating %s digest; size: %d (%+d) bytes\n", host, cblock.mask_size, (int) (cblock.mask_size - freed_size)); pd->cd = cacheDigestCreate(cblock.capacity, cblock.bits_per_entry); if (cblock.mask_size >= freed_size) kb_incr(&Counter.cd.memory, cblock.mask_size - freed_size); } assert(pd->cd); /* these assignments leave us in an inconsistent state until we finish reading the digest */ pd->cd->count = cblock.count; pd->cd->del_count = cblock.del_count; return 1; }