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 = 6553614 };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 nname = 0;54 for(i=0; i<nelem(vl.hash); i++)55 for(l=vl.hash[i]; l; l=l->next){56 strcpy(a, l->name);57 s[nname++] = a;58 a += strlen(a)+1;59 }60 *pn = nname;61 assert(a == e);62 qunlock(&vl.lk);64 return s;65 }67 VtLog*68 vtlogopen(char *name, uint size)69 {70 uint h;71 int i, nc;72 char *p;73 VtLog *l, *last;75 if(!ventilogging)76 return nil;78 h = hash(name)%nelem(vl.hash);79 qlock(&vl.lk);80 last = nil;81 for(l=vl.hash[h]; l; last=l, l=l->next)82 if(strcmp(l->name, name) == 0){83 if(last){ /* move to front */84 last->next = l->next;85 l->next = vl.hash[h];86 vl.hash[h] = l;87 }88 l->ref++;89 qunlock(&vl.lk);90 return l;91 }93 if(size == 0){94 qunlock(&vl.lk);95 return nil;96 }98 /* allocate */99 nc = (size+LogChunkSize-1)/LogChunkSize;100 l = vtmalloc(sizeof *l + nc*(sizeof(*l->chunk)+LogChunkSize) + strlen(name)+1);101 memset(l, 0, sizeof *l);102 l->chunk = (VtLogChunk*)(l+1);103 l->nchunk = nc;104 l->w = l->chunk;105 p = (char*)(l->chunk+nc);106 for(i=0; i<nc; i++){107 l->chunk[i].p = p;108 l->chunk[i].wp = p;109 p += LogChunkSize;110 l->chunk[i].ep = p;111 }112 strcpy(p, name);113 l->name = p;115 /* insert */116 l->next = vl.hash[h];117 vl.hash[h] = l;118 l->ref++;120 l->ref++;121 qunlock(&vl.lk);122 return l;123 }125 void126 vtlogclose(VtLog *l)127 {128 if(l == nil)129 return;131 qlock(&vl.lk);132 if(--l->ref == 0){133 /* must not be in hash table */134 assert(l->name == Eremoved);135 free(l);136 }else137 assert(l->ref > 0);138 qunlock(&vl.lk);139 }141 void142 vtlogremove(char *name)143 {144 uint h;145 VtLog *last, *l;147 h = hash(name)%nelem(vl.hash);148 qlock(&vl.lk);149 last = nil;150 for(l=vl.hash[h]; l; last=l, l=l->next)151 if(strcmp(l->name, name) == 0){152 if(last)153 last->next = l->next;154 else155 vl.hash[h] = l->next;156 l->name = Eremoved;157 l->next = nil;158 qunlock(&vl.lk);159 vtlogclose(l);160 return;161 }162 qunlock(&vl.lk);163 }165 static int166 timefmt(Fmt *fmt)167 {168 static uvlong t0;169 uvlong t;171 if(t0 == 0)172 t0 = nsec();173 t = nsec()-t0;174 return fmtprint(fmt, "T+%d.%04d", (uint)(t/1000000000), (uint)(t%1000000000)/100000);175 }177 void178 vtlogvprint(VtLog *l, char *fmt, va_list arg)179 {180 int n;181 char *p;182 VtLogChunk *c;183 static int first = 1;185 if(l == nil)186 return;188 if(first){189 fmtinstall('T', timefmt);190 first = 0;191 }194 qlock(&l->lk);195 c = l->w;196 n = c->ep - c->wp;197 if(n < 512){198 c++;199 if(c == l->chunk+l->nchunk)200 c = l->chunk;201 c->wp = c->p;202 l->w = c;203 }204 p = vseprint(c->wp, c->ep, fmt, arg);205 if(p)206 c->wp = p;207 qunlock(&l->lk);208 }210 void211 vtlogprint(VtLog *l, char *fmt, ...)212 {213 va_list arg;215 if(l == nil)216 return;218 va_start(arg, fmt);219 vtlogvprint(l, fmt, arg);220 va_end(arg);221 }223 void224 vtlog(char *name, char *fmt, ...)225 {226 VtLog *l;227 va_list arg;229 l = vtlogopen(name, LogSize);230 if(l == nil)231 return;232 va_start(arg, fmt);233 vtlogvprint(l, fmt, arg);234 va_end(arg);235 vtlogclose(l);236 }238 void239 vtlogdump(int fd, VtLog *l)240 {241 int i;242 VtLogChunk *c;244 if(l == nil)245 return;247 c = l->w;248 for(i=0; i<l->nchunk; i++){249 if(++c == l->chunk+l->nchunk)250 c = l->chunk;251 write(fd, c->p, c->wp-c->p);252 }253 }