2005-02-13 19:26:14 +00:00
|
|
|
#include <u.h>
|
|
|
|
#include <libc.h>
|
|
|
|
#include <venti.h>
|
|
|
|
|
2005-02-14 19:33:42 +00:00
|
|
|
int ventilogging;
|
2005-02-13 19:26:14 +00:00
|
|
|
#define log not_the_log_library_call
|
|
|
|
|
2005-02-14 19:33:42 +00:00
|
|
|
static char Eremoved[] = "[removed]";
|
|
|
|
|
2005-02-13 19:26:14 +00:00
|
|
|
enum
|
|
|
|
{ /* defaults */
|
|
|
|
LogChunkSize = 8192,
|
|
|
|
LogSize = 65536,
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct {
|
|
|
|
QLock lk;
|
|
|
|
VtLog *hash[1024];
|
|
|
|
} vl;
|
|
|
|
|
|
|
|
static uint
|
|
|
|
hash(char *s)
|
|
|
|
{
|
|
|
|
uint h;
|
|
|
|
uchar *p;
|
|
|
|
|
|
|
|
h = 0;
|
|
|
|
for(p=(uchar*)s; *p; p++)
|
|
|
|
h = h*37 + *p;
|
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
2005-05-12 14:03:57 +00:00
|
|
|
char**
|
|
|
|
vtlognames(int *pn)
|
|
|
|
{
|
|
|
|
int i, nname, size;
|
|
|
|
VtLog *l;
|
|
|
|
char **s, *a, *e;
|
|
|
|
|
|
|
|
qlock(&vl.lk);
|
|
|
|
size = 0;
|
|
|
|
nname = 0;
|
|
|
|
for(i=0; i<nelem(vl.hash); i++)
|
|
|
|
for(l=vl.hash[i]; l; l=l->next){
|
|
|
|
nname++;
|
|
|
|
size += strlen(l->name)+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
s = vtmalloc(nname*sizeof(char*)+size);
|
|
|
|
a = (char*)(s+nname);
|
|
|
|
e = (char*)s+nname*sizeof(char*)+size;
|
|
|
|
|
|
|
|
size = 0;
|
|
|
|
nname = 0;
|
|
|
|
for(i=0; i<nelem(vl.hash); i++)
|
|
|
|
for(l=vl.hash[i]; l; l=l->next){
|
|
|
|
strcpy(a, l->name);
|
|
|
|
s[nname++] = a;
|
|
|
|
a += strlen(a)+1;
|
|
|
|
}
|
|
|
|
*pn = nname;
|
|
|
|
assert(a == e);
|
|
|
|
qunlock(&vl.lk);
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2005-02-13 19:26:14 +00:00
|
|
|
VtLog*
|
|
|
|
vtlogopen(char *name, uint size)
|
|
|
|
{
|
|
|
|
uint h;
|
|
|
|
int i, nc;
|
|
|
|
char *p;
|
|
|
|
VtLog *l, *last;
|
|
|
|
|
2005-02-14 19:33:42 +00:00
|
|
|
if(!ventilogging)
|
|
|
|
return nil;
|
|
|
|
|
2005-02-13 19:26:14 +00:00
|
|
|
h = hash(name)%nelem(vl.hash);
|
|
|
|
qlock(&vl.lk);
|
|
|
|
last = nil;
|
|
|
|
for(l=vl.hash[h]; l; last=l, l=l->next)
|
|
|
|
if(strcmp(l->name, name) == 0){
|
|
|
|
if(last){ /* move to front */
|
|
|
|
last->next = l->next;
|
|
|
|
l->next = vl.hash[h];
|
|
|
|
vl.hash[h] = l;
|
|
|
|
}
|
|
|
|
l->ref++;
|
|
|
|
qunlock(&vl.lk);
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(size == 0){
|
|
|
|
qunlock(&vl.lk);
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allocate */
|
|
|
|
nc = (size+LogChunkSize-1)/LogChunkSize;
|
|
|
|
l = vtmalloc(sizeof *l + nc*(sizeof(*l->chunk)+LogChunkSize) + strlen(name)+1);
|
|
|
|
memset(l, 0, sizeof *l);
|
|
|
|
l->chunk = (VtLogChunk*)(l+1);
|
|
|
|
l->nchunk = nc;
|
|
|
|
l->w = l->chunk;
|
|
|
|
p = (char*)(l->chunk+nc);
|
|
|
|
for(i=0; i<nc; i++){
|
|
|
|
l->chunk[i].p = p;
|
2005-02-14 19:33:42 +00:00
|
|
|
l->chunk[i].wp = p;
|
2005-02-13 19:26:14 +00:00
|
|
|
p += LogChunkSize;
|
|
|
|
l->chunk[i].ep = p;
|
|
|
|
}
|
|
|
|
strcpy(p, name);
|
|
|
|
l->name = p;
|
|
|
|
|
|
|
|
/* insert */
|
|
|
|
l->next = vl.hash[h];
|
|
|
|
vl.hash[h] = l;
|
2005-02-14 19:33:42 +00:00
|
|
|
l->ref++;
|
2005-02-13 19:26:14 +00:00
|
|
|
|
|
|
|
l->ref++;
|
|
|
|
qunlock(&vl.lk);
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vtlogclose(VtLog *l)
|
|
|
|
{
|
|
|
|
if(l == nil)
|
|
|
|
return;
|
|
|
|
|
|
|
|
qlock(&vl.lk);
|
2005-02-14 19:33:42 +00:00
|
|
|
if(--l->ref == 0){
|
|
|
|
/* must not be in hash table */
|
|
|
|
assert(l->name == Eremoved);
|
2005-02-13 19:26:14 +00:00
|
|
|
free(l);
|
2005-02-14 19:33:42 +00:00
|
|
|
}else
|
2005-02-13 19:26:14 +00:00
|
|
|
assert(l->ref > 0);
|
|
|
|
qunlock(&vl.lk);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vtlogremove(char *name)
|
|
|
|
{
|
|
|
|
uint h;
|
|
|
|
VtLog *last, *l;
|
|
|
|
|
|
|
|
h = hash(name)%nelem(vl.hash);
|
|
|
|
qlock(&vl.lk);
|
|
|
|
last = nil;
|
|
|
|
for(l=vl.hash[h]; l; last=l, l=l->next)
|
|
|
|
if(strcmp(l->name, name) == 0){
|
|
|
|
if(last)
|
|
|
|
last->next = l->next;
|
|
|
|
else
|
|
|
|
vl.hash[h] = l->next;
|
2005-02-14 19:33:42 +00:00
|
|
|
l->name = Eremoved;
|
|
|
|
l->next = nil;
|
2005-02-13 19:26:14 +00:00
|
|
|
qunlock(&vl.lk);
|
|
|
|
vtlogclose(l);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
qunlock(&vl.lk);
|
|
|
|
}
|
|
|
|
|
2005-02-14 19:33:42 +00:00
|
|
|
static int
|
|
|
|
timefmt(Fmt *fmt)
|
|
|
|
{
|
|
|
|
static uvlong t0;
|
|
|
|
uvlong t;
|
|
|
|
|
|
|
|
if(t0 == 0)
|
|
|
|
t0 = nsec();
|
|
|
|
t = nsec()-t0;
|
|
|
|
return fmtprint(fmt, "T+%d.%04d", (uint)(t/1000000000), (uint)(t%1000000000)/100000);
|
|
|
|
}
|
|
|
|
|
2005-02-13 19:26:14 +00:00
|
|
|
void
|
|
|
|
vtlogvprint(VtLog *l, char *fmt, va_list arg)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
char *p;
|
|
|
|
VtLogChunk *c;
|
2005-02-14 19:33:42 +00:00
|
|
|
static int first = 1;
|
2005-02-13 19:26:14 +00:00
|
|
|
|
|
|
|
if(l == nil)
|
|
|
|
return;
|
|
|
|
|
2005-02-14 19:33:42 +00:00
|
|
|
if(first){
|
|
|
|
fmtinstall('T', timefmt);
|
|
|
|
first = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-02-13 19:26:14 +00:00
|
|
|
qlock(&l->lk);
|
|
|
|
c = l->w;
|
|
|
|
n = c->ep - c->wp;
|
|
|
|
if(n < 512){
|
|
|
|
c++;
|
|
|
|
if(c == l->chunk+l->nchunk)
|
|
|
|
c = l->chunk;
|
|
|
|
c->wp = c->p;
|
|
|
|
l->w = c;
|
|
|
|
}
|
|
|
|
p = vseprint(c->wp, c->ep, fmt, arg);
|
|
|
|
if(p)
|
|
|
|
c->wp = p;
|
|
|
|
qunlock(&l->lk);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vtlogprint(VtLog *l, char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list arg;
|
|
|
|
|
|
|
|
if(l == nil)
|
|
|
|
return;
|
|
|
|
|
|
|
|
va_start(arg, fmt);
|
|
|
|
vtlogvprint(l, fmt, arg);
|
|
|
|
va_end(arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vtlog(char *name, char *fmt, ...)
|
|
|
|
{
|
|
|
|
VtLog *l;
|
|
|
|
va_list arg;
|
2005-02-14 19:33:42 +00:00
|
|
|
|
2005-02-13 19:26:14 +00:00
|
|
|
l = vtlogopen(name, LogSize);
|
2005-02-14 19:33:42 +00:00
|
|
|
if(l == nil)
|
|
|
|
return;
|
2005-02-13 19:26:14 +00:00
|
|
|
va_start(arg, fmt);
|
|
|
|
vtlogvprint(l, fmt, arg);
|
|
|
|
va_end(arg);
|
|
|
|
vtlogclose(l);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vtlogdump(int fd, VtLog *l)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
VtLogChunk *c;
|
|
|
|
|
|
|
|
if(l == nil)
|
|
|
|
return;
|
|
|
|
|
|
|
|
c = l->w;
|
|
|
|
for(i=0; i<l->nchunk; i++){
|
|
|
|
if(++c == l->chunk+l->nchunk)
|
|
|
|
c = l->chunk;
|
|
|
|
write(fd, c->p, c->wp-c->p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|