1*37da2899SCharles.Forsythimplement Diskm; 2*37da2899SCharles.Forsyth 3*37da2899SCharles.Forsythinclude "common.m"; 4*37da2899SCharles.Forsyth 5*37da2899SCharles.Forsythsys : Sys; 6*37da2899SCharles.Forsythacme : Acme; 7*37da2899SCharles.Forsythutils : Utils; 8*37da2899SCharles.Forsyth 9*37da2899SCharles.ForsythSZSHORT, Block, Blockincr, Astring : import Dat; 10*37da2899SCharles.Forsytherror : import utils; 11*37da2899SCharles.Forsyth 12*37da2899SCharles.Forsythinit(mods : ref Dat->Mods) 13*37da2899SCharles.Forsyth{ 14*37da2899SCharles.Forsyth sys = mods.sys; 15*37da2899SCharles.Forsyth acme = mods.acme; 16*37da2899SCharles.Forsyth utils = mods.utils; 17*37da2899SCharles.Forsyth} 18*37da2899SCharles.Forsyth 19*37da2899SCharles.Forsythblist : ref Block; 20*37da2899SCharles.Forsyth 21*37da2899SCharles.Forsythtempfile() : ref Sys->FD 22*37da2899SCharles.Forsyth{ 23*37da2899SCharles.Forsyth buf := sys->sprint("/tmp/X%d.%.4sacme", sys->pctl(0, nil), utils->getuser()); 24*37da2899SCharles.Forsyth for(i:='A'; i<='Z'; i++){ 25*37da2899SCharles.Forsyth buf[5] = i; 26*37da2899SCharles.Forsyth (ok, nil) := sys->stat(buf); 27*37da2899SCharles.Forsyth if(ok == 0) 28*37da2899SCharles.Forsyth continue; 29*37da2899SCharles.Forsyth fd := sys->create(buf, Sys->ORDWR|Sys->ORCLOSE, 8r600); 30*37da2899SCharles.Forsyth if(fd != nil) 31*37da2899SCharles.Forsyth return fd; 32*37da2899SCharles.Forsyth } 33*37da2899SCharles.Forsyth return nil; 34*37da2899SCharles.Forsyth} 35*37da2899SCharles.Forsyth 36*37da2899SCharles.ForsythDisk.init() : ref Disk 37*37da2899SCharles.Forsyth{ 38*37da2899SCharles.Forsyth d : ref Disk; 39*37da2899SCharles.Forsyth 40*37da2899SCharles.Forsyth d = ref Disk; 41*37da2899SCharles.Forsyth d.free = array[Dat->Maxblock/Dat->Blockincr+1] of ref Block; 42*37da2899SCharles.Forsyth d.addr = 0; 43*37da2899SCharles.Forsyth d.fd = tempfile(); 44*37da2899SCharles.Forsyth if(d.fd == nil){ 45*37da2899SCharles.Forsyth error(sys->sprint("can't create temp file %r")); 46*37da2899SCharles.Forsyth acme->acmeexit("temp create"); 47*37da2899SCharles.Forsyth } 48*37da2899SCharles.Forsyth return d; 49*37da2899SCharles.Forsyth} 50*37da2899SCharles.Forsyth 51*37da2899SCharles.Forsythntosize(n : int) : (int, int) 52*37da2899SCharles.Forsyth{ 53*37da2899SCharles.Forsyth size : int; 54*37da2899SCharles.Forsyth 55*37da2899SCharles.Forsyth if (n > Dat->Maxblock) 56*37da2899SCharles.Forsyth error("bad assert in ntosize"); 57*37da2899SCharles.Forsyth size = n; 58*37da2899SCharles.Forsyth if(size & (Blockincr-1)) 59*37da2899SCharles.Forsyth size += Blockincr - (size & (Blockincr-1)); 60*37da2899SCharles.Forsyth # last bucket holds blocks of exactly Maxblock 61*37da2899SCharles.Forsyth return (size * SZSHORT, size/Blockincr); 62*37da2899SCharles.Forsyth} 63*37da2899SCharles.Forsyth 64*37da2899SCharles.ForsythDisk.new(d : self ref Disk, n : int) : ref Block 65*37da2899SCharles.Forsyth{ 66*37da2899SCharles.Forsyth i, j, size : int; 67*37da2899SCharles.Forsyth b, bl : ref Block; 68*37da2899SCharles.Forsyth 69*37da2899SCharles.Forsyth (size, i) = ntosize(n); 70*37da2899SCharles.Forsyth b = d.free[i]; 71*37da2899SCharles.Forsyth if(b != nil) 72*37da2899SCharles.Forsyth d.free[i] = b.next; 73*37da2899SCharles.Forsyth else{ 74*37da2899SCharles.Forsyth # allocate in chunks to reduce malloc overhead 75*37da2899SCharles.Forsyth if(blist == nil){ 76*37da2899SCharles.Forsyth blist = ref Block; 77*37da2899SCharles.Forsyth bl = blist; 78*37da2899SCharles.Forsyth for(j=0; j<100-1; j++) { 79*37da2899SCharles.Forsyth bl.next = ref Block; 80*37da2899SCharles.Forsyth bl = bl.next; 81*37da2899SCharles.Forsyth } 82*37da2899SCharles.Forsyth } 83*37da2899SCharles.Forsyth b = blist; 84*37da2899SCharles.Forsyth blist = b.next; 85*37da2899SCharles.Forsyth b.addr = d.addr; 86*37da2899SCharles.Forsyth d.addr += size; 87*37da2899SCharles.Forsyth } 88*37da2899SCharles.Forsyth b.n = n; 89*37da2899SCharles.Forsyth return b; 90*37da2899SCharles.Forsyth} 91*37da2899SCharles.Forsyth 92*37da2899SCharles.ForsythDisk.release(d : self ref Disk, b : ref Block) 93*37da2899SCharles.Forsyth{ 94*37da2899SCharles.Forsyth (nil, i) := ntosize(b.n); 95*37da2899SCharles.Forsyth b.next = d.free[i]; 96*37da2899SCharles.Forsyth d.free[i] = b; 97*37da2899SCharles.Forsyth} 98*37da2899SCharles.Forsyth 99*37da2899SCharles.ForsythDisk.write(d : self ref Disk, bp : ref Block, r : string, n : int) : ref Block 100*37da2899SCharles.Forsyth{ 101*37da2899SCharles.Forsyth size, nsize, i : int; 102*37da2899SCharles.Forsyth b : ref Block; 103*37da2899SCharles.Forsyth ab : array of byte; 104*37da2899SCharles.Forsyth 105*37da2899SCharles.Forsyth b = bp; 106*37da2899SCharles.Forsyth (size, i) = ntosize(b.n); 107*37da2899SCharles.Forsyth (nsize, i) = ntosize(n); 108*37da2899SCharles.Forsyth if(size != nsize){ 109*37da2899SCharles.Forsyth d.release(b); 110*37da2899SCharles.Forsyth b = d.new(n); 111*37da2899SCharles.Forsyth } 112*37da2899SCharles.Forsyth if(sys->seek(d.fd, big b.addr, 0) < big 0) 113*37da2899SCharles.Forsyth error("seek error in temp file"); 114*37da2899SCharles.Forsyth ab = utils->stob(r, n); 115*37da2899SCharles.Forsyth if(sys->write(d.fd, ab, len ab) != len ab) 116*37da2899SCharles.Forsyth error("write error to temp file"); 117*37da2899SCharles.Forsyth ab = nil; 118*37da2899SCharles.Forsyth b.n = n; 119*37da2899SCharles.Forsyth return b; 120*37da2899SCharles.Forsyth} 121*37da2899SCharles.Forsyth 122*37da2899SCharles.ForsythDisk.read(d : self ref Disk, b : ref Block, r : ref Astring, n : int) 123*37da2899SCharles.Forsyth{ 124*37da2899SCharles.Forsyth ab : array of byte; 125*37da2899SCharles.Forsyth 126*37da2899SCharles.Forsyth if (n > b.n) 127*37da2899SCharles.Forsyth error("bad assert in Disk.read"); 128*37da2899SCharles.Forsyth (nil, nil) := ntosize(b.n); 129*37da2899SCharles.Forsyth if(sys->seek(d.fd, big b.addr, 0) < big 0) 130*37da2899SCharles.Forsyth error("seek error in temp file"); 131*37da2899SCharles.Forsyth ab = array[n*SZSHORT] of byte; 132*37da2899SCharles.Forsyth if(sys->read(d.fd, ab, len ab) != len ab) 133*37da2899SCharles.Forsyth error("read error from temp file"); 134*37da2899SCharles.Forsyth utils->btos(ab, r); 135*37da2899SCharles.Forsyth ab = nil; 136*37da2899SCharles.Forsyth} 137