Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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