|
|
researchv9-SUN3(old)
#include "sam.h"
/*
* Guarantee: No compaction from Dread, Dinsert, Ddelete, Dreplace
*/
static Discdesc desc[NBUFFILES];
static bkalloc();
static bkfree();
static int bkread();
static int bkwrite();
static char tempnam[20];
Discdesc *
Dstart()
{
register i;
register Discdesc *dd;
register fd;
for(i=0, dd=desc; dd->fd; i++, dd++)
if(i==NBUFFILES-1)
panic("too many buffer files");
if(tempnam[0]==0)
sprint(tempnam, "/tmp/sam%d", getpid());
fd=creat(tempnam, 0600);
if(fd<0){
unlink(tempnam);
fd=creat(tempnam, 0600);
}
if(fd<0 || (close(fd), fd=open(tempnam, 2))<0)
panic("can't create buffer file");
closeonexec(fd);
unlink(tempnam);
dd->fd=fd;
return dd;
}
Dclosefd()
{
register i;
for(i=0; i<NBUFFILES; i++)
if(desc[i].fd)
close(desc[i].fd);
}
Disc *
Dopen(dd)
Discdesc *dd;
{
register Disc *d;
d=new(Disc, 1);
d->desc=dd;
return d;
}
Dclose(d)
register Disc *d;
{
register i;
for(i=d->block.nused; --i>=0; ) /* backwards because bkfree() stacks */
bkfree(d, i);
gcfree((uchar *)d->block.ptr);
free((uchar *)d);
}
int
Dread(d, addr, n, p1)
register Disc *d;
uchar *addr;
int n;
Posn p1;
{
register i, nb, nr;
register Posn p=0, p2=p1+n;
for(i=0; i<d->block.nused; i++){
if((p+=d->block.ptr[i].nbytes)>p1){
p-=d->block.ptr[i].nbytes;
goto out;
}
}
if(p==p1)
return 0; /* eof */
return -1; /* past eof */
out:
n=0;
if(p!=p1){ /* trailing partial block */
nb=d->block.ptr[i].nbytes;
if(p2>p+nb)
nr=nb-(p1-p);
else
nr=p2-p1;
bkread(d, addr, nr, i, (int)(p1-p));
/* advance to next block */
p+=nb;
addr+=nr;
n+=nr;
i++;
}
/* whole blocks */
while(p<p2 && (nb=d->block.ptr[i].nbytes)<=p2-p){
if(i>=d->block.nused)
return n; /* eof */
bkread(d, addr, nb, i, 0);
p+=nb;
addr+=nb;
n+=nb;
i++;
}
if(p<p2){ /* any initial partial block left? */
nr=p2-p;
nb=d->block.ptr[i].nbytes;
if(nr>nb)
nr=nb; /* eof */
/* just read in the part that survives */
bkread(d, addr, nr, i, 0);
n+=nr;
}
return n;
}
Dinsert(d, addr, n, p0)
register Disc *d;
uchar *addr; /* if null, just make space */
int n;
Posn p0;
{
register i, nb, ni;
register Posn p=0;
uchar hold[BLOCKSIZE];
int nhold;
for(i=0; i<d->block.nused; i++){
if((p+=d->block.ptr[i].nbytes)>=p0){
p-=d->block.ptr[i].nbytes;
goto out;
}
}
if(p!=p0)
panic("Dinsert"); /* beyond eof */
out:
d->nbytes+=n;
nhold=0;
if(i<d->block.nused && (nb=d->block.ptr[i].nbytes)>p0-p){
nhold=nb-(p0-p);
bkread(d, hold, nhold, i, (int)(p0-p));
d->block.ptr[i].nbytes-=nhold; /* no write necessary */
}
/* insertion point is now at end of block i (which may not exist) */
while(n>0){
if(i<d->block.nused && (nb=d->block.ptr[i].nbytes)<BLOCKSIZE/2){
/* fill this block */
if(nb+n>BLOCKSIZE)
ni=BLOCKSIZE/2-nb;
else
ni=n;
if(addr)
bkwrite(d, addr, ni, i, nb);
nb+=ni;
}else{ /* make new block */
if(i<d->block.nused)
i++; /* put after this block, if it exists */
bkalloc(d, i);
if(n>BLOCKSIZE)
ni=BLOCKSIZE/2;
else
ni=n;
if(addr)
bkwrite(d, addr, ni, i, 0);
nb=ni;
}
d->block.ptr[i].nbytes=nb;
if(addr)
addr+=ni;
n-=ni;
}
if(nhold){
if(i<d->block.nused && (nb=d->block.ptr[i].nbytes)+nhold<BLOCKSIZE){
/* fill this block */
bkwrite(d, hold, nhold, i, nb);
nb+=nhold;
}else{ /* make new block */
if(i<d->block.nused)
i++; /* put after this block, if it exists */
bkalloc(d, i);
bkwrite(d, hold, nhold, i, 0);
nb=nhold;
}
d->block.ptr[i].nbytes=nb;
}
}
Ddelete(d, p1, p2)
register Disc *d;
Posn p1, p2;
{
register i, nb, nd;
register Posn p=0;
uchar buf[BLOCKSIZE];
for(i=0; i<d->block.nused; i++){
if((p+=d->block.ptr[i].nbytes)>p1){
p-=d->block.ptr[i].nbytes;
goto out;
}
}
if(p1!=d->nbytes || p2!=p1)
panic("Ddelete");
return; /* beyond eof */
out:
d->nbytes-=p2-p1;
if(p!=p1){ /* throw away partial block */
nb=d->block.ptr[i].nbytes;
bkread(d, buf, nb, i, 0);
if(p2>=p+nb)
nd=nb-(p1-p);
else{
nd=p2-p1;
bcopy(buf+(p1-p)+nd, buf+nb, buf+(p1-p), 1);
}
nb-=nd;
bkwrite(d, buf, nb, i, 0);
d->block.ptr[i].nbytes=nb;
p2-=nd;
/* advance to next block */
p+=nb;
i++;
}
/* throw away whole blocks */
while(p<p2 && (nb=d->block.ptr[i].nbytes)<=p2-p){
if(i>=d->block.nused)
panic("Ddelete 2");
bkfree(d, i);
p2-=nb;
}
if(p>=p2) /* any initial partial block left to delete? */
return; /* no */
nd=p2-p;
nb=d->block.ptr[i].nbytes;
/* just read in the part that survives */
bkread(d, buf, nb-=nd, i, nd);
/* a little block merging */
if(nb<BLOCKSIZE/2 && i>0 && (nd=d->block.ptr[i-1].nbytes)<BLOCKSIZE/2){
bcopy(buf, buf+nb, buf+nd, -1);
bkread(d, buf, nd, --i, 0);
bkfree(d, i);
nb+=nd;
}
bkwrite(d, buf, nb, i, 0);
d->block.ptr[i].nbytes=nb;
}
Dreplace(d, p1, p2, addr, n)
register Disc *d;
Posn p1, p2;
uchar *addr;
int n;
{
register i, nb, nr;
register Posn p=0;
uchar buf[BLOCKSIZE];
if(p2-p1>n)
Ddelete(d, p1+n, p2);
else if(p2-p1<n)
Dinsert(d, (uchar *)0, (int)(n-(p2-p1)), p2);
p2=p1+n;
/* they're now conformal; replace in place */
for(i=0; i<d->block.nused; i++){
if((p+=d->block.ptr[i].nbytes)>p1){
p-=d->block.ptr[i].nbytes;
goto out;
}
}
panic("Dreplace");
out:
if(p!=p1){ /* trailing partial block */
nb=d->block.ptr[i].nbytes;
bkread(d, buf, nb, i, 0);
if(p2>p+nb)
nr=nb-(p1-p);
else
nr=p2-p1;
bcopy(addr, addr+nr, buf+p1-p, 1);
bkwrite(d, buf, nb, i, 0);
/* advance to next block */
p+=nb;
addr+=nr;
i++;
}
/* whole blocks */
while(p<p2 && (nb=d->block.ptr[i].nbytes)<=p2-p){
if(i>=d->block.nused)
panic("Dreplace 2");
bkwrite(d, addr, nb, i, 0);
p+=nb;
addr+=nb;
i++;
}
if(p<p2){ /* any initial partial block left? */
nr=p2-p;
nb=d->block.ptr[i].nbytes;
/* just read in the part that survives */
bkread(d, buf+nr, nb-nr, i, nr);
bcopy(addr, addr+nr, buf, 1);
bkwrite(d, buf, nb, i, 0);
}
}
static int
bkread(d, loc, n, bk, off)
Disc *d;
uchar *loc;
int n;
int bk;
int off;
{
Lseek(d->desc->fd, BLOCKSIZE*(long)d->block.ptr[bk].bnum+off, 0);
return Read(d->desc->fd, loc, n);
}
static int
bkwrite(d, loc, n, bk, off)
Disc *d;
uchar *loc;
int n;
int bk;
int off;
{
Lseek(d->desc->fd, BLOCKSIZE*(long)d->block.ptr[bk].bnum+off, 0);
return Write(d->desc->fd, loc, n);
}
static
bkalloc(d, n)
register Disc *d;
int n;
{
register Discdesc *dd=d->desc;
register bnum;
if(dd->free.nused)
bnum=dd->free.ptr[--dd->free.nused];
else
bnum=dd->nbk++;
nocompact();
inslist((List *)&d->block, n, 0L);
compactok();
d->block.ptr[n].bnum=bnum;
}
static
bkfree(d, n)
Disc *d;
int n;
{
Discdesc *dd=d->desc;
nocompact();
inslist(&dd->free, dd->free.nused, (long)d->block.ptr[n].bnum);
compactok();
dellist((List *)&d->block, n);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.