Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "sam.h"
2
 
3
static	Block	*blist;
4
 
5
static int
6
tempdisk(void)
7
{
8
	char buf[128];
9
	int i, fd;
10
 
11
	snprint(buf, sizeof buf, "/tmp/X%d.%.4ssam", getpid(), getuser());
12
	for(i='A'; i<='Z'; i++){
13
		buf[5] = i;
14
		if(access(buf, AEXIST) == 0)
15
			continue;
16
		fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
17
		if(fd >= 0)
18
			return fd;
19
	}
20
	return -1;
21
}
22
 
23
Disk*
24
diskinit()
25
{
26
	Disk *d;
27
 
28
	d = emalloc(sizeof(Disk));
29
	d->fd = tempdisk();
30
	if(d->fd < 0){
31
		fprint(2, "sam: can't create temp file: %r\n");
32
		exits("diskinit");
33
	}
34
	return d;
35
}
36
 
37
static
38
uint
39
ntosize(uint n, uint *ip)
40
{
41
	uint size;
42
 
43
	if(n > Maxblock)
44
		panic("internal error: ntosize");
45
	size = n;
46
	if(size & (Blockincr-1))
47
		size += Blockincr - (size & (Blockincr-1));
48
	/* last bucket holds blocks of exactly Maxblock */
49
	if(ip)
50
		*ip = size/Blockincr;
51
	return size * sizeof(Rune);
52
}
53
 
54
Block*
55
disknewblock(Disk *d, uint n)
56
{
57
	uint i, j, size;
58
	Block *b;
59
 
60
	size = ntosize(n, &i);
61
	b = d->free[i];
62
	if(b)
63
		d->free[i] = b->next;
64
	else{
65
		/* allocate in chunks to reduce malloc overhead */
66
		if(blist == nil){
67
			blist = emalloc(100*sizeof(Block));
68
			for(j=0; j<100-1; j++)
69
				blist[j].next = &blist[j+1];
70
		}
71
		b = blist;
72
		blist = b->next;
73
		b->addr = d->addr;
74
		d->addr += size;
75
	}
76
	b->n = n;
77
	return b;
78
}
79
 
80
void
81
diskrelease(Disk *d, Block *b)
82
{
83
	uint i;
84
 
85
	ntosize(b->n, &i);
86
	b->next = d->free[i];
87
	d->free[i] = b;
88
}
89
 
90
void
91
diskwrite(Disk *d, Block **bp, Rune *r, uint n)
92
{
93
	int size, nsize;
94
	Block *b;
95
 
96
	b = *bp;
97
	size = ntosize(b->n, nil);
98
	nsize = ntosize(n, nil);
99
	if(size != nsize){
100
		diskrelease(d, b);
101
		b = disknewblock(d, n);
102
		*bp = b;
103
	}
104
	if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
105
		panic("write error to temp file");
106
	b->n = n;
107
}
108
 
109
void
110
diskread(Disk *d, Block *b, Rune *r, uint n)
111
{
112
	if(n > b->n)
113
		panic("internal error: diskread");
114
 
115
	ntosize(b->n, nil);	/* called only for sanity check on Maxblock */
116
	if(pread(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
117
		panic("read error from temp file");
118
}