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