|
|
1.1 ! root 1: #include "sam.h" ! 2: ! 3: /* ! 4: * Guarantee: No compaction from Dread, Dinsert, Ddelete, Dreplace ! 5: */ ! 6: static Discdesc desc[NBUFFILES]; ! 7: static bkalloc(); ! 8: static bkfree(); ! 9: static int bkread(); ! 10: static int bkwrite(); ! 11: static char tempnam[20]; ! 12: ! 13: Discdesc * ! 14: Dstart() ! 15: { ! 16: register i; ! 17: register Discdesc *dd; ! 18: register fd; ! 19: for(i=0, dd=desc; dd->fd; i++, dd++) ! 20: if(i==NBUFFILES-1) ! 21: panic("too many buffer files"); ! 22: if(tempnam[0]==0) ! 23: sprint(tempnam, "/tmp/sam%d", getpid()); ! 24: fd=creat(tempnam, 0600); ! 25: if(fd<0){ ! 26: unlink(tempnam); ! 27: fd=creat(tempnam, 0600); ! 28: } ! 29: if(fd<0 || (close(fd), fd=open(tempnam, 2))<0) ! 30: panic("can't create buffer file"); ! 31: closeonexec(fd); ! 32: unlink(tempnam); ! 33: dd->fd=fd; ! 34: return dd; ! 35: } ! 36: Dclosefd() ! 37: { ! 38: register i; ! 39: for(i=0; i<NBUFFILES; i++) ! 40: if(desc[i].fd) ! 41: close(desc[i].fd); ! 42: } ! 43: Disc * ! 44: Dopen(dd) ! 45: Discdesc *dd; ! 46: { ! 47: register Disc *d; ! 48: d=new(Disc, 1); ! 49: d->desc=dd; ! 50: return d; ! 51: } ! 52: Dclose(d) ! 53: register Disc *d; ! 54: { ! 55: register i; ! 56: for(i=d->block.nused; --i>=0; ) /* backwards because bkfree() stacks */ ! 57: bkfree(d, i); ! 58: gcfree((uchar *)d->block.ptr); ! 59: free((uchar *)d); ! 60: } ! 61: int ! 62: Dread(d, addr, n, p1) ! 63: register Disc *d; ! 64: uchar *addr; ! 65: int n; ! 66: Posn p1; ! 67: { ! 68: register i, nb, nr; ! 69: register Posn p=0, p2=p1+n; ! 70: for(i=0; i<d->block.nused; i++){ ! 71: if((p+=d->block.ptr[i].nbytes)>p1){ ! 72: p-=d->block.ptr[i].nbytes; ! 73: goto out; ! 74: } ! 75: } ! 76: if(p==p1) ! 77: return 0; /* eof */ ! 78: return -1; /* past eof */ ! 79: out: ! 80: n=0; ! 81: if(p!=p1){ /* trailing partial block */ ! 82: nb=d->block.ptr[i].nbytes; ! 83: if(p2>p+nb) ! 84: nr=nb-(p1-p); ! 85: else ! 86: nr=p2-p1; ! 87: bkread(d, addr, nr, i, (int)(p1-p)); ! 88: /* advance to next block */ ! 89: p+=nb; ! 90: addr+=nr; ! 91: n+=nr; ! 92: i++; ! 93: } ! 94: /* whole blocks */ ! 95: while(p<p2 && (nb=d->block.ptr[i].nbytes)<=p2-p){ ! 96: if(i>=d->block.nused) ! 97: return n; /* eof */ ! 98: bkread(d, addr, nb, i, 0); ! 99: p+=nb; ! 100: addr+=nb; ! 101: n+=nb; ! 102: i++; ! 103: } ! 104: if(p<p2){ /* any initial partial block left? */ ! 105: nr=p2-p; ! 106: nb=d->block.ptr[i].nbytes; ! 107: if(nr>nb) ! 108: nr=nb; /* eof */ ! 109: /* just read in the part that survives */ ! 110: bkread(d, addr, nr, i, 0); ! 111: n+=nr; ! 112: } ! 113: return n; ! 114: } ! 115: Dinsert(d, addr, n, p0) ! 116: register Disc *d; ! 117: uchar *addr; /* if null, just make space */ ! 118: int n; ! 119: Posn p0; ! 120: { ! 121: register i, nb, ni; ! 122: register Posn p=0; ! 123: uchar hold[BLOCKSIZE]; ! 124: int nhold; ! 125: for(i=0; i<d->block.nused; i++){ ! 126: if((p+=d->block.ptr[i].nbytes)>=p0){ ! 127: p-=d->block.ptr[i].nbytes; ! 128: goto out; ! 129: } ! 130: } ! 131: if(p!=p0) ! 132: panic("Dinsert"); /* beyond eof */ ! 133: out: ! 134: d->nbytes+=n; ! 135: nhold=0; ! 136: if(i<d->block.nused && (nb=d->block.ptr[i].nbytes)>p0-p){ ! 137: nhold=nb-(p0-p); ! 138: bkread(d, hold, nhold, i, (int)(p0-p)); ! 139: d->block.ptr[i].nbytes-=nhold; /* no write necessary */ ! 140: } ! 141: /* insertion point is now at end of block i (which may not exist) */ ! 142: while(n>0){ ! 143: if(i<d->block.nused && (nb=d->block.ptr[i].nbytes)<BLOCKSIZE/2){ ! 144: /* fill this block */ ! 145: if(nb+n>BLOCKSIZE) ! 146: ni=BLOCKSIZE/2-nb; ! 147: else ! 148: ni=n; ! 149: if(addr) ! 150: bkwrite(d, addr, ni, i, nb); ! 151: nb+=ni; ! 152: }else{ /* make new block */ ! 153: if(i<d->block.nused) ! 154: i++; /* put after this block, if it exists */ ! 155: bkalloc(d, i); ! 156: if(n>BLOCKSIZE) ! 157: ni=BLOCKSIZE/2; ! 158: else ! 159: ni=n; ! 160: if(addr) ! 161: bkwrite(d, addr, ni, i, 0); ! 162: nb=ni; ! 163: } ! 164: d->block.ptr[i].nbytes=nb; ! 165: if(addr) ! 166: addr+=ni; ! 167: n-=ni; ! 168: } ! 169: if(nhold){ ! 170: if(i<d->block.nused && (nb=d->block.ptr[i].nbytes)+nhold<BLOCKSIZE){ ! 171: /* fill this block */ ! 172: bkwrite(d, hold, nhold, i, nb); ! 173: nb+=nhold; ! 174: }else{ /* make new block */ ! 175: if(i<d->block.nused) ! 176: i++; /* put after this block, if it exists */ ! 177: bkalloc(d, i); ! 178: bkwrite(d, hold, nhold, i, 0); ! 179: nb=nhold; ! 180: } ! 181: d->block.ptr[i].nbytes=nb; ! 182: } ! 183: } ! 184: Ddelete(d, p1, p2) ! 185: register Disc *d; ! 186: Posn p1, p2; ! 187: { ! 188: register i, nb, nd; ! 189: register Posn p=0; ! 190: uchar buf[BLOCKSIZE]; ! 191: for(i=0; i<d->block.nused; i++){ ! 192: if((p+=d->block.ptr[i].nbytes)>p1){ ! 193: p-=d->block.ptr[i].nbytes; ! 194: goto out; ! 195: } ! 196: } ! 197: if(p1!=d->nbytes || p2!=p1) ! 198: panic("Ddelete"); ! 199: return; /* beyond eof */ ! 200: out: ! 201: d->nbytes-=p2-p1; ! 202: if(p!=p1){ /* throw away partial block */ ! 203: nb=d->block.ptr[i].nbytes; ! 204: bkread(d, buf, nb, i, 0); ! 205: if(p2>=p+nb) ! 206: nd=nb-(p1-p); ! 207: else{ ! 208: nd=p2-p1; ! 209: bcopy(buf+(p1-p)+nd, buf+nb, buf+(p1-p), 1); ! 210: } ! 211: nb-=nd; ! 212: bkwrite(d, buf, nb, i, 0); ! 213: d->block.ptr[i].nbytes=nb; ! 214: p2-=nd; ! 215: /* advance to next block */ ! 216: p+=nb; ! 217: i++; ! 218: } ! 219: /* throw away whole blocks */ ! 220: while(p<p2 && (nb=d->block.ptr[i].nbytes)<=p2-p){ ! 221: if(i>=d->block.nused) ! 222: panic("Ddelete 2"); ! 223: bkfree(d, i); ! 224: p2-=nb; ! 225: } ! 226: if(p>=p2) /* any initial partial block left to delete? */ ! 227: return; /* no */ ! 228: nd=p2-p; ! 229: nb=d->block.ptr[i].nbytes; ! 230: /* just read in the part that survives */ ! 231: bkread(d, buf, nb-=nd, i, nd); ! 232: /* a little block merging */ ! 233: if(nb<BLOCKSIZE/2 && i>0 && (nd=d->block.ptr[i-1].nbytes)<BLOCKSIZE/2){ ! 234: bcopy(buf, buf+nb, buf+nd, -1); ! 235: bkread(d, buf, nd, --i, 0); ! 236: bkfree(d, i); ! 237: nb+=nd; ! 238: } ! 239: bkwrite(d, buf, nb, i, 0); ! 240: d->block.ptr[i].nbytes=nb; ! 241: } ! 242: Dreplace(d, p1, p2, addr, n) ! 243: register Disc *d; ! 244: Posn p1, p2; ! 245: uchar *addr; ! 246: int n; ! 247: { ! 248: register i, nb, nr; ! 249: register Posn p=0; ! 250: uchar buf[BLOCKSIZE]; ! 251: if(p2-p1>n) ! 252: Ddelete(d, p1+n, p2); ! 253: else if(p2-p1<n) ! 254: Dinsert(d, (uchar *)0, (int)(n-(p2-p1)), p2); ! 255: p2=p1+n; ! 256: /* they're now conformal; replace in place */ ! 257: for(i=0; i<d->block.nused; i++){ ! 258: if((p+=d->block.ptr[i].nbytes)>p1){ ! 259: p-=d->block.ptr[i].nbytes; ! 260: goto out; ! 261: } ! 262: } ! 263: panic("Dreplace"); ! 264: out: ! 265: if(p!=p1){ /* trailing partial block */ ! 266: nb=d->block.ptr[i].nbytes; ! 267: bkread(d, buf, nb, i, 0); ! 268: if(p2>p+nb) ! 269: nr=nb-(p1-p); ! 270: else ! 271: nr=p2-p1; ! 272: bcopy(addr, addr+nr, buf+p1-p, 1); ! 273: bkwrite(d, buf, nb, i, 0); ! 274: /* advance to next block */ ! 275: p+=nb; ! 276: addr+=nr; ! 277: i++; ! 278: } ! 279: /* whole blocks */ ! 280: while(p<p2 && (nb=d->block.ptr[i].nbytes)<=p2-p){ ! 281: if(i>=d->block.nused) ! 282: panic("Dreplace 2"); ! 283: bkwrite(d, addr, nb, i, 0); ! 284: p+=nb; ! 285: addr+=nb; ! 286: i++; ! 287: } ! 288: if(p<p2){ /* any initial partial block left? */ ! 289: nr=p2-p; ! 290: nb=d->block.ptr[i].nbytes; ! 291: /* just read in the part that survives */ ! 292: bkread(d, buf+nr, nb-nr, i, nr); ! 293: bcopy(addr, addr+nr, buf, 1); ! 294: bkwrite(d, buf, nb, i, 0); ! 295: } ! 296: } ! 297: static int ! 298: bkread(d, loc, n, bk, off) ! 299: Disc *d; ! 300: uchar *loc; ! 301: int n; ! 302: int bk; ! 303: int off; ! 304: { ! 305: Lseek(d->desc->fd, BLOCKSIZE*(long)d->block.ptr[bk].bnum+off, 0); ! 306: return Read(d->desc->fd, loc, n); ! 307: } ! 308: static int ! 309: bkwrite(d, loc, n, bk, off) ! 310: Disc *d; ! 311: uchar *loc; ! 312: int n; ! 313: int bk; ! 314: int off; ! 315: { ! 316: Lseek(d->desc->fd, BLOCKSIZE*(long)d->block.ptr[bk].bnum+off, 0); ! 317: return Write(d->desc->fd, loc, n); ! 318: } ! 319: static ! 320: bkalloc(d, n) ! 321: register Disc *d; ! 322: int n; ! 323: { ! 324: register Discdesc *dd=d->desc; ! 325: register bnum; ! 326: if(dd->free.nused) ! 327: bnum=dd->free.ptr[--dd->free.nused]; ! 328: else ! 329: bnum=dd->nbk++; ! 330: nocompact(); ! 331: inslist((List *)&d->block, n, 0L); ! 332: compactok(); ! 333: d->block.ptr[n].bnum=bnum; ! 334: } ! 335: static ! 336: bkfree(d, n) ! 337: Disc *d; ! 338: int n; ! 339: { ! 340: Discdesc *dd=d->desc; ! 341: nocompact(); ! 342: inslist(&dd->free, dd->free.nused, (long)d->block.ptr[n].bnum); ! 343: compactok(); ! 344: dellist((List *)&d->block, n); ! 345: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.