diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/libventi/log.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libventi/log.c')
-rwxr-xr-x | sys/src/libventi/log.c | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/sys/src/libventi/log.c b/sys/src/libventi/log.c new file mode 100755 index 000000000..80a1d4787 --- /dev/null +++ b/sys/src/libventi/log.c @@ -0,0 +1,256 @@ +#include <u.h> +#include <libc.h> +#include <venti.h> + +char *VtServerLog = "libventi/server"; + +int ventilogging; +#define log not_the_log_library_call + +static char Eremoved[] = "[removed]"; + +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; +} + +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; + + 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; +} + +VtLog* +vtlogopen(char *name, uint size) +{ + uint h; + int i, nc; + char *p; + VtLog *l, *last; + + if(!ventilogging) + return nil; + + 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; + l->chunk[i].wp = p; + p += LogChunkSize; + l->chunk[i].ep = p; + } + strcpy(p, name); + l->name = p; + + /* insert */ + l->next = vl.hash[h]; + vl.hash[h] = l; + l->ref++; + + l->ref++; + qunlock(&vl.lk); + return l; +} + +void +vtlogclose(VtLog *l) +{ + if(l == nil) + return; + + qlock(&vl.lk); + if(--l->ref == 0){ + /* must not be in hash table */ + assert(l->name == Eremoved); + free(l); + }else + 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; + l->name = Eremoved; + l->next = nil; + qunlock(&vl.lk); + vtlogclose(l); + return; + } + qunlock(&vl.lk); +} + +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); +} + +void +vtlogvprint(VtLog *l, char *fmt, va_list arg) +{ + int n; + char *p; + VtLogChunk *c; + static int first = 1; + + if(l == nil) + return; + + if(first){ + fmtinstall('T', timefmt); + first = 0; + } + + + 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; + + l = vtlogopen(name, LogSize); + if(l == nil) + return; + 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); + } +} + |