Blob
1 #include <u.h>2 #include <libc.h>3 #include <venti.h>5 int ventilogging;6 #define log not_the_log_library_call8 static char Eremoved[] = "[removed]";10 enum11 { /* defaults */12 LogChunkSize = 8192,13 LogSize = 65536,14 };16 static struct {17 QLock lk;18 VtLog *hash[1024];19 } vl;21 static uint22 hash(char *s)23 {24 uint h;25 uchar *p;27 h = 0;28 for(p=(uchar*)s; *p; p++)29 h = h*37 + *p;30 return h;31 }33 VtLog*34 vtlogopen(char *name, uint size)35 {36 uint h;37 int i, nc;38 char *p;39 VtLog *l, *last;41 if(!ventilogging)42 return nil;44 h = hash(name)%nelem(vl.hash);45 qlock(&vl.lk);46 last = nil;47 for(l=vl.hash[h]; l; last=l, l=l->next)48 if(strcmp(l->name, name) == 0){49 if(last){ /* move to front */50 last->next = l->next;51 l->next = vl.hash[h];52 vl.hash[h] = l;53 }54 l->ref++;55 qunlock(&vl.lk);56 return l;57 }59 if(size == 0){60 qunlock(&vl.lk);61 return nil;62 }64 /* allocate */65 nc = (size+LogChunkSize-1)/LogChunkSize;66 l = vtmalloc(sizeof *l + nc*(sizeof(*l->chunk)+LogChunkSize) + strlen(name)+1);67 memset(l, 0, sizeof *l);68 l->chunk = (VtLogChunk*)(l+1);69 l->nchunk = nc;70 l->w = l->chunk;71 p = (char*)(l->chunk+nc);72 for(i=0; i<nc; i++){73 l->chunk[i].p = p;74 l->chunk[i].wp = p;75 p += LogChunkSize;76 l->chunk[i].ep = p;77 }78 strcpy(p, name);79 l->name = p;81 /* insert */82 l->next = vl.hash[h];83 vl.hash[h] = l;84 l->ref++;86 l->ref++;87 qunlock(&vl.lk);88 return l;89 }91 void92 vtlogclose(VtLog *l)93 {94 if(l == nil)95 return;97 qlock(&vl.lk);98 if(--l->ref == 0){99 /* must not be in hash table */100 assert(l->name == Eremoved);101 free(l);102 }else103 assert(l->ref > 0);104 qunlock(&vl.lk);105 }107 void108 vtlogremove(char *name)109 {110 uint h;111 VtLog *last, *l;113 h = hash(name)%nelem(vl.hash);114 qlock(&vl.lk);115 last = nil;116 for(l=vl.hash[h]; l; last=l, l=l->next)117 if(strcmp(l->name, name) == 0){118 if(last)119 last->next = l->next;120 else121 vl.hash[h] = l->next;122 l->name = Eremoved;123 l->next = nil;124 qunlock(&vl.lk);125 vtlogclose(l);126 return;127 }128 qunlock(&vl.lk);129 }131 static int132 timefmt(Fmt *fmt)133 {134 static uvlong t0;135 uvlong t;137 if(t0 == 0)138 t0 = nsec();139 t = nsec()-t0;140 return fmtprint(fmt, "T+%d.%04d", (uint)(t/1000000000), (uint)(t%1000000000)/100000);141 }143 void144 vtlogvprint(VtLog *l, char *fmt, va_list arg)145 {146 int n;147 char *p;148 VtLogChunk *c;149 static int first = 1;151 if(l == nil)152 return;154 if(first){155 fmtinstall('T', timefmt);156 first = 0;157 }160 qlock(&l->lk);161 c = l->w;162 n = c->ep - c->wp;163 if(n < 512){164 c++;165 if(c == l->chunk+l->nchunk)166 c = l->chunk;167 c->wp = c->p;168 l->w = c;169 }170 p = vseprint(c->wp, c->ep, fmt, arg);171 if(p)172 c->wp = p;173 qunlock(&l->lk);174 }176 void177 vtlogprint(VtLog *l, char *fmt, ...)178 {179 va_list arg;181 if(l == nil)182 return;184 va_start(arg, fmt);185 vtlogvprint(l, fmt, arg);186 va_end(arg);187 }189 void190 vtlog(char *name, char *fmt, ...)191 {192 VtLog *l;193 va_list arg;195 l = vtlogopen(name, LogSize);196 if(l == nil)197 return;198 va_start(arg, fmt);199 vtlogvprint(l, fmt, arg);200 va_end(arg);201 vtlogclose(l);202 }204 void205 vtlogdump(int fd, VtLog *l)206 {207 int i;208 VtLogChunk *c;210 if(l == nil)211 return;213 c = l->w;214 for(i=0; i<l->nchunk; i++){215 if(++c == l->chunk+l->nchunk)216 c = l->chunk;217 write(fd, c->p, c->wp-c->p);218 }219 }