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