plan9port

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

cmparenas.c (7209B)


      1 #include "stdinc.h"
      2 #include "dat.h"
      3 #include "fns.h"
      4 
      5 static int	verbose;
      6 static int	fd;
      7 static int	fd1;
      8 static uchar	*data;
      9 static uchar	*data1;
     10 static int	blocksize;
     11 static int	sleepms;
     12 
     13 void
     14 usage(void)
     15 {
     16 	fprint(2, "usage: cmparenas [-b blocksize] [-s ms] [-v] arenapart1 arenapart2 [name...]]\n");
     17 	threadexitsall(0);
     18 }
     19 
     20 static int
     21 preadblock(int fd, uchar *buf, int n, vlong off)
     22 {
     23 	int nr, m;
     24 
     25 	for(nr = 0; nr < n; nr += m){
     26 		m = n - nr;
     27 		m = pread(fd, &buf[nr], m, off+nr);
     28 		if(m <= 0){
     29 			if(m == 0)
     30 				werrstr("early eof");
     31 			return -1;
     32 		}
     33 	}
     34 	return 0;
     35 }
     36 
     37 static int
     38 readblock(int fd, uchar *buf, int n)
     39 {
     40 	int nr, m;
     41 
     42 	for(nr = 0; nr < n; nr += m){
     43 		m = n - nr;
     44 		m = read(fd, &buf[nr], m);
     45 		if(m <= 0){
     46 			if(m == 0)
     47 				werrstr("early eof");
     48 			return -1;
     49 		}
     50 	}
     51 	return 0;
     52 }
     53 
     54 static int
     55 printheader(char *name, ArenaHead *head, int fd)
     56 {
     57 	Arena arena;
     58 	vlong baseoff, lo, hi, off;
     59 	int clumpmax;
     60 
     61 	off = seek(fd, 0, 1);
     62 	seek(fd, off + head->size - head->blocksize, 0);
     63 	if(readblock(fd, data, head->blocksize) < 0){
     64 		fprint(2, "%s: reading arena tail: %r\n", name);
     65 		return -1;
     66 	}
     67 	seek(fd, off, 0);
     68 
     69 	memset(&arena, 0, sizeof arena);
     70 	if(unpackarena(&arena, data) < 0){
     71 		fprint(2, "%s: unpack arena tail: %r\n", name);
     72 		return -1;
     73 	}
     74 	arena.blocksize = head->blocksize;
     75 	arena.base = off + head->blocksize;
     76 	arena.clumpmax = arena.blocksize / ClumpInfoSize;
     77 	arena.size = head->size - 2*head->blocksize;
     78 
     79 	fprint(2, "%s: base=%llx size=%llx blocksize=%x\n", name, off, head->size, head->blocksize);
     80 
     81 	baseoff = head->blocksize;
     82 	fprint(2, "\t%llx-%llx: head\n", (vlong)0, baseoff);
     83 	lo = baseoff;
     84 	hi = baseoff + arena.diskstats.used;
     85 	fprint(2, "\t%llx-%llx: data (%llx)\n", lo, hi, hi - lo);
     86 	hi = head->size - head->blocksize;
     87 	clumpmax = head->blocksize / ClumpInfoSize;
     88 	if(clumpmax > 0)
     89 		lo = hi - (u64int)arena.diskstats.clumps/clumpmax * head->blocksize;
     90 	else
     91 		lo = hi;
     92 	fprint(2, "\t%llx-%llx: clumps (%llx)\n", lo, hi, hi - lo);
     93 	fprint(2, "\t%llx-%llx: tail\n", hi, hi + head->blocksize);
     94 
     95 	fprint(2, "arena:\n");
     96 	printarena(2, &arena);
     97 	return 0;
     98 }
     99 
    100 static void
    101 cmparena(char *name, vlong len)
    102 {
    103 	ArenaHead head;
    104 	DigestState s;
    105 	u64int n, e;
    106 	u32int bs;
    107 	int i, j;
    108 	char buf[20];
    109 
    110 	fprint(2, "cmp %s\n", name);
    111 
    112 	memset(&s, 0, sizeof s);
    113 
    114 	/*
    115 	 * read a little bit, which will include the header
    116 	 */
    117 	if(readblock(fd, data, HeadSize) < 0){
    118 		fprint(2, "%s: reading header: %r\n", name);
    119 		return;
    120 	}
    121 	if(unpackarenahead(&head, data) < 0){
    122 		fprint(2, "%s: corrupt arena header: %r\n", name);
    123 		return;
    124 	}
    125 	if(head.version != ArenaVersion4 && head.version != ArenaVersion5)
    126 		fprint(2, "%s: warning: unknown arena version %d\n", name, head.version);
    127 	if(len != 0 && len != head.size)
    128 		fprint(2, "%s: warning: unexpected length %lld != %lld\n", name, head.size, len);
    129 	if(strcmp(name, "<stdin>") != 0 && strcmp(head.name, name) != 0)
    130 		fprint(2, "%s: warning: unexpected name %s\n", name, head.name);
    131 
    132 	if(readblock(fd1, data1, HeadSize) < 0){
    133 		fprint(2, "%s: reading header: %r\n", name);
    134 		return;
    135 	}
    136 	if(unpackarenahead(&head, data) < 0){
    137 		fprint(2, "%s: corrupt arena header: %r\n", name);
    138 		return;
    139 	}
    140 	if(head.version != ArenaVersion4 && head.version != ArenaVersion5)
    141 		fprint(2, "%s: warning: unknown arena version %d\n", name, head.version);
    142 	if(len != 0 && len != head.size)
    143 		fprint(2, "%s: warning: unexpected length %lld != %lld\n", name, head.size, len);
    144 	if(strcmp(name, "<stdin>") != 0 && strcmp(head.name, name) != 0)
    145 		fprint(2, "%s: warning: unexpected name %s\n", name, head.name);
    146 
    147 	seek(fd, -HeadSize, 1);
    148 	seek(fd1, -HeadSize, 1);
    149 
    150 	if(printheader(name, &head, fd) < 0)
    151 		return;
    152 
    153 	/*
    154 	 * now we know how much to read
    155 	 * read everything but the last block, which is special
    156 	 */
    157 	e = head.size;
    158 	bs = blocksize;
    159 	for(n = 0; n < e; n += bs){
    160 		if(n + bs > e)
    161 			bs = e - n;
    162 		if(readblock(fd, data, bs) < 0){
    163 			fprint(2, "%s: read data: %r\n", name);
    164 			return;
    165 		}
    166 		if(readblock(fd1, data1, bs) < 0){
    167 			fprint(2, "%s: read data: %r\n", name);
    168 			return;
    169 		}
    170 		if(memcmp(data, data1, bs) != 0){
    171 			print("mismatch at %llx\n", n);
    172 			for(i=0; i<bs; i+=16){
    173 				if(memcmp(data+i, data1+i, 16) != 0){
    174 					snprint(buf, sizeof buf, "%llx", n+i);
    175 					print("%s ", buf);
    176 					for(j=0; j<16; j++){
    177 						print(" %.2ux", data[i+j]);
    178 						if(j == 7)
    179 							print(" -");
    180 					}
    181 					print("\n");
    182 					print("%*s ", (int)strlen(buf), "");
    183 					for(j=0; j<16; j++){
    184 						print(" %.2ux", data1[i+j]);
    185 						if(j == 7)
    186 							print(" -");
    187 					}
    188 					print("\n");
    189 				}
    190 			}
    191 		}
    192 	}
    193 }
    194 
    195 static int
    196 shouldcheck(char *name, char **s, int n)
    197 {
    198 	int i;
    199 
    200 	if(n == 0)
    201 		return 1;
    202 
    203 	for(i=0; i<n; i++){
    204 		if(s[i] && strcmp(name, s[i]) == 0){
    205 			s[i] = nil;
    206 			return 1;
    207 		}
    208 	}
    209 	return 0;
    210 }
    211 
    212 char *
    213 readap(int fd, ArenaPart *ap)
    214 {
    215 	char *table;
    216 
    217 	if(preadblock(fd, data, 8192, PartBlank) < 0)
    218 		sysfatal("read arena part header: %r");
    219 	if(unpackarenapart(ap, data) < 0)
    220 		sysfatal("corrupted arena part header: %r");
    221 	fprint(2, "# arena part version=%d blocksize=%d arenabase=%d\n",
    222 		ap->version, ap->blocksize, ap->arenabase);
    223 	ap->tabbase = (PartBlank+HeadSize+ap->blocksize-1)&~(ap->blocksize-1);
    224 	ap->tabsize = ap->arenabase - ap->tabbase;
    225 	table = malloc(ap->tabsize+1);
    226 	if(preadblock(fd, (uchar*)table, ap->tabsize, ap->tabbase) < 0)
    227 		sysfatal("reading arena part directory: %r");
    228 	table[ap->tabsize] = 0;
    229 	return table;
    230 }
    231 
    232 void
    233 threadmain(int argc, char *argv[])
    234 {
    235 	int i, nline;
    236 	char *p, *q, *table, *table1, *f[10], line[256];
    237 	vlong start, stop;
    238 	ArenaPart ap;
    239 	ArenaPart ap1;
    240 
    241 	ventifmtinstall();
    242 	blocksize = MaxIoSize;
    243 	ARGBEGIN{
    244 	case 'b':
    245 		blocksize = unittoull(EARGF(usage()));
    246 		break;
    247 	case 's':
    248 		sleepms = atoi(EARGF(usage()));
    249 		break;
    250 	case 'v':
    251 		verbose++;
    252 		break;
    253 	default:
    254 		usage();
    255 		break;
    256 	}ARGEND
    257 
    258 	if(argc < 2)
    259 		usage();
    260 
    261 	data = vtmalloc(blocksize);
    262 	data1 = vtmalloc(blocksize);
    263 	if((fd = open(argv[0], OREAD)) < 0)
    264 		sysfatal("open %s: %r", argv[0]);
    265 	if((fd1 = open(argv[1], OREAD)) < 0)
    266 		sysfatal("open %s: %r", argv[0]);
    267 
    268 	table = readap(fd, &ap);
    269 	table1 = readap(fd1, &ap1);
    270 	if(strcmp(table, table1) != 0)
    271 		sysfatal("arena partitions do not have identical tables");
    272 
    273 	nline = atoi(table);
    274 	p = strchr(table, '\n');
    275 	if(p)
    276 		p++;
    277 	for(i=0; i<nline; i++){
    278 		if(p == nil){
    279 			fprint(2, "warning: unexpected arena table end\n");
    280 			break;
    281 		}
    282 		q = strchr(p, '\n');
    283 		if(q)
    284 			*q++ = 0;
    285 		if(strlen(p) >= sizeof line){
    286 			fprint(2, "warning: long arena table line: %s\n", p);
    287 			p = q;
    288 			continue;
    289 		}
    290 		strcpy(line, p);
    291 		memset(f, 0, sizeof f);
    292 		if(tokenize(line, f, nelem(f)) < 3){
    293 			fprint(2, "warning: bad arena table line: %s\n", p);
    294 			p = q;
    295 			continue;
    296 		}
    297 		p = q;
    298 		if(shouldcheck(f[0], argv+1, argc-1)){
    299 			start = strtoull(f[1], 0, 0);
    300 			stop = strtoull(f[2], 0, 0);
    301 			if(stop <= start){
    302 				fprint(2, "%s: bad start,stop %lld,%lld\n", f[0], stop, start);
    303 				continue;
    304 			}
    305 			if(seek(fd, start, 0) < 0)
    306 				fprint(2, "%s: seek to start: %r\n", f[0]);
    307 			if(seek(fd1, start, 0) < 0)
    308 				fprint(2, "%s: seek to start: %r\n", f[0]);
    309 			cmparena(f[0], stop - start);
    310 		}
    311 	}
    312 	for(i=2; i<argc; i++)
    313 		if(argv[i] != 0)
    314 			fprint(2, "%s: did not find arena\n", argv[i]);
    315 
    316 	threadexitsall(nil);
    317 }