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