blob: 81c983892dc869db4f3163e990930fc8aa95b1b6 [file] [log] [blame]
rsc76193d72003-09-30 17:47:42 +00001#include "sam.h"
2
3static Block *blist;
4
5#if 0
6static int
7tempdisk(void)
8{
9 char buf[128];
10 int i, fd;
11
12 snprint(buf, sizeof buf, "/tmp/X%d.%.4ssam", getpid(), getuser());
13 for(i='A'; i<='Z'; i++){
14 buf[5] = i;
15 if(access(buf, AEXIST) == 0)
16 continue;
17 fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
18 if(fd >= 0)
19 return fd;
20 }
21 return -1;
22}
23#else
24extern int tempdisk(void);
25#endif
26
27Disk*
rsc2b604082005-05-07 22:42:14 +000028diskinit(void)
rsc76193d72003-09-30 17:47:42 +000029{
30 Disk *d;
31
32 d = emalloc(sizeof(Disk));
33 d->fd = tempdisk();
34 if(d->fd < 0){
35 fprint(2, "sam: can't create temp file: %r\n");
36 exits("diskinit");
37 }
38 return d;
39}
40
41static
42uint
43ntosize(uint n, uint *ip)
44{
45 uint size;
46
47 if(n > Maxblock)
48 panic("internal error: ntosize");
49 size = n;
50 if(size & (Blockincr-1))
51 size += Blockincr - (size & (Blockincr-1));
52 /* last bucket holds blocks of exactly Maxblock */
53 if(ip)
54 *ip = size/Blockincr;
55 return size * sizeof(Rune);
56}
57
58Block*
59disknewblock(Disk *d, uint n)
60{
61 uint i, j, size;
62 Block *b;
63
64 size = ntosize(n, &i);
65 b = d->free[i];
66 if(b)
rsc522b0682003-09-30 19:05:50 +000067 d->free[i] = b->u.next;
rsc76193d72003-09-30 17:47:42 +000068 else{
69 /* allocate in chunks to reduce malloc overhead */
70 if(blist == nil){
71 blist = emalloc(100*sizeof(Block));
72 for(j=0; j<100-1; j++)
rsc522b0682003-09-30 19:05:50 +000073 blist[j].u.next = &blist[j+1];
rsc76193d72003-09-30 17:47:42 +000074 }
75 b = blist;
rsc522b0682003-09-30 19:05:50 +000076 blist = b->u.next;
rsc76193d72003-09-30 17:47:42 +000077 b->addr = d->addr;
78 d->addr += size;
79 }
rsc522b0682003-09-30 19:05:50 +000080 b->u.n = n;
rsc76193d72003-09-30 17:47:42 +000081 return b;
82}
83
84void
85diskrelease(Disk *d, Block *b)
86{
87 uint i;
88
rsc522b0682003-09-30 19:05:50 +000089 ntosize(b->u.n, &i);
90 b->u.next = d->free[i];
rsc76193d72003-09-30 17:47:42 +000091 d->free[i] = b;
92}
93
94void
95diskwrite(Disk *d, Block **bp, Rune *r, uint n)
96{
97 int size, nsize;
98 Block *b;
99
100 b = *bp;
rsc522b0682003-09-30 19:05:50 +0000101 size = ntosize(b->u.n, nil);
rsc76193d72003-09-30 17:47:42 +0000102 nsize = ntosize(n, nil);
103 if(size != nsize){
104 diskrelease(d, b);
105 b = disknewblock(d, n);
106 *bp = b;
107 }
108 if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
109 panic("write error to temp file");
rsc522b0682003-09-30 19:05:50 +0000110 b->u.n = n;
rsc76193d72003-09-30 17:47:42 +0000111}
112
113void
114diskread(Disk *d, Block *b, Rune *r, uint n)
115{
rsc522b0682003-09-30 19:05:50 +0000116 if(n > b->u.n)
rsc76193d72003-09-30 17:47:42 +0000117 panic("internal error: diskread");
118
rsc522b0682003-09-30 19:05:50 +0000119 ntosize(b->u.n, nil); /* called only for sanity check on Maxblock */
rsc76193d72003-09-30 17:47:42 +0000120 if(pread(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
121 panic("read error from temp file");
122}