#include "stdinc.h" #include "dat.h" #include "fns.h" enum { ClumpChunks = 32*1024 }; /* * 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) { Packet *pack; IEntry ie; IAddr ia; ClumpInfo *ci, *cis; u32int now; u64int *addrs; int i, n, ok, *s; now = time(nil); cis = MKN(ClumpInfo, ClumpChunks); addrs = MKN(u64int, ClumpChunks); s = MKN(int, ClumpChunks); ok = 0; for(; clump < arena->clumps; clump += n){ n = ClumpChunks; if(n > arena->clumps - clump) n = arena->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(loadientry(ix, ci->score, ci->type, &ie) < 0) fprint(2, "missing block type=%d score=%V\n", ci->type, ci->score); else if(iaddrcmp(&ia, &ie.ia) != 0){ 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); packetfree(pack); if(pack != nil){ fprint(2, "duplicated lump\n"); continue; } }else continue; if(!fix){ ok = -1; continue; } ie.ia = ia; scorecp(ie.score, ci->score); ie.train = 0; ie.wtime = now; if(storeientry(ix, &ie) < 0){ fprint(2, "can't fix index: %r"); ok = -1; } } if(0 && clump / 1000 != (clump + n) / 1000) fprint(2, "."); } free(cis); free(addrs); free(s); return ok; } int syncindex(Index *ix, int fix) { Arena *arena; u64int a; u32int clump; int i, e, e1, ok, ok1; ok = 0; for(i = 0; i < ix->narenas; i++){ arena = ix->arenas[i]; clump = arena->clumps; a = arena->used; e = syncarena(arena, TWID32, fix, fix); e1 = e; if(fix) e1 &= ~(SyncHeader|SyncCIZero); 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); if(fix && ok1==0 && (e & SyncHeader) && wbarena(arena) < 0) fprint(2, "arena=%s header write failed: %r\n", arena->name); ok |= ok1; } } if(fix && wbindex(ix) < 0){ fprint(2, "can't write back index header for %s: %r\n", ix->name); return -1; } return ok; }