Annotation of researchv9/jtools/src/sam/disc.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.