/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#include "base/polygraph.h"
#include "xstd/gadgets.h"
#include "base/ObjId.h"
#include "client/PrivCache.h"
PrivCache::PrivCache(int aCapacity): theEntryCount(0), theHitCount(0), theMissCount(0) {
if (aCapacity > 0)
capacity(aCapacity);
}
void PrivCache::clear() {
theHistory.reset();
theHash.memset(0);
theEntryCount = 0;
// theHitCount = theMissCount = 0; // need to handle stats differently
}
bool PrivCache::loadOid(const ObjId &oid) {
const int idx = index(hash(oid));
const Entry &e = theHash[idx];
if (e.key == oid.hash()) {
if (oid.basic()) {
++theHitCount;
return true;
}
--theEntryCount;
delAt(idx); // purge stale or because request demands it
}
theMissCount++;
return false;
}
bool PrivCache::storeOid(const ObjId &oid) {
// XXX: implement
addOid(oid);
return true;
}
bool PrivCache::purgeOid(const ObjId &oid) {
const int idx = index(hash(oid));
const Entry &e = theHash[idx];
if (e.key == oid.hash()) {
--theEntryCount;
delAt(idx);
return true;
}
return false;
}
void PrivCache::capacity(int aCap) {
Assert(aCap >= 0);
Assert(!theHash.count());
theHistory.resize(aCap);
// would be nice to find the closest prime
aCap = 3*aCap | 1;
Assert(aCap <= 0xFFFF); // we use short int as an index
theHash.stretch(aCap);
theHash.count(theHash.capacity());
}
int PrivCache::hash(const ObjId &oid) const {
return oid.hash();
}
int PrivCache::index(int key) const {
return key % theHash.capacity();
}
bool PrivCache::hasOid(const ObjId &oid) const {
return theHash[index(hash(oid))].key == oid.hash();
}
void PrivCache::addOid(const ObjId &oid) {
Assert(oid.name() > 0 || oid.foreignUrl());
while (theEntryCount > theHistory.capacity())
purgeOne();
// the entry count may not reflect history size: collisions are not purged
if (theHistory.full())
purgeOne();
const int idx = index(hash(oid));
Entry &e = theHash[idx];
if (e) // collision simply overwrites an older entry w/o history update
--theEntryCount;
e.key = oid.hash();
theHistory.enqueue((HistoryItem)e.key);
++theEntryCount;
}
void PrivCache::delAt(int idx) {
theHash[idx].key = -1;
}
void PrivCache::purgeOne() {
const int key = theHistory.dequeue();
const int idx = index(key);
if (theHash[idx].key == key) // else we decremented the count on collision
--theEntryCount;
delAt(idx);
}
syntax highlighted by Code2HTML, v. 0.9.1