Annotation of researchv9/jtools/src/sam/disc.c, revision 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.