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 char**34 vtlognames(int *pn)35 {36 int i, nname, size;37 VtLog *l;38 char **s, *a, *e;40 qlock(&vl.lk);41 size = 0;42 nname = 0;43 for(i=0; i<nelem(vl.hash); i++)44 for(l=vl.hash[i]; l; l=l->next){45 nname++;46 size += strlen(l->name)+1;47 }49 s = vtmalloc(nname*sizeof(char*)+size);50 a = (char*)(s+nname);51 e = (char*)s+nname*sizeof(char*)+size;53 size = 0;54 nname = 0;55 for(i=0; i<nelem(vl.hash); i++)56 for(l=vl.hash[i]; l; l=l->next){57 strcpy(a, l->name);58 s[nname++] = a;59 a += strlen(a)+1;60 }61 *pn = nname;62 assert(a == e);63 qunlock(&vl.lk);65 return s;66 }68 VtLog*69 vtlogopen(char *name, uint size)70 {71 uint h;72 int i, nc;73 char *p;74 VtLog *l, *last;76 if(!ventilogging)77 return nil;79 h = hash(name)%nelem(vl.hash);80 qlock(&vl.lk);81 last = nil;82 for(l=vl.hash[h]; l; last=l, l=l->next)83 if(strcmp(l->name, name) == 0){84 if(last){ /* move to front */85 last->next = l->next;86 l->next = vl.hash[h];87 vl.hash[h] = l;88 }89 l->ref++;90 qunlock(&vl.lk);91 return l;92 }94 if(size == 0){95 qunlock(&vl.lk);96 return nil;97 }99 /* allocate */100 nc = (size+LogChunkSize-1)/LogChunkSize;101 l = vtmalloc(sizeof *l + nc*(sizeof(*l->chunk)+LogChunkSize) + strlen(name)+1);102 memset(l, 0, sizeof *l);103 l->chunk = (VtLogChunk*)(l+1);104 l->nchunk = nc;105 l->w = l->chunk;106 p = (char*)(l->chunk+nc);107 for(i=0; i<nc; i++){108 l->chunk[i].p = p;109 l->chunk[i].wp = p;110 p += LogChunkSize;111 l->chunk[i].ep = p;112 }113 strcpy(p, name);114 l->name = p;116 /* insert */117 l->next = vl.hash[h];118 vl.hash[h] = l;119 l->ref++;121 l->ref++;122 qunlock(&vl.lk);123 return l;124 }126 void127 vtlogclose(VtLog *l)128 {129 if(l == nil)130 return;132 qlock(&vl.lk);133 if(--l->ref == 0){134 /* must not be in hash table */135 assert(l->name == Eremoved);136 free(l);137 }else138 assert(l->ref > 0);139 qunlock(&vl.lk);140 }142 void143 vtlogremove(char *name)144 {145 uint h;146 VtLog *last, *l;148 h = hash(name)%nelem(vl.hash);149 qlock(&vl.lk);150 last = nil;151 for(l=vl.hash[h]; l; last=l, l=l->next)152 if(strcmp(l->name, name) == 0){153 if(last)154 last->next = l->next;155 else156 vl.hash[h] = l->next;157 l->name = Eremoved;158 l->next = nil;159 qunlock(&vl.lk);160 vtlogclose(l);161 return;162 }163 qunlock(&vl.lk);164 }166 static int167 timefmt(Fmt *fmt)168 {169 static uvlong t0;170 uvlong t;172 if(t0 == 0)173 t0 = nsec();174 t = nsec()-t0;175 return fmtprint(fmt, "T+%d.%04d", (uint)(t/1000000000), (uint)(t%1000000000)/100000);176 }178 void179 vtlogvprint(VtLog *l, char *fmt, va_list arg)180 {181 int n;182 char *p;183 VtLogChunk *c;184 static int first = 1;186 if(l == nil)187 return;189 if(first){190 fmtinstall('T', timefmt);191 first = 0;192 }195 qlock(&l->lk);196 c = l->w;197 n = c->ep - c->wp;198 if(n < 512){199 c++;200 if(c == l->chunk+l->nchunk)201 c = l->chunk;202 c->wp = c->p;203 l->w = c;204 }205 p = vseprint(c->wp, c->ep, fmt, arg);206 if(p)207 c->wp = p;208 qunlock(&l->lk);209 }211 void212 vtlogprint(VtLog *l, char *fmt, ...)213 {214 va_list arg;216 if(l == nil)217 return;219 va_start(arg, fmt);220 vtlogvprint(l, fmt, arg);221 va_end(arg);222 }224 void225 vtlog(char *name, char *fmt, ...)226 {227 VtLog *l;228 va_list arg;230 l = vtlogopen(name, LogSize);231 if(l == nil)232 return;233 va_start(arg, fmt);234 vtlogvprint(l, fmt, arg);235 va_end(arg);236 vtlogclose(l);237 }239 void240 vtlogdump(int fd, VtLog *l)241 {242 int i;243 VtLogChunk *c;245 if(l == nil)246 return;248 c = l->w;249 for(i=0; i<l->nchunk; i++){250 if(++c == l->chunk+l->nchunk)251 c = l->chunk;252 write(fd, c->p, c->wp-c->p);253 }254 }