plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

disk.c (2124B)


      1 #include "sam.h"
      2 
      3 static	Block	*blist;
      4 
      5 #if 0
      6 static int
      7 tempdisk(void)
      8 {
      9 	char buf[128];
     10 	int i, fd;
     11 
     12 	snprint(buf, sizeof buf, "/tmp/X%d.%.4ssam", getpid(), getuser());
     13 	for(i='A'; i<='Z'; i++){
     14 		buf[5] = i;
     15 		if(access(buf, AEXIST) == 0)
     16 			continue;
     17 		fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
     18 		if(fd >= 0)
     19 			return fd;
     20 	}
     21 	return -1;
     22 }
     23 #else
     24 extern int tempdisk(void);
     25 #endif
     26 
     27 Disk*
     28 diskinit(void)
     29 {
     30 	Disk *d;
     31 
     32 	d = emalloc(sizeof(Disk));
     33 	d->fd = tempdisk();
     34 	if(d->fd < 0){
     35 		fprint(2, "sam: can't create temp file: %r\n");
     36 		exits("diskinit");
     37 	}
     38 	return d;
     39 }
     40 
     41 static
     42 uint
     43 ntosize(uint n, uint *ip)
     44 {
     45 	uint size;
     46 
     47 	if(n > Maxblock)
     48 		panic("internal error: ntosize");
     49 	size = n;
     50 	if(size & (Blockincr-1))
     51 		size += Blockincr - (size & (Blockincr-1));
     52 	/* last bucket holds blocks of exactly Maxblock */
     53 	if(ip)
     54 		*ip = size/Blockincr;
     55 	return size * sizeof(Rune);
     56 }
     57 
     58 Block*
     59 disknewblock(Disk *d, uint n)
     60 {
     61 	uint i, j, size;
     62 	Block *b;
     63 
     64 	size = ntosize(n, &i);
     65 	b = d->free[i];
     66 	if(b)
     67 		d->free[i] = b->u.next;
     68 	else{
     69 		/* allocate in chunks to reduce malloc overhead */
     70 		if(blist == nil){
     71 			blist = emalloc(100*sizeof(Block));
     72 			for(j=0; j<100-1; j++)
     73 				blist[j].u.next = &blist[j+1];
     74 		}
     75 		b = blist;
     76 		blist = b->u.next;
     77 		b->addr = d->addr;
     78 		if(d->addr+size < d->addr){
     79 			panic("temp file overflow");
     80 		}
     81 		d->addr += size;
     82 	}
     83 	b->u.n = n;
     84 	return b;
     85 }
     86 
     87 void
     88 diskrelease(Disk *d, Block *b)
     89 {
     90 	uint i;
     91 
     92 	ntosize(b->u.n, &i);
     93 	b->u.next = d->free[i];
     94 	d->free[i] = b;
     95 }
     96 
     97 void
     98 diskwrite(Disk *d, Block **bp, Rune *r, uint n)
     99 {
    100 	int size, nsize;
    101 	Block *b;
    102 
    103 	b = *bp;
    104 	size = ntosize(b->u.n, nil);
    105 	nsize = ntosize(n, nil);
    106 	if(size != nsize){
    107 		diskrelease(d, b);
    108 		b = disknewblock(d, n);
    109 		*bp = b;
    110 	}
    111 	if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
    112 		panic("write error to temp file");
    113 	b->u.n = n;
    114 }
    115 
    116 void
    117 diskread(Disk *d, Block *b, Rune *r, uint n)
    118 {
    119 	if(n > b->u.n)
    120 		panic("internal error: diskread");
    121 
    122 	ntosize(b->u.n, nil);	/* called only for sanity check on Maxblock */
    123 	if(pread(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
    124 		panic("read error from temp file");
    125 }