16 fprint(2, "usage: cmparenas [-b blocksize] [-s ms] [-v] arenapart1 arenapart2 [name...]]\n");
21 preadblock(int fd, uchar *buf, int n, vlong off)
25 for(nr = 0; nr < n; nr += m){
27 m = pread(fd, &buf[nr], m, off+nr);
38 readblock(int fd, uchar *buf, int n)
42 for(nr = 0; nr < n; nr += m){
44 m = read(fd, &buf[nr], m);
55 printheader(char *name, ArenaHead *head, int fd)
58 vlong baseoff, lo, hi, off;
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);
69 memset(&arena, 0, sizeof arena);
70 if(unpackarena(&arena, data) < 0){
71 fprint(2, "%s: unpack arena tail: %r\n", name);
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;
79 fprint(2, "%s: base=%llx size=%llx blocksize=%x\n", name, off, head->size, head->blocksize);
81 baseoff = head->blocksize;
82 fprint(2, "\t%llx-%llx: head\n", (vlong)0, 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;
89 lo = hi - (u64int)arena.diskstats.clumps/clumpmax * head->blocksize;
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);
95 fprint(2, "arena:\n");
96 printarena(2, &arena);
101 cmparena(char *name, vlong len)
110 fprint(2, "cmp %s\n", name);
112 memset(&s, 0, sizeof s);
115 * read a little bit, which will include the header
117 if(readblock(fd, data, HeadSize) < 0){
118 fprint(2, "%s: reading header: %r\n", name);
121 if(unpackarenahead(&head, data) < 0){
122 fprint(2, "%s: corrupt arena header: %r\n", name);
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);
132 if(readblock(fd1, data1, HeadSize) < 0){
133 fprint(2, "%s: reading header: %r\n", name);
136 if(unpackarenahead(&head, data) < 0){
137 fprint(2, "%s: corrupt arena header: %r\n", name);
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);
147 seek(fd, -HeadSize, 1);
148 seek(fd1, -HeadSize, 1);
150 if(printheader(name, &head, fd) < 0)
154 * now we know how much to read
155 * read everything but the last block, which is special
159 for(n = 0; n < e; n += bs){
162 if(readblock(fd, data, bs) < 0){
163 fprint(2, "%s: read data: %r\n", name);
166 if(readblock(fd1, data1, bs) < 0){
167 fprint(2, "%s: read data: %r\n", name);
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);
177 print(" %.2ux", data[i+j]);
182 print("%*s ", (int)strlen(buf), "");
184 print(" %.2ux", data1[i+j]);
196 shouldcheck(char *name, char **s, int n)
204 if(s[i] && strcmp(name, s[i]) == 0){
213 readap(int fd, ArenaPart *ap)
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;
233 threadmain(int argc, char *argv[])
236 char *p, *q, *table, *table1, *f[10], line[256];
242 blocksize = MaxIoSize;
245 blocksize = unittoull(EARGF(usage()));
248 sleepms = atoi(EARGF(usage()));
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]);
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");
274 p = strchr(table, '\n');
277 for(i=0; i<nline; i++){
279 fprint(2, "warning: unexpected arena table end\n");
285 if(strlen(p) >= sizeof line){
286 fprint(2, "warning: long arena table line: %s\n", 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);
298 if(shouldcheck(f[0], argv+1, argc-1)){
299 start = strtoull(f[1], 0, 0);
300 stop = strtoull(f[2], 0, 0);
302 fprint(2, "%s: bad start,stop %lld,%lld\n", f[0], stop, start);
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);
312 for(i=2; i<argc; i++)
314 fprint(2, "%s: did not find arena\n", argv[i]);