aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/venti/srv/syncindex0.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/syncindex0.c
parent88bb285e3d87ec2508840af33f7e0af53ec3c13c (diff)
downloadplan9port-a0d146edd7a7de6236a0d60baafeeb59f8452aae.tar.gz
plan9port-a0d146edd7a7de6236a0d60baafeeb59f8452aae.tar.bz2
plan9port-a0d146edd7a7de6236a0d60baafeeb59f8452aae.zip
return of venti
Diffstat (limited to 'src/cmd/venti/srv/syncindex0.c')
-rw-r--r--src/cmd/venti/srv/syncindex0.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/src/cmd/venti/srv/syncindex0.c b/src/cmd/venti/srv/syncindex0.c
new file mode 100644
index 00000000..12b69ed2
--- /dev/null
+++ b/src/cmd/venti/srv/syncindex0.c
@@ -0,0 +1,167 @@
+#include "stdinc.h"
+#include "dat.h"
+#include "fns.h"
+
+enum
+{
+ ClumpChunks = 32*1024
+};
+
+static int missing, wrong;
+
+/*
+ * shell sort is plenty good enough
+ * because we're going to do a bunch of disk i/o's
+ */
+static void
+sortclumpinfo(ClumpInfo *ci, int *s, int n)
+{
+ int i, j, m, t;
+
+ for(m = (n + 3) / 5; m > 0; m = (m + 1) / 3){
+ for(i = n - m; i-- > 0;){
+ for(j = i + m; j < n; j += m){
+ if(memcmp(ci[s[j - m]].score, ci[s[j]].score, VtScoreSize) <= 0)
+ break;
+ t = s[j];
+ s[j] = s[j - m];
+ s[j - m] = t;
+ }
+ }
+ }
+}
+
+int
+syncarenaindex(Index *ix, Arena *arena, u32int clump, u64int a, int fix, int *pflush, int check)
+{
+ Packet *pack;
+ IEntry ie;
+ IAddr ia;
+ ClumpInfo *ci, *cis;
+ u64int *addrs;
+ int i, n, ok, *s, flush;
+
+ trace(TraceProc, "syncarenaindex enter");
+
+ flush = 0;
+ cis = MKN(ClumpInfo, ClumpChunks);
+ addrs = MKN(u64int, ClumpChunks);
+ s = MKN(int, ClumpChunks);
+ ok = 0;
+ for(; clump < arena->memstats.clumps; clump += n){
+ n = ClumpChunks;
+ if(n > arena->memstats.clumps - clump)
+ n = arena->memstats.clumps - clump;
+ n = readclumpinfos(arena, clump, cis, n);
+ if(n <= 0){
+ fprint(2, "arena directory read failed\n");
+ ok = -1;
+ break;
+ }
+
+ for(i = 0; i < n; i++){
+ addrs[i] = a;
+ a += cis[i].size + ClumpSize;
+ s[i] = i;
+ }
+
+ sortclumpinfo(cis, s, n);
+
+ for(i = 0; i < n; i++){
+ ci = &cis[s[i]];
+ ia.type = ci->type;
+ ia.size = ci->uncsize;
+ ia.addr = addrs[s[i]];
+ ia.blocks = (ci->size + ClumpSize + (1 << ABlockLog) - 1) >> ABlockLog;
+
+ if(!check)
+ goto Add;
+ if(loadientry(ix, ci->score, ci->type, &ie) < 0){
+ trace(TraceProc, "syncarenaindex missing block %V.%d", ci->score, ci->type);
+ missing++;
+ if(0) fprint(2, "missing block type=%d score=%V\n", ci->type, ci->score);
+ }else if(iaddrcmp(&ia, &ie.ia) != 0){
+ trace(TraceProc, "syncarenaindex mismatched entry");
+ fprint(2, "\nmismatched index entry and clump at %d\n", clump + i);
+ fprint(2, "\tclump: type=%d size=%d blocks=%d addr=%lld\n", ia.type, ia.size, ia.blocks, ia.addr);
+ fprint(2, "\tindex: type=%d size=%d block=%d addr=%lld\n", ie.ia.type, ie.ia.size, ie.ia.blocks, ie.ia.addr);
+ pack = readlump(ie.score, ie.ia.type, ie.ia.size, nil);
+ packetfree(pack);
+ if(pack != nil){
+ fprint(2, "duplicated lump\n");
+ continue;
+ }
+ wrong++;
+ }else
+ continue;
+ Add:
+ if(!fix){
+ ok = -1;
+ continue;
+ }
+ flush = 1;
+ trace(TraceProc, "syncarenaindex insert %V", ci->score);
+ insertscore(ci->score, &ia, 1);
+ }
+
+ if(0 && clump / 1000 != (clump + n) / 1000)
+ fprint(2, ".");
+ }
+ free(cis);
+ free(addrs);
+ free(s);
+ if(flush){
+ flushdcache();
+ *pflush = 1;
+ }
+ return ok;
+}
+
+int
+syncindex(Index *ix, int fix, int mustflush, int check)
+{
+ Arena *arena;
+ u64int a;
+ u32int clump;
+ int i, e, e1, ok, ok1, flush;
+
+ ok = 0;
+ flush = 0;
+ for(i = 0; i < ix->narenas; i++){
+ trace(TraceProc, "syncindex start %d", i);
+ arena = ix->arenas[i];
+ clump = arena->memstats.clumps;
+ a = arena->memstats.used;
+ e = syncarena(arena, ix->amap[i].start, TWID32, fix, fix);
+ e1 = e;
+ if(fix)
+ e1 &= ~(SyncHeader|SyncCIZero|SyncCIErr);
+ if(e1 == SyncHeader)
+ fprint(2, "arena %s: header is out-of-date\n", arena->name);
+ if(e1)
+ ok = -1;
+ else{
+ ok1 = syncarenaindex(ix, arena, clump, a + ix->amap[i].start, fix, &flush, check);
+ if(ok1 < 0)
+ fprint(2, "syncarenaindex: %r\n");
+ if(fix && ok1==0 && (e & SyncHeader) && wbarena(arena) < 0)
+ fprint(2, "arena=%s header write failed: %r\n", arena->name);
+ ok |= ok1;
+ }
+ }
+ if(missing || wrong)
+ fprint(2, "syncindex: %d missing entries, %d wrong entries (flush=%d)\n", missing, wrong, flush);
+ if(fix && wbindex(ix) < 0){
+ fprint(2, "can't write back index header for %s: %r\n", ix->name);
+ return -1;
+ }
+ if(fix && flush){
+ flushdcache();
+ if(mustflush){
+ flushicache();
+ flushdcache();
+ }else
+ kickicache();
+ }
+ return ok;
+}