summaryrefslogtreecommitdiff
path: root/sys/src/libventi/log.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/libventi/log.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libventi/log.c')
-rwxr-xr-xsys/src/libventi/log.c256
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);
+ }
+}
+