aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/venti/srv/buildbuck.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2005-07-12 15:23:36 +0000
committerrsc <devnull@localhost>2005-07-12 15:23:36 +0000
commita0d146edd7a7de6236a0d60baafeeb59f8452aae (patch)
treeb55baa526d9f5adfc73246e6ee2fadf455e0b7a2 /src/cmd/venti/srv/buildbuck.c
parent88bb285e3d87ec2508840af33f7e0af53ec3c13c (diff)
downloadplan9port-a0d146edd7a7de6236a0d60baafeeb59f8452aae.tar.gz
plan9port-a0d146edd7a7de6236a0d60baafeeb59f8452aae.tar.bz2
plan9port-a0d146edd7a7de6236a0d60baafeeb59f8452aae.zip
return of venti
Diffstat (limited to 'src/cmd/venti/srv/buildbuck.c')
-rw-r--r--src/cmd/venti/srv/buildbuck.c132
1 files changed, 132 insertions, 0 deletions
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;
+}