|
|
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.