plan9port/src/cmd/venti/syncindex0.c
2003-11-23 17:54:58 +00:00

144 lines
3.1 KiB
C

#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;
}