int main (void) { assert(QEF_MIN(17, 23) == 17); assert(QEF_MIN(23, 17) == 17); assert(hashbits(0) == 1); assert(hashbits(1) == 1); assert(hashbits(2) == 2); return 0; }
/* * Compute the bucket number for the given IEntry. * Knows that the score is the first thing in the packed * representation. */ static uint32_t iebuck(Index *ix, uint8_t *b, IBucket *ib, IEStream *ies) { USED(ies); USED(ib); return hashbits(b, 32) / ix->div; }
static u64int ie2diskaddr(Index *ix, ISect *is, IEntry *ie) { u64int bucket, addr; bucket = hashbits(ie->score, 32)/ix->div; addr = is->blockbase + ((bucket - is->start) << is->blocklog); return addr; }
static void ihashinsert(IHash *ih, IEntry *ie) { u32int h; h = hashbits(ie->score, ih->bits); ie->nexthash = ih->table[h]; ih->table[h] = ie; }
static IEntry* ihashlookup(IHash *ih, u8int score[VtScoreSize], int type) { u32int h; IEntry *ie; h = hashbits(score, ih->bits); for(ie=ih->table[h]; ie; ie=ie->nexthash) if((type == -1 || type == ie->ia.type) && scorecmp(score, ie->score) == 0) return ie; return nil; }
struct map *findscore(u8int *score) { int ix; ix = hashbits(score, hashb); //fprint(2, "find for %V is %d, maps[].data %p\n", score, ix, maps[ix].data); while (maps[ix].data) { //fprint(2, "Check: %d, %V\n", ix, maps[ix].score); //fprint(2, "scorecmp(%V,%V, %d\n", maps[ix].score, score,scorecmp(maps[ix].score, score) ); if (scorecmp(maps[ix].score, score) == 0) return &maps[ix]; ix++; } return nil; }
static void ihashdelete(IHash *ih, IEntry *ie, char *what) { u32int h; IEntry **l; h = hashbits(ie->score, ih->bits); for(l=&ih->table[h]; *l; l=&(*l)->nexthash) if(*l == ie){ *l = ie->nexthash; return; } fprint(2, "warning: %s %V not found in ihashdelete\n", what, ie->score); }
/* * initial sort: put the entry into the correct bucket */ static int sprayientry(IEBucks *ib, IEntry *ie) { uint32_t n; int b; b = hashbits(ie->score, ib->bits); n = ib->bucks[b].used; if(n + IEntrySize > ib->usable){ /* should be flushed below, but if flush fails, this can happen */ seterr(EOk, "out of space in bucket"); return -1; } packientry(ie, &ib->bucks[b].buf[n]); n += IEntrySize; ib->bucks[b].used = n; if(n + IEntrySize <= ib->usable) return 0; return flushiebuck(ib, b, 1); }
int installentry(u8int *data, ulong len, u8int *score, uchar blocktype) { int ix, initial; datasha1(data, len, score); initial = ix = hashbits(score, hashb); //fprint(2, "installentry: ix %d, V %V, maps[].data %p\n", ix, score, maps[ix].data); while (maps[ix].data) { ix++; if (ix > maxmap) ix = 0; if (ix == initial) sysfatal("OOPS -- no more map slots"); } maps[ix].data = data; //fprint(2, "set map[%d] to %p\n", ix, mmventidata); maps[ix].len = len; scorecp(maps[ix].score, score); maps[ix].blocktype = blocktype; return ix; }
/* * Return a singly-linked list of dirty index entries. * with 32-bit hash numbers between lo and hi * and address < limit. */ IEntry* icachedirty(u32int lo, u32int hi, u64int limit) { u32int h; IEntry *ie, *dirty; dirty = nil; trace(TraceProc, "icachedirty enter"); qlock(&icache.lock); for(ie = icache.dirty.next; ie != &icache.dirty; ie=ie->next){ if(ie->state == IEDirty && ie->ia.addr <= limit){ h = hashbits(ie->score, 32); if(lo <= h && h <= hi){ ie->nextdirty = dirty; dirty = ie; } } } qunlock(&icache.lock); trace(TraceProc, "icachedirty exit"); if(dirty == nil) flushdcache(); return dirty; }