plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

syncarena.c (4816B)


      1 #include "stdinc.h"
      2 #include "dat.h"
      3 #include "fns.h"
      4 
      5 static int	writeclumphead(Arena *arena, u64int aa, Clump *cl);
      6 static int	writeclumpmagic(Arena *arena, u64int aa, u32int magic);
      7 
      8 int
      9 clumpinfocmp(ClumpInfo *c, ClumpInfo *d)
     10 {
     11 	return c->type != d->type
     12 		|| c->size != d->size
     13 		|| c->uncsize != d->uncsize
     14 		|| scorecmp(c->score, d->score)!=0;
     15 }
     16 
     17 /*
     18  * synchronize the clump info directory with
     19  * with the clumps actually stored in the arena.
     20  * the directory should be at least as up to date
     21  * as the arena's trailer.
     22  *
     23  * checks/updates at most n clumps.
     24  *
     25  * returns 0 if ok, flags if error occurred
     26  */
     27 int
     28 syncarena(Arena *arena, u32int n, int zok, int fix)
     29 {
     30 	ZBlock *lump;
     31 	Clump cl;
     32 	ClumpInfo ci;
     33 	static ClumpInfo zci = { .type = -1 };
     34 	u8int score[VtScoreSize];
     35 	u64int uncsize, used, aa;
     36 	u32int clump, clumps, cclumps, magic;
     37 	int err, flush, broken;
     38 
     39 	used = arena->memstats.used;
     40 	clumps = arena->memstats.clumps;
     41 	cclumps = arena->memstats.cclumps;
     42 	uncsize = arena->memstats.uncsize;
     43 	trace(TraceProc, "syncarena start");
     44 	flush = 0;
     45 	err = 0;
     46 	for(; n; n--){
     47 		aa = arena->memstats.used;
     48 		clump = arena->memstats.clumps;
     49 		magic = clumpmagic(arena, aa);
     50 		if(magic == ClumpFreeMagic)
     51 			break;
     52 		if(magic != arena->clumpmagic){
     53 			fprint(2, "%s: illegal clump magic number=%#8.8ux at clump=%d\n", arena->name, magic, clump);
     54 			/* err |= SyncDataErr; */
     55 			if(fix && writeclumpmagic(arena, aa, ClumpFreeMagic) < 0){
     56 				fprint(2, "%s: can't write corrected clump free magic: %r", arena->name);
     57 				err |= SyncFixErr;
     58 			}
     59 			break;
     60 		}
     61 
     62 		broken = 0;
     63 		lump = loadclump(arena, aa, 0, &cl, score, 0);
     64 		if(lump == nil){
     65 			fprint(2, "%s: clump=%d failed to read correctly: %r\n", arena->name, clump);
     66 			break;
     67 		}else if(cl.info.type != VtCorruptType){
     68 			scoremem(score, lump->data, cl.info.uncsize);
     69 			if(scorecmp(cl.info.score, score) != 0){
     70 				/* ignore partially written block */
     71 				if(cl.encoding == ClumpENone)
     72 					break;
     73 				fprint(2, "%s: clump=%d has mismatched score\n", arena->name, clump);
     74 				err |= SyncDataErr;
     75 				broken = 1;
     76 			}else if(vttypevalid(cl.info.type) < 0){
     77 				fprint(2, "%s: clump=%d has invalid type %d", arena->name, clump, cl.info.type);
     78 				err |= SyncDataErr;
     79 				broken = 1;
     80 			}
     81 			if(broken && fix){
     82 				cl.info.type = VtCorruptType;
     83 				if(writeclumphead(arena, aa, &cl) < 0){
     84 					fprint(2, "%s: can't write corrected clump header: %r", arena->name);
     85 					err |= SyncFixErr;
     86 				}
     87 			}
     88 		}
     89 		freezblock(lump);
     90 		arena->memstats.used += ClumpSize + cl.info.size;
     91 
     92 		arena->memstats.clumps++;
     93 		if(!broken && readclumpinfo(arena, clump, &ci)<0){
     94 			fprint(2, "%s: arena directory read failed\n", arena->name);
     95 			broken = 1;
     96 		}else if(!broken && clumpinfocmp(&ci, &cl.info)!=0){
     97 			if(clumpinfocmp(&ci, &zci) == 0){
     98 				err |= SyncCIZero;
     99 				if(!zok)
    100 					fprint(2, "%s: unwritten clump info for clump=%d\n", arena->name, clump);
    101 			}else{
    102 				err |= SyncCIErr;
    103 				fprint(2, "%s: bad clump info for clump=%d\n", arena->name, clump);
    104 				fprint(2, "\texpected score=%V type=%d size=%d uncsize=%d\n",
    105 					cl.info.score, cl.info.type, cl.info.size, cl.info.uncsize);
    106 				fprint(2, "\tfound score=%V type=%d size=%d uncsize=%d\n",
    107 					ci.score, ci.type, ci.size, ci.uncsize);
    108 			}
    109 			broken = 1;
    110 		}
    111 		if(broken && fix){
    112 			flush = 1;
    113 			ci = cl.info;
    114 			if(writeclumpinfo(arena, clump, &ci) < 0){
    115 				fprint(2, "%s: can't write correct clump directory: %r\n", arena->name);
    116 				err |= SyncFixErr;
    117 			}
    118 		}
    119 		trace(TraceProc, "syncarena unindexed clump %V %d", cl.info.score, arena->memstats.clumps);
    120 
    121 		arena->memstats.uncsize += cl.info.uncsize;
    122 		if(cl.info.size < cl.info.uncsize)
    123 			arena->memstats.cclumps++;
    124 	}
    125 
    126 	if(flush){
    127 		trace(TraceProc, "syncarena flush");
    128 		arena->wtime = now();
    129 		if(arena->ctime == 0 && arena->memstats.clumps)
    130 			arena->ctime = arena->wtime;
    131 		flushdcache();
    132 	}
    133 
    134 	if(used != arena->memstats.used
    135 	|| clumps != arena->memstats.clumps
    136 	|| cclumps != arena->memstats.cclumps
    137 	|| uncsize != arena->memstats.uncsize){
    138 		err |= SyncHeader;
    139 		fprint(2, "arena %s: fix=%d flush=%d %lld->%lld %ud->%ud %ud->%ud %lld->%lld\n",
    140 			arena->name,
    141 			fix,
    142 			flush,
    143 			used, arena->memstats.used,
    144 			clumps, arena->memstats.clumps,
    145 			cclumps, arena->memstats.cclumps,
    146 			uncsize, arena->memstats.uncsize);
    147 	}
    148 
    149 	return err;
    150 }
    151 
    152 static int
    153 writeclumphead(Arena *arena, u64int aa, Clump *cl)
    154 {
    155 	ZBlock *zb;
    156 	int bad;
    157 
    158 	zb = alloczblock(ClumpSize, 0, arena->blocksize);
    159 	if(zb == nil)
    160 		return -1;
    161 	bad = packclump(cl, zb->data, arena->clumpmagic)<0
    162 		|| writearena(arena, aa, zb->data, ClumpSize) != ClumpSize;
    163 	freezblock(zb);
    164 	return bad ? -1 : 0;
    165 }
    166 
    167 static int
    168 writeclumpmagic(Arena *arena, u64int aa, u32int magic)
    169 {
    170 	u8int buf[U32Size];
    171 
    172 	packmagic(magic, buf);
    173 	return writearena(arena, aa, buf, U32Size) == U32Size;
    174 }