From a0d146edd7a7de6236a0d60baafeeb59f8452aae Mon Sep 17 00:00:00 2001 From: rsc Date: Tue, 12 Jul 2005 15:23:36 +0000 Subject: return of venti --- src/cmd/venti/srv/buildbuck.c | 132 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/cmd/venti/srv/buildbuck.c (limited to 'src/cmd/venti/srv/buildbuck.c') diff --git a/src/cmd/venti/srv/buildbuck.c b/src/cmd/venti/srv/buildbuck.c new file mode 100644 index 00000000..240e77d7 --- /dev/null +++ b/src/cmd/venti/srv/buildbuck.c @@ -0,0 +1,132 @@ +#include "stdinc.h" +#include "dat.h" +#include "fns.h" + +/* + * An IEStream is a sorted list of index entries. + */ +struct IEStream +{ + Part *part; + u64int off; /* read position within part */ + u64int n; /* number of valid ientries left to read */ + u32int size; /* allocated space in buffer */ + u8int *buf; + u8int *pos; /* current place in buffer */ + u8int *epos; /* end of valid buffer contents */ +}; + +IEStream* +initiestream(Part *part, u64int off, u64int clumps, u32int size) +{ + IEStream *ies; + +//ZZZ out of memory? + ies = MKZ(IEStream); + ies->buf = MKN(u8int, size); + ies->epos = ies->buf; + ies->pos = ies->epos; + ies->off = off; + ies->n = clumps; + ies->size = size; + ies->part = part; + return ies; +} + +void +freeiestream(IEStream *ies) +{ + if(ies == nil) + return; + free(ies->buf); + free(ies); +} + +/* + * Return the next IEntry (still packed) in the stream. + */ +static u8int* +peekientry(IEStream *ies) +{ + u32int n, nn; + + n = ies->epos - ies->pos; + if(n < IEntrySize){ + memmove(ies->buf, ies->pos, n); + ies->epos = &ies->buf[n]; + ies->pos = ies->buf; + nn = ies->size; + if(nn > ies->n * IEntrySize) + nn = ies->n * IEntrySize; + nn -= n; + if(nn == 0) + return nil; +//fprint(2, "peek %d from %llud into %p\n", nn, ies->off, ies->epos); + if(readpart(ies->part, ies->off, ies->epos, nn) < 0){ + seterr(EOk, "can't read sorted index entries: %r"); + return nil; + } + ies->epos += nn; + ies->off += nn; + } + return ies->pos; +} + +/* + * Compute the bucket number for the given IEntry. + * Knows that the score is the first thing in the packed + * representation. + */ +static u32int +iebuck(Index *ix, u8int *b, IBucket *ib, IEStream *ies) +{ + USED(ies); + USED(ib); + return hashbits(b, 32) / ix->div; +} + +/* + * Fill ib with the next bucket in the stream. + */ +u32int +buildbucket(Index *ix, IEStream *ies, IBucket *ib, uint maxdata) +{ + IEntry ie1, ie2; + u8int *b; + u32int buck; + + buck = TWID32; + ib->n = 0; + while(ies->n){ + b = peekientry(ies); + if(b == nil) + return TWID32; +//fprint(2, "b=%p ies->n=%lld ib.n=%d buck=%d score=%V\n", b, ies->n, ib->n, iebuck(ix, b, ib, ies), b); + if(ib->n == 0) + buck = iebuck(ix, b, ib, ies); + else{ + if(buck != iebuck(ix, b, ib, ies)) + break; + if(ientrycmp(&ib->data[(ib->n - 1)* IEntrySize], b) == 0){ + /* + * guess that the larger address is the correct one to use + */ + unpackientry(&ie1, &ib->data[(ib->n - 1)* IEntrySize]); + unpackientry(&ie2, b); + seterr(EOk, "duplicate index entry for score=%V type=%d", ie1.score, ie1.ia.type); + ib->n--; + if(ie1.ia.addr > ie2.ia.addr) + memmove(b, &ib->data[ib->n * IEntrySize], IEntrySize); + } + } + if((ib->n+1)*IEntrySize > maxdata){ + seterr(EOk, "bucket overflow"); + return TWID32; + } + memmove(&ib->data[ib->n * IEntrySize], b, IEntrySize); + ib->n++; + ies->n--; + ies->pos += IEntrySize; + } + return buck; +} -- cgit v1.2.3