struct ICache
{
VtLock *lock; /* locks hash table & all associated data */
IEntry **heads; /* heads of all the hash chains */
int bits; /* bits to use for indexing heads */
u32int size; /* number of heads; == 1 << bits, should be < entries */
IEntry *base; /* all allocated hash table entries */
u32int entries; /* elements in base */
u32int unused; /* index of first unused element in base */
u32int stolen; /* last head from which an element was stolen */
};
/*
ZZZ need to think about evicting the correct IEntry,
and writing back the wtime.
* look up data score in the index cache
* if this fails, pull it in from the disk index table, if it exists.
*
* must be called with the lump for this score locked
*/
int
lookupScore(u8int *score, int type, IAddr *ia)
{
IEntry d, *ie, *last;
u32int h;
/*
* no one else can load an entry for this score,
* since we have the overall score lock.
*/
vtLock(stats.lock);
stats.icFills++;
vtUnlock(stats.lock);
vtLock(icache.lock);
h = hashBits(score, icache.bits);
ie = icacheAlloc(ia->type, score);
scoreCp(ie->score, score);
ie->ia = *ia;
ie->next = icache.heads[h];
icache.heads[h] = ie;
se = *ie;
vtUnlock(icache.lock);
return storeIEntry(mainIndex, &se);
}
/*
* allocate a index cache entry which hasn't been used in a while.
* must be called with icache.lock locked
* if the score is already in the table, update the entry.
*/
static IEntry *
icacheAlloc(int type, u8int *score)
{
IEntry *ie, *last, *next;
u32int h;
h = hashBits(score, icache.bits);
last = nil;
for(ie = icache.heads[h]; ie != nil; ie = ie->next){
if(ie->ia.type == type && scoreEq(ie->score, score)){
if(last != nil)
last->next = ie->next;
else
icache.heads[h] = ie->next;
return ie;
}
last = ie;
}