diff options
author | rsc <devnull@localhost> | 2005-07-12 15:23:36 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2005-07-12 15:23:36 +0000 |
commit | a0d146edd7a7de6236a0d60baafeeb59f8452aae (patch) | |
tree | b55baa526d9f5adfc73246e6ee2fadf455e0b7a2 /src/cmd/venti/srv/syncarena.c | |
parent | 88bb285e3d87ec2508840af33f7e0af53ec3c13c (diff) | |
download | plan9port-a0d146edd7a7de6236a0d60baafeeb59f8452aae.tar.gz plan9port-a0d146edd7a7de6236a0d60baafeeb59f8452aae.tar.bz2 plan9port-a0d146edd7a7de6236a0d60baafeeb59f8452aae.zip |
return of venti
Diffstat (limited to 'src/cmd/venti/srv/syncarena.c')
-rw-r--r-- | src/cmd/venti/srv/syncarena.c | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/src/cmd/venti/srv/syncarena.c b/src/cmd/venti/srv/syncarena.c new file mode 100644 index 00000000..d11ca4f3 --- /dev/null +++ b/src/cmd/venti/srv/syncarena.c @@ -0,0 +1,174 @@ +#include "stdinc.h" +#include "dat.h" +#include "fns.h" + +static int writeclumphead(Arena *arena, u64int aa, Clump *cl); +static int writeclumpmagic(Arena *arena, u64int aa, u32int magic); + +int +clumpinfocmp(ClumpInfo *c, ClumpInfo *d) +{ + return c->type != d->type + || c->size != d->size + || c->uncsize != d->uncsize + || scorecmp(c->score, d->score)!=0; +} + +/* + * synchronize the clump info directory with + * with the clumps actually stored in the arena. + * the directory should be at least as up to date + * as the arena's trailer. + * + * checks/updates at most n clumps. + * + * returns 0 if ok, flags if error occurred + */ +int +syncarena(Arena *arena, u64int start, u32int n, int zok, int fix) +{ + ZBlock *lump; + Clump cl; + ClumpInfo ci; + static ClumpInfo zci = { .type = -1 }; + u8int score[VtScoreSize]; + u64int uncsize, used, aa; + u32int clump, clumps, cclumps, magic; + int err, flush, broken; + AState as; + + used = arena->memstats.used; + clumps = arena->memstats.clumps; + cclumps = arena->memstats.cclumps; + uncsize = arena->memstats.uncsize; + trace(TraceProc, "syncarena start"); + flush = 0; + err = 0; + for(; n; n--){ + aa = arena->memstats.used; + clump = arena->memstats.clumps; + magic = clumpmagic(arena, aa); + if(magic == ClumpFreeMagic) + break; + if(magic != arena->clumpmagic){ + fprint(2, "%s: illegal clump magic number=%#8.8ux at clump=%d\n", arena->name, magic, clump); + /* err |= SyncDataErr; */ + if(fix && writeclumpmagic(arena, aa, ClumpFreeMagic) < 0){ + fprint(2, "can't write corrected clump free magic: %r"); + err |= SyncFixErr; + } + break; + } + + broken = 0; + lump = loadclump(arena, aa, 0, &cl, score, 0); + if(lump == nil){ + fprint(2, "%s: clump=%d failed to read correctly: %r\n", arena->name, clump); + break; + err |= SyncDataErr; + }else if(cl.info.type != VtCorruptType){ + scoremem(score, lump->data, cl.info.uncsize); + if(scorecmp(cl.info.score, score) != 0){ + /* ignore partially written block */ + if(cl.encoding == ClumpENone) + break; + fprint(2, "%s: clump=%d has mismatched score\n", arena->name, clump); + err |= SyncDataErr; + broken = 1; + }else if(vttypevalid(cl.info.type) < 0){ + fprint(2, "%s: clump=%d has invalid type %d", arena->name, clump, cl.info.type); + err |= SyncDataErr; + broken = 1; + } + if(broken && fix){ + cl.info.type = VtCorruptType; + if(writeclumphead(arena, aa, &cl) < 0){ + fprint(2, "%s: can't write corrected clump header: %r", arena->name); + err |= SyncFixErr; + } + } + } + freezblock(lump); + arena->memstats.used += ClumpSize + cl.info.size; + + arena->memstats.clumps++; + if(!broken && readclumpinfo(arena, clump, &ci)<0){ + fprint(2, "%s: arena directory read failed\n", arena->name); + broken = 1; + }else if(!broken && clumpinfocmp(&ci, &cl.info)!=0){ + if(clumpinfocmp(&ci, &zci) == 0){ + err |= SyncCIZero; + if(!zok) + fprint(2, "%s: unwritten clump info for clump=%d\n", arena->name, clump); + }else{ + err |= SyncCIErr; + fprint(2, "%s: bad clump info for clump=%d\n", arena->name, clump); + fprint(2, "\texpected score=%V type=%d size=%d uncsize=%d\n", + cl.info.score, cl.info.type, cl.info.size, cl.info.uncsize); + fprint(2, "\tfound score=%V type=%d size=%d uncsize=%d\n", + ci.score, ci.type, ci.size, ci.uncsize); + } + broken = 1; + } + if(broken && fix){ + flush = 1; + ci = cl.info; + if(writeclumpinfo(arena, clump, &ci) < 0){ + fprint(2, "%s: can't write correct clump directory: %r\n", arena->name); + err |= SyncFixErr; + } + } + trace(TraceProc, "syncarena unindexed clump %V %d", cl.info.score, arena->memstats.clumps); + + arena->memstats.uncsize += cl.info.uncsize; + if(cl.info.size < cl.info.uncsize) + arena->memstats.cclumps++; + } + + if(flush){ + trace(TraceProc, "syncarena flush"); + arena->wtime = now(); + if(arena->ctime == 0 && arena->memstats.clumps) + arena->ctime = arena->wtime; + flushdcache(); + } + + if(used != arena->memstats.used + || clumps != arena->memstats.clumps + || cclumps != arena->memstats.cclumps + || uncsize != arena->memstats.uncsize) + err |= SyncHeader; + if(start && (err&SyncHeader)){ + trace(TraceProc, "syncarena setdcachestate"); + as.arena = arena; + as.aa = start+arena->memstats.used; + as.stats = arena->memstats; + setdcachestate(&as); + } + + return err; +} + +static int +writeclumphead(Arena *arena, u64int aa, Clump *cl) +{ + ZBlock *zb; + int bad; + + zb = alloczblock(ClumpSize, 0, arena->blocksize); + if(zb == nil) + return -1; + bad = packclump(cl, zb->data, arena->clumpmagic)<0 + || writearena(arena, aa, zb->data, ClumpSize) != ClumpSize; + freezblock(zb); + return bad ? -1 : 0; +} + +static int +writeclumpmagic(Arena *arena, u64int aa, u32int magic) +{ + u8int buf[U32Size]; + + packmagic(magic, buf); + return writearena(arena, aa, buf, U32Size) == U32Size; +} |