plan9port

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

log.c (3410B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <venti.h>
      4 
      5 int ventilogging;
      6 #define log	not_the_log_library_call
      7 
      8 static char Eremoved[] = "[removed]";
      9 
     10 enum
     11 {	/* defaults */
     12 	LogChunkSize = 8192,
     13 	LogSize = 65536
     14 };
     15 
     16 static struct {
     17 	QLock lk;
     18 	VtLog *hash[1024];
     19 } vl;
     20 
     21 static uint
     22 hash(char *s)
     23 {
     24 	uint h;
     25 	uchar *p;
     26 
     27 	h = 0;
     28 	for(p=(uchar*)s; *p; p++)
     29 		h = h*37 + *p;
     30 	return h;
     31 }
     32 
     33 char**
     34 vtlognames(int *pn)
     35 {
     36 	int i, nname, size;
     37 	VtLog *l;
     38 	char **s, *a, *e;
     39 
     40 	qlock(&vl.lk);
     41 	size = 0;
     42 	nname = 0;
     43 	for(i=0; i<nelem(vl.hash); i++)
     44 	for(l=vl.hash[i]; l; l=l->next){
     45 		nname++;
     46 		size += strlen(l->name)+1;
     47 	}
     48 
     49 	s = vtmalloc(nname*sizeof(char*)+size);
     50 	a = (char*)(s+nname);
     51 	e = (char*)s+nname*sizeof(char*)+size;
     52 
     53 	nname = 0;
     54 	for(i=0; i<nelem(vl.hash); i++)
     55 	for(l=vl.hash[i]; l; l=l->next){
     56 		strcpy(a, l->name);
     57 		s[nname++] = a;
     58 		a += strlen(a)+1;
     59 	}
     60 	*pn = nname;
     61 	assert(a == e);
     62 	qunlock(&vl.lk);
     63 
     64 	return s;
     65 }
     66 
     67 VtLog*
     68 vtlogopen(char *name, uint size)
     69 {
     70 	uint h;
     71 	int i, nc;
     72 	char *p;
     73 	VtLog *l, *last;
     74 
     75 	if(!ventilogging)
     76 		return nil;
     77 
     78 	h = hash(name)%nelem(vl.hash);
     79 	qlock(&vl.lk);
     80 	last = nil;
     81 	for(l=vl.hash[h]; l; last=l, l=l->next)
     82 		if(strcmp(l->name, name) == 0){
     83 			if(last){	/* move to front */
     84 				last->next = l->next;
     85 				l->next = vl.hash[h];
     86 				vl.hash[h] = l;
     87 			}
     88 			l->ref++;
     89 			qunlock(&vl.lk);
     90 			return l;
     91 		}
     92 
     93 	if(size == 0){
     94 		qunlock(&vl.lk);
     95 		return nil;
     96 	}
     97 
     98 	/* allocate */
     99 	nc = (size+LogChunkSize-1)/LogChunkSize;
    100 	l = vtmalloc(sizeof *l + nc*(sizeof(*l->chunk)+LogChunkSize) + strlen(name)+1);
    101 	memset(l, 0, sizeof *l);
    102 	l->chunk = (VtLogChunk*)(l+1);
    103 	l->nchunk = nc;
    104 	l->w = l->chunk;
    105 	p = (char*)(l->chunk+nc);
    106 	for(i=0; i<nc; i++){
    107 		l->chunk[i].p = p;
    108 		l->chunk[i].wp = p;
    109 		p += LogChunkSize;
    110 		l->chunk[i].ep = p;
    111 	}
    112 	strcpy(p, name);
    113 	l->name = p;
    114 
    115 	/* insert */
    116 	l->next = vl.hash[h];
    117 	vl.hash[h] = l;
    118 	l->ref++;
    119 
    120 	l->ref++;
    121 	qunlock(&vl.lk);
    122 	return l;
    123 }
    124 
    125 void
    126 vtlogclose(VtLog *l)
    127 {
    128 	if(l == nil)
    129 		return;
    130 
    131 	qlock(&vl.lk);
    132 	if(--l->ref == 0){
    133 		/* must not be in hash table */
    134 		assert(l->name == Eremoved);
    135 		free(l);
    136 	}else
    137 		assert(l->ref > 0);
    138 	qunlock(&vl.lk);
    139 }
    140 
    141 void
    142 vtlogremove(char *name)
    143 {
    144 	uint h;
    145 	VtLog *last, *l;
    146 
    147 	h = hash(name)%nelem(vl.hash);
    148 	qlock(&vl.lk);
    149 	last = nil;
    150 	for(l=vl.hash[h]; l; last=l, l=l->next)
    151 		if(strcmp(l->name, name) == 0){
    152 			if(last)
    153 				last->next = l->next;
    154 			else
    155 				vl.hash[h] = l->next;
    156 			l->name = Eremoved;
    157 			l->next = nil;
    158 			qunlock(&vl.lk);
    159 			vtlogclose(l);
    160 			return;
    161 		}
    162 	qunlock(&vl.lk);
    163 }
    164 
    165 void
    166 vtlogvprint(VtLog *l, char *fmt, va_list arg)
    167 {
    168 	int n;
    169 	char *p;
    170 	VtLogChunk *c;
    171 
    172 	if(l == nil)
    173 		return;
    174 
    175 	qlock(&l->lk);
    176 	c = l->w;
    177 	n = c->ep - c->wp;
    178 	if(n < 512){
    179 		c++;
    180 		if(c == l->chunk+l->nchunk)
    181 			c = l->chunk;
    182 		c->wp = c->p;
    183 		l->w = c;
    184 	}
    185 	p = vseprint(c->wp, c->ep, fmt, arg);
    186 	if(p)
    187 		c->wp = p;
    188 	qunlock(&l->lk);
    189 }
    190 
    191 void
    192 vtlogprint(VtLog *l, char *fmt, ...)
    193 {
    194 	va_list arg;
    195 
    196 	if(l == nil)
    197 		return;
    198 
    199 	va_start(arg, fmt);
    200 	vtlogvprint(l, fmt, arg);
    201 	va_end(arg);
    202 }
    203 
    204 void
    205 vtlog(char *name, char *fmt, ...)
    206 {
    207 	VtLog *l;
    208 	va_list arg;
    209 
    210 	l = vtlogopen(name, LogSize);
    211 	if(l == nil)
    212 		return;
    213 	va_start(arg, fmt);
    214 	vtlogvprint(l, fmt, arg);
    215 	va_end(arg);
    216 	vtlogclose(l);
    217 }
    218 
    219 void
    220 vtlogdump(int fd, VtLog *l)
    221 {
    222 	int i;
    223 	VtLogChunk *c;
    224 
    225 	if(l == nil)
    226 		return;
    227 
    228 	c = l->w;
    229 	for(i=0; i<l->nchunk; i++){
    230 		if(++c == l->chunk+l->nchunk)
    231 			c = l->chunk;
    232 		write(fd, c->p, c->wp-c->p);
    233 	}
    234 }