URI:
       tcmparenas.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tcmparenas.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 }