|
|
1.1 root 1: #include "sam.h"
2:
3: static flush();
4: static setcache();
5:
6: Buffer *
7: Bopen(dd)
8: Discdesc *dd;
9: {
10: register Buffer *b;
11: b=new(Buffer, 1);
12: b->disc=Dopen(dd);
13: strinit(&b->cache);
14: return b;
15: }
16: Bclose(b)
17: register Buffer *b;
18: {
19: Dclose(b->disc);
20: strclose(&b->cache);
21: free((uchar *)b);
22: }
23: int
24: Bread(b, addr, n, p0)
25: register Buffer *b;
26: uchar *addr;
27: int n;
28: Posn p0;
29: {
30: register m;
31: if(b->c2>b->disc->nbytes || b->c1>b->disc->nbytes)
32: panic("bread cache");
33: if(p0<0)
34: panic("Bread p0<0");
35: if(p0+n>b->nbytes){
36: n=b->nbytes-p0;
37: if(n<0)
38: panic("Bread<0");
39: }
40: if(!incache(b, p0, p0+n)){
41: flush(b);
42: if(n>=BLOCKSIZE/2)
43: return Dread(b->disc, addr, n, p0);
44: else{
45: Posn minp;
46: if(b->nbytes-p0>BLOCKSIZE/2)
47: m=BLOCKSIZE/2;
48: else
49: m=b->nbytes-p0;
50: if(m<n)
51: m=n;
52: minp=p0-BLOCKSIZE/2;
53: if(minp<0)
54: minp=0;
55: m+=p0-minp;
56: strinsure(&b->cache, (ulong)m);
57: if(Dread(b->disc, b->cache.s, m, minp)!=m)
58: panic("Bread");
59: b->cache.n=m;
60: b->c1=minp;
61: b->c2=minp+m;
62: b->dirty=FALSE;
63: }
64: }
65: bcopy(&b->cache.s[p0-b->c1], &b->cache.s[p0-b->c1+n], addr, 1);
66: return n;
67: }
68: Binsert(b, s, p0)
69: register Buffer *b;
70: String *s;
71: Posn p0;
72: {
73: if(b->c2>b->disc->nbytes || b->c1>b->disc->nbytes)
74: panic("binsert cache");
75: if(p0<0)
76: panic("Binsert p0<0");
77: if(s->n==0)
78: return;
79: if(incache(b, p0, p0)){
80: strinsert(&b->cache, s, p0-b->c1);
81: b->dirty=TRUE;
82: if(b->cache.n>BLOCKSIZE){
83: b->nbytes+=s->n;
84: flush(b);
85: b->cache.n-=BLOCKSIZE;
86: b->c2=b->c1+b->cache.n;
87: return;
88: }
89: }else{
90: flush(b);
91: if(s->n>=BLOCKSIZE/2){
92: b->cache.n=0;
93: b->c1=b->c2=0;
94: Dinsert(b->disc, s->s, s->n, p0);
95: }else{
96: register m;
97: Posn minp;
98: if(b->nbytes-p0>BLOCKSIZE/2)
99: m=BLOCKSIZE/2;
100: else
101: m=b->nbytes-p0;
102: minp=p0-BLOCKSIZE/2;
103: if(minp<0)
104: minp=0;
105: m+=p0-minp;
106: strinsure(&b->cache, (ulong)m);
107: if(Dread(b->disc, b->cache.s, m, minp)!=m)
108: panic("Bread");
109: b->cache.n=m;
110: b->c1=minp;
111: b->c2=minp+m;
112: strinsert(&b->cache, s, p0-b->c1);
113: b->dirty=TRUE;
114: }
115: }
116: b->nbytes+=s->n;
117: }
118: Bdelete(b, p1, p2)
119: register Buffer *b;
120: Posn p1, p2;
121: {
122: if(p1<0 || p2<0)
123: panic("Bdelete p<0");
124: if(b->c2>b->disc->nbytes || b->c1>b->disc->nbytes)
125: panic("bdelete cache");
126: if(p1==p2)
127: return;
128: if(incache(b, p1, p2)){
129: strdelete(&b->cache, p1-b->c1, p2-b->c1);
130: b->dirty=TRUE;
131: }else{
132: flush(b);
133: Ddelete(b->disc, p1, p2);
134: b->cache.n=0;
135: b->c1=b->c2=0;
136: }
137: b->nbytes-=(p2-p1);
138: }
139: static
140: flush(b)
141: register Buffer *b;
142: {
143: if(b->dirty){
144: Dreplace(b->disc, b->c1, b->c2, b->cache.s, b->cache.n);
145: b->c2=b->c1+b->cache.n;
146: b->dirty=FALSE;
147: if(b->nbytes!=b->disc->nbytes)
148: panic("flush");
149: }
150: }
151: int hits, misses;
152: incache(b, p1, p2)
153: Buffer *b;
154: Posn p1, p2;
155: {
156: if(b->c1<=p1 && p2<=b->c1+b->cache.n)hits++; else misses++;
157: return b->c1<=p1 && p2<=b->c1+b->cache.n;
158: }
159: static
160: setcache(b, s, p0)
161: register Buffer *b;
162: String *s;
163: Posn p0;
164: {
165: strdelete(&b->cache, (long)0, (long)b->cache.n);
166: strinsert(&b->cache, s, (long)0);
167: b->c1=p0;
168: b->c2=p0+s->n;
169: b->dirty=FALSE;
170: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.