plan9port

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

disk.c (2257B)


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