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
hash(char * s)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**
vtlognames(int * pn)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*
vtlogopen(char * name,uint size)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
vtlogclose(VtLog * l)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
vtlogremove(char * name)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
vtlogvprint(VtLog * l,char * fmt,va_list arg)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
vtlogprint(VtLog * l,char * fmt,...)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
vtlog(char * name,char * fmt,...)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
vtlogdump(int fd,VtLog * l)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 }
235