137da2899SCharles.Forsythimplement Logs; 237da2899SCharles.Forsyth 337da2899SCharles.Forsythinclude "sys.m"; 437da2899SCharles.Forsyth sys: Sys; 537da2899SCharles.Forsyth 637da2899SCharles.Forsythinclude "draw.m"; 737da2899SCharles.Forsyth 837da2899SCharles.Forsythinclude "bufio.m"; 937da2899SCharles.Forsyth bufio: Bufio; 1037da2899SCharles.Forsyth Iobuf: import bufio; 1137da2899SCharles.Forsyth 1237da2899SCharles.Forsythinclude "string.m"; 1337da2899SCharles.Forsyth str: String; 1437da2899SCharles.Forsyth 1537da2899SCharles.Forsythinclude "logs.m"; 1637da2899SCharles.Forsyth 1737da2899SCharles.ForsythHashsize: con 1024; 1837da2899SCharles.ForsythIncr: con 500; 1937da2899SCharles.Forsyth 2037da2899SCharles.Forsythinit(bio: Bufio): string 2137da2899SCharles.Forsyth{ 2237da2899SCharles.Forsyth sys = load Sys Sys->PATH; 2337da2899SCharles.Forsyth bufio = bio; 2437da2899SCharles.Forsyth str = load String String->PATH; 2537da2899SCharles.Forsyth if(str == nil) 2637da2899SCharles.Forsyth return sys->sprint("can't load %s: %r", String->PATH); 2737da2899SCharles.Forsyth return nil; 2837da2899SCharles.Forsyth} 2937da2899SCharles.Forsyth 3037da2899SCharles.ForsythEntry.read(in: ref Iobuf): (ref Entry, string) 3137da2899SCharles.Forsyth{ 3237da2899SCharles.Forsyth if((s := in.gets('\n')) == nil) 3337da2899SCharles.Forsyth return (nil, nil); 3437da2899SCharles.Forsyth if(s[len s-1] == '\n') 3537da2899SCharles.Forsyth s = s[0:len s-1]; 3637da2899SCharles.Forsyth 3737da2899SCharles.Forsyth e := ref Entry; 3837da2899SCharles.Forsyth e.x = -1; 3937da2899SCharles.Forsyth 4037da2899SCharles.Forsyth l := str->unquoted(s); 4137da2899SCharles.Forsyth fields := array[11] of string; 4237da2899SCharles.Forsyth for(i := 0; l != nil; l = tl l) 4337da2899SCharles.Forsyth fields[i++] = S(hd l); 4437da2899SCharles.Forsyth 4537da2899SCharles.Forsyth # time gen verb path serverpath mode uid gid mtime length 4637da2899SCharles.Forsyth # 1064889121 4 a sys/src/cmd/ip/httpd/webls.denied - 664 sys sys 1064887847 3 4737da2899SCharles.Forsyth # time[0] gen[1] op[2] path[3] (serverpath|"-")[4] mode[5] uid[6] gid[7] mtime[8] length[9] 4837da2899SCharles.Forsyth 4937da2899SCharles.Forsyth if(i < 10 || len fields[2] != 1) 5037da2899SCharles.Forsyth return (nil, sys->sprint("bad log entry: %q", s)); 5137da2899SCharles.Forsyth e.action = fields[2][0]; 5237da2899SCharles.Forsyth case e.action { 5337da2899SCharles.Forsyth 'a' or 'c' or 'd' or 'm' => 5437da2899SCharles.Forsyth ; 5537da2899SCharles.Forsyth * => 5637da2899SCharles.Forsyth return (nil, sys->sprint("bad log entry: %q", s)); 5737da2899SCharles.Forsyth } 5837da2899SCharles.Forsyth 5937da2899SCharles.Forsyth time := bigof(fields[0], 10); 6037da2899SCharles.Forsyth sgen := bigof(fields[1], 10); 6137da2899SCharles.Forsyth e.seq = (time << 32) | sgen; # for easier comparison 6237da2899SCharles.Forsyth 6337da2899SCharles.Forsyth # time/gen check 6437da2899SCharles.Forsyth # name check 6537da2899SCharles.Forsyth 6637da2899SCharles.Forsyth if(fields[4] == "-") # undocumented 6737da2899SCharles.Forsyth fields[4] = fields[3]; 6837da2899SCharles.Forsyth e.path = fields[3]; 6937da2899SCharles.Forsyth e.serverpath = fields[4]; 7037da2899SCharles.Forsyth e.d = sys->nulldir; 7137da2899SCharles.Forsyth { 7237da2899SCharles.Forsyth e.d.mode = intof(fields[5], 8); 7337da2899SCharles.Forsyth e.d.qid.qtype = e.d.mode>>24; 7437da2899SCharles.Forsyth e.d.uid = fields[6]; 7537da2899SCharles.Forsyth if(e.d.uid == "-") 7637da2899SCharles.Forsyth e.d.uid = ""; 7737da2899SCharles.Forsyth e.d.gid = fields[7]; 7837da2899SCharles.Forsyth if(e.d.gid == "-") 7937da2899SCharles.Forsyth e.d.gid = ""; 8037da2899SCharles.Forsyth e.d.mtime = intof(fields[8], 10); 8137da2899SCharles.Forsyth e.d.length = bigof(fields[9], 10); 8237da2899SCharles.Forsyth }exception ex { 8337da2899SCharles.Forsyth "log format:*" => 8437da2899SCharles.Forsyth return (nil, sys->sprint("%s in log entry %q", ex, s)); 8537da2899SCharles.Forsyth } 8637da2899SCharles.Forsyth e.contents = fields[10] :: nil; # optional 8737da2899SCharles.Forsyth return (e, nil); 8837da2899SCharles.Forsyth} 8937da2899SCharles.Forsyth 9037da2899SCharles.Forsythrev[T](l: list of T): list of T 9137da2899SCharles.Forsyth{ 9237da2899SCharles.Forsyth rl: list of T; 9337da2899SCharles.Forsyth for(; l != nil; l = tl l) 9437da2899SCharles.Forsyth rl = hd l :: rl; 9537da2899SCharles.Forsyth return rl; 9637da2899SCharles.Forsyth} 9737da2899SCharles.Forsyth 9837da2899SCharles.Forsythbigof(s: string, base: int): big 9937da2899SCharles.Forsyth{ 10037da2899SCharles.Forsyth (b, r) := str->tobig(s, base); 10137da2899SCharles.Forsyth if(r != nil) 10237da2899SCharles.Forsyth raise "invalid integer field"; 10337da2899SCharles.Forsyth return b; 10437da2899SCharles.Forsyth} 10537da2899SCharles.Forsyth 10637da2899SCharles.Forsythintof(s: string, base: int): int 10737da2899SCharles.Forsyth{ 10837da2899SCharles.Forsyth return int bigof(s, base); 10937da2899SCharles.Forsyth} 11037da2899SCharles.Forsyth 11137da2899SCharles.Forsythmkpath(root: string, name: string): string 11237da2899SCharles.Forsyth{ 11337da2899SCharles.Forsyth if(len root > 0 && root[len root-1] != '/' && (len name == 0 || name[0] != '/')) 11437da2899SCharles.Forsyth return root+"/"+name; 11537da2899SCharles.Forsyth return root+name; 11637da2899SCharles.Forsyth} 11737da2899SCharles.Forsyth 11837da2899SCharles.Forsythcontents(e: ref Entry): string 11937da2899SCharles.Forsyth{ 12037da2899SCharles.Forsyth if(e.contents == nil) 12137da2899SCharles.Forsyth return ""; 12237da2899SCharles.Forsyth s := ""; 12337da2899SCharles.Forsyth for(cl := e.contents; cl != nil; cl = tl cl) 12437da2899SCharles.Forsyth s += " " + hd cl; 125*1f44c82aSCharles.Forsyth return s; # includes initial space 12637da2899SCharles.Forsyth} 12737da2899SCharles.Forsyth 12837da2899SCharles.ForsythEntry.text(e: self ref Entry): string 12937da2899SCharles.Forsyth{ 13037da2899SCharles.Forsyth a := e.action; 13137da2899SCharles.Forsyth if(a == 0) 13237da2899SCharles.Forsyth a = '?'; 13337da2899SCharles.Forsyth return sys->sprint("%bd %bd %q [%d] %c m=%uo l=%bd t=%ud c=%q", e.seq>>32, e.seq & 16rFFFFFFFF, e.path, e.x, a, e.d.mode, e.d.length, e.d.mtime, contents(e)); 13437da2899SCharles.Forsyth} 13537da2899SCharles.Forsyth 13637da2899SCharles.ForsythEntry.sumtext(e: self ref Entry): string 13737da2899SCharles.Forsyth{ 13837da2899SCharles.Forsyth case e.action { 13937da2899SCharles.Forsyth 'a' or 'm' => 14037da2899SCharles.Forsyth return sys->sprint("%c %q %uo %q %q %ud", e.action, e.path, e.d.mode, e.d.uid, e.d.gid, e.d.mtime); 14137da2899SCharles.Forsyth 'd' or 'c' => 14237da2899SCharles.Forsyth return sys->sprint("%c %q", e.action, e.path); 14337da2899SCharles.Forsyth * => 14437da2899SCharles.Forsyth return sys->sprint("? %q", e.path); 14537da2899SCharles.Forsyth } 14637da2899SCharles.Forsyth} 14737da2899SCharles.Forsyth 14837da2899SCharles.ForsythEntry.dbtext(e: self ref Entry): string 14937da2899SCharles.Forsyth{ 15037da2899SCharles.Forsyth # path dpath|"-" mode uid gid mtime length 15137da2899SCharles.Forsyth return sys->sprint("%bd %bd %q - %uo %q %q %ud %bd%s", e.seq>>32, e.seq & 16rFFFFFFFF, e.path, e.d.mode, e.d.uid, e.d.gid, e.d.mtime, e.d.length, contents(e)); 15237da2899SCharles.Forsyth} 15337da2899SCharles.Forsyth 15437da2899SCharles.ForsythEntry.logtext(e: self ref Entry): string 15537da2899SCharles.Forsyth{ 15637da2899SCharles.Forsyth # gen n act path spath|"-" dpath|"-" mode uid gid mtime length 15737da2899SCharles.Forsyth a := e.action; 15837da2899SCharles.Forsyth if(a == 0) 15937da2899SCharles.Forsyth a = '?'; 16037da2899SCharles.Forsyth sf := e.serverpath; 16137da2899SCharles.Forsyth if(sf == nil || sf == e.path) 16237da2899SCharles.Forsyth sf = "-"; 16337da2899SCharles.Forsyth return sys->sprint("%bd %bd %c %q %q %uo %q %q %ud %bd%s", e.seq>>32, e.seq & 16rFFFFFFFF, a, e.path, sf, e.d.mode, e.d.uid, e.d.gid, e.d.mtime, e.d.length, contents(e)); 16437da2899SCharles.Forsyth} 16537da2899SCharles.Forsyth 16637da2899SCharles.ForsythEntry.remove(e: self ref Entry) 16737da2899SCharles.Forsyth{ 16837da2899SCharles.Forsyth e.action = 'd'; 16937da2899SCharles.Forsyth} 17037da2899SCharles.Forsyth 17137da2899SCharles.ForsythEntry.removed(e: self ref Entry): int 17237da2899SCharles.Forsyth{ 17337da2899SCharles.Forsyth return e.action == 'd'; 17437da2899SCharles.Forsyth} 17537da2899SCharles.Forsyth 17637da2899SCharles.ForsythEntry.update(e: self ref Entry, n: ref Entry) 17737da2899SCharles.Forsyth{ 17837da2899SCharles.Forsyth if(n == nil) 17937da2899SCharles.Forsyth return; 18037da2899SCharles.Forsyth if(n.action == 'd') 18137da2899SCharles.Forsyth e.contents = nil; 18237da2899SCharles.Forsyth else 18337da2899SCharles.Forsyth e.d = n.d; 18437da2899SCharles.Forsyth if(n.action != 'm' || e.action == 'd') 18537da2899SCharles.Forsyth e.action = n.action; 18637da2899SCharles.Forsyth e.serverpath = S(n.serverpath); 18737da2899SCharles.Forsyth for(nl := rev(n.contents); nl != nil; nl = tl nl) 18837da2899SCharles.Forsyth e.contents = hd nl :: e.contents; 18937da2899SCharles.Forsyth if(n.seq > e.seq) 19037da2899SCharles.Forsyth e.seq = n.seq; 19137da2899SCharles.Forsyth} 19237da2899SCharles.Forsyth 19337da2899SCharles.ForsythDb.new(name: string): ref Db 19437da2899SCharles.Forsyth{ 19537da2899SCharles.Forsyth db := ref Db; 19637da2899SCharles.Forsyth db.name = name; 19737da2899SCharles.Forsyth db.stateht = array[Hashsize] of list of ref Entry; 19837da2899SCharles.Forsyth db.nstate = 0; 19937da2899SCharles.Forsyth db.state = array[50] of ref Entry; 20037da2899SCharles.Forsyth return db; 20137da2899SCharles.Forsyth} 20237da2899SCharles.Forsyth 20337da2899SCharles.ForsythDb.look(db: self ref Db, name: string): ref Entry 20437da2899SCharles.Forsyth{ 20537da2899SCharles.Forsyth (b, nil) := hash(name, len db.stateht); 20637da2899SCharles.Forsyth for(l := db.stateht[b]; l != nil; l = tl l) 20737da2899SCharles.Forsyth if((hd l).path == name) 20837da2899SCharles.Forsyth return hd l; 20937da2899SCharles.Forsyth return nil; 21037da2899SCharles.Forsyth} 21137da2899SCharles.Forsyth 21237da2899SCharles.ForsythDb.entry(db: self ref Db, seq: big, name: string, d: Sys->Dir): ref Entry 21337da2899SCharles.Forsyth{ 21437da2899SCharles.Forsyth e := ref Entry; 21537da2899SCharles.Forsyth e.action = 'a'; 21637da2899SCharles.Forsyth e.seq = seq; 21737da2899SCharles.Forsyth e.path = name; 21837da2899SCharles.Forsyth e.d = d; 21937da2899SCharles.Forsyth e.x = db.nstate++; 22037da2899SCharles.Forsyth if(e.x >= len db.state){ 22137da2899SCharles.Forsyth a := array[len db.state + Incr] of ref Entry; 22237da2899SCharles.Forsyth a[0:] = db.state; 22337da2899SCharles.Forsyth db.state = a; 22437da2899SCharles.Forsyth } 22537da2899SCharles.Forsyth db.state[e.x] = e; 22637da2899SCharles.Forsyth (b, nil) := hash(name, len db.stateht); 22737da2899SCharles.Forsyth db.stateht[b] = e :: db.stateht[b]; 22837da2899SCharles.Forsyth return e; 22937da2899SCharles.Forsyth} 23037da2899SCharles.Forsyth 23137da2899SCharles.ForsythDb.sort(db: self ref Db, key: int) 23237da2899SCharles.Forsyth{ 23337da2899SCharles.Forsyth sortentries(db.state[0:db.nstate], key); 23437da2899SCharles.Forsyth} 23537da2899SCharles.Forsyth 23637da2899SCharles.Forsythsortentries(a: array of ref Entry, key: int): (array of ref Entry, int) 23737da2899SCharles.Forsyth{ 23837da2899SCharles.Forsyth mergesort(a, array[len a] of ref Entry, key); 23937da2899SCharles.Forsyth return (a, len a); 24037da2899SCharles.Forsyth} 24137da2899SCharles.Forsyth 24237da2899SCharles.Forsythmergesort(a, b: array of ref Entry, key: int) 24337da2899SCharles.Forsyth{ 24437da2899SCharles.Forsyth r := len a; 24537da2899SCharles.Forsyth if(r > 1) { 24637da2899SCharles.Forsyth m := (r-1)/2 + 1; 24737da2899SCharles.Forsyth mergesort(a[0:m], b[0:m], key); 24837da2899SCharles.Forsyth mergesort(a[m:], b[m:], key); 24937da2899SCharles.Forsyth b[0:] = a; 25037da2899SCharles.Forsyth for((i, j, k) := (0, m, 0); i < m && j < r; k++) { 25137da2899SCharles.Forsyth if(key==Byname && b[i].path > b[j].path || key==Byseq && b[i].seq > b[j].seq) 25237da2899SCharles.Forsyth a[k] = b[j++]; 25337da2899SCharles.Forsyth else 25437da2899SCharles.Forsyth a[k] = b[i++]; 25537da2899SCharles.Forsyth } 25637da2899SCharles.Forsyth if(i < m) 25737da2899SCharles.Forsyth a[k:] = b[i:m]; 25837da2899SCharles.Forsyth else if(j < r) 25937da2899SCharles.Forsyth a[k:] = b[j:r]; 26037da2899SCharles.Forsyth } 26137da2899SCharles.Forsyth} 26237da2899SCharles.Forsyth 26337da2899SCharles.Forsythstrings: array of list of string; 26437da2899SCharles.Forsyth 26537da2899SCharles.ForsythS(s: string): string 26637da2899SCharles.Forsyth{ 26737da2899SCharles.Forsyth if(strings == nil) 26837da2899SCharles.Forsyth strings = array[257] of list of string; 26937da2899SCharles.Forsyth h := hash(s, len strings).t0; 27037da2899SCharles.Forsyth for(sl := strings[h]; sl != nil; sl = tl sl) 27137da2899SCharles.Forsyth if(hd sl == s) 27237da2899SCharles.Forsyth return hd sl; 27337da2899SCharles.Forsyth strings[h] = s :: strings[h]; 27437da2899SCharles.Forsyth return s; 27537da2899SCharles.Forsyth} 27637da2899SCharles.Forsyth 27737da2899SCharles.Forsythhash(s: string, n: int): (int, int) 27837da2899SCharles.Forsyth{ 27937da2899SCharles.Forsyth # hashpjw 28037da2899SCharles.Forsyth h := 0; 28137da2899SCharles.Forsyth for(i:=0; i<len s; i++){ 28237da2899SCharles.Forsyth h = (h<<4) + s[i]; 28337da2899SCharles.Forsyth if((g := h & int 16rF0000000) != 0) 28437da2899SCharles.Forsyth h ^= ((g>>24) & 16rFF) | g; 28537da2899SCharles.Forsyth } 28637da2899SCharles.Forsyth return ((h&~(1<<31))%n, h); 28737da2899SCharles.Forsyth} 288