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