xref: /inferno-os/appl/acme/disk.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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