mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-15 11:20:03 +00:00
167 lines
3.8 KiB
C
167 lines
3.8 KiB
C
#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;
|
|
}
|