Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <venti.h>
5 int ventilogging;
6 #define log not_the_log_library_call
8 static char Eremoved[] = "[removed]";
10 enum
11 { /* defaults */
12 LogChunkSize = 8192,
13 LogSize = 65536,
14 };
16 static struct {
17 QLock lk;
18 VtLog *hash[1024];
19 } vl;
21 static uint
22 hash(char *s)
23 {
24 uint h;
25 uchar *p;
27 h = 0;
28 for(p=(uchar*)s; *p; p++)
29 h = h*37 + *p;
30 return h;
31 }
33 VtLog*
34 vtlogopen(char *name, uint size)
35 {
36 uint h;
37 int i, nc;
38 char *p;
39 VtLog *l, *last;
41 if(!ventilogging)
42 return nil;
44 h = hash(name)%nelem(vl.hash);
45 qlock(&vl.lk);
46 last = nil;
47 for(l=vl.hash[h]; l; last=l, l=l->next)
48 if(strcmp(l->name, name) == 0){
49 if(last){ /* move to front */
50 last->next = l->next;
51 l->next = vl.hash[h];
52 vl.hash[h] = l;
53 }
54 l->ref++;
55 qunlock(&vl.lk);
56 return l;
57 }
59 if(size == 0){
60 qunlock(&vl.lk);
61 return nil;
62 }
64 /* allocate */
65 nc = (size+LogChunkSize-1)/LogChunkSize;
66 l = vtmalloc(sizeof *l + nc*(sizeof(*l->chunk)+LogChunkSize) + strlen(name)+1);
67 memset(l, 0, sizeof *l);
68 l->chunk = (VtLogChunk*)(l+1);
69 l->nchunk = nc;
70 l->w = l->chunk;
71 p = (char*)(l->chunk+nc);
72 for(i=0; i<nc; i++){
73 l->chunk[i].p = p;
74 l->chunk[i].wp = p;
75 p += LogChunkSize;
76 l->chunk[i].ep = p;
77 }
78 strcpy(p, name);
79 l->name = p;
81 /* insert */
82 l->next = vl.hash[h];
83 vl.hash[h] = l;
84 l->ref++;
86 l->ref++;
87 qunlock(&vl.lk);
88 return l;
89 }
91 void
92 vtlogclose(VtLog *l)
93 {
94 if(l == nil)
95 return;
97 qlock(&vl.lk);
98 if(--l->ref == 0){
99 /* must not be in hash table */
100 assert(l->name == Eremoved);
101 free(l);
102 }else
103 assert(l->ref > 0);
104 qunlock(&vl.lk);
107 void
108 vtlogremove(char *name)
110 uint h;
111 VtLog *last, *l;
113 h = hash(name)%nelem(vl.hash);
114 qlock(&vl.lk);
115 last = nil;
116 for(l=vl.hash[h]; l; last=l, l=l->next)
117 if(strcmp(l->name, name) == 0){
118 if(last)
119 last->next = l->next;
120 else
121 vl.hash[h] = l->next;
122 l->name = Eremoved;
123 l->next = nil;
124 qunlock(&vl.lk);
125 vtlogclose(l);
126 return;
128 qunlock(&vl.lk);
131 static int
132 timefmt(Fmt *fmt)
134 static uvlong t0;
135 uvlong t;
137 if(t0 == 0)
138 t0 = nsec();
139 t = nsec()-t0;
140 return fmtprint(fmt, "T+%d.%04d", (uint)(t/1000000000), (uint)(t%1000000000)/100000);
143 void
144 vtlogvprint(VtLog *l, char *fmt, va_list arg)
146 int n;
147 char *p;
148 VtLogChunk *c;
149 static int first = 1;
151 if(l == nil)
152 return;
154 if(first){
155 fmtinstall('T', timefmt);
156 first = 0;
160 qlock(&l->lk);
161 c = l->w;
162 n = c->ep - c->wp;
163 if(n < 512){
164 c++;
165 if(c == l->chunk+l->nchunk)
166 c = l->chunk;
167 c->wp = c->p;
168 l->w = c;
170 p = vseprint(c->wp, c->ep, fmt, arg);
171 if(p)
172 c->wp = p;
173 qunlock(&l->lk);
176 void
177 vtlogprint(VtLog *l, char *fmt, ...)
179 va_list arg;
181 if(l == nil)
182 return;
184 va_start(arg, fmt);
185 vtlogvprint(l, fmt, arg);
186 va_end(arg);
189 void
190 vtlog(char *name, char *fmt, ...)
192 VtLog *l;
193 va_list arg;
195 l = vtlogopen(name, LogSize);
196 if(l == nil)
197 return;
198 va_start(arg, fmt);
199 vtlogvprint(l, fmt, arg);
200 va_end(arg);
201 vtlogclose(l);
204 void
205 vtlogdump(int fd, VtLog *l)
207 int i;
208 VtLogChunk *c;
210 if(l == nil)
211 return;
213 c = l->w;
214 for(i=0; i<l->nchunk; i++){
215 if(++c == l->chunk+l->nchunk)
216 c = l->chunk;
217 write(fd, c->p, c->wp-c->p);