1 #include <u.h> 2 #include <libc.h> 3 #include <venti.h> 4 5 char *VtServerLog = "libventi/server"; 6 7 int ventilogging; 8 #define log not_the_log_library_call 9 10 static char Eremoved[] = "[removed]"; 11 12 enum 13 { /* defaults */ 14 LogChunkSize = 8192, 15 LogSize = 65536 16 }; 17 18 static struct { 19 QLock lk; 20 VtLog *hash[1024]; 21 } vl; 22 23 static uint 24 hash(char *s) 25 { 26 uint h; 27 uchar *p; 28 29 h = 0; 30 for(p=(uchar*)s; *p; p++) 31 h = h*37 + *p; 32 return h; 33 } 34 35 char** 36 vtlognames(int *pn) 37 { 38 int i, nname, size; 39 VtLog *l; 40 char **s, *a, *e; 41 42 qlock(&vl.lk); 43 size = 0; 44 nname = 0; 45 for(i=0; i<nelem(vl.hash); i++) 46 for(l=vl.hash[i]; l; l=l->next){ 47 nname++; 48 size += strlen(l->name)+1; 49 } 50 51 s = vtmalloc(nname*sizeof(char*)+size); 52 a = (char*)(s+nname); 53 e = (char*)s+nname*sizeof(char*)+size; 54 55 nname = 0; 56 for(i=0; i<nelem(vl.hash); i++) 57 for(l=vl.hash[i]; l; l=l->next){ 58 strcpy(a, l->name); 59 s[nname++] = a; 60 a += strlen(a)+1; 61 } 62 *pn = nname; 63 assert(a == e); 64 qunlock(&vl.lk); 65 66 return s; 67 } 68 69 VtLog* 70 vtlogopen(char *name, uint size) 71 { 72 uint h; 73 int i, nc; 74 char *p; 75 VtLog *l, *last; 76 77 if(!ventilogging) 78 return nil; 79 80 h = hash(name)%nelem(vl.hash); 81 qlock(&vl.lk); 82 last = nil; 83 for(l=vl.hash[h]; l; last=l, l=l->next) 84 if(strcmp(l->name, name) == 0){ 85 if(last){ /* move to front */ 86 last->next = l->next; 87 l->next = vl.hash[h]; 88 vl.hash[h] = l; 89 } 90 l->ref++; 91 qunlock(&vl.lk); 92 return l; 93 } 94 95 if(size == 0){ 96 qunlock(&vl.lk); 97 return nil; 98 } 99 100 /* allocate */ 101 nc = (size+LogChunkSize-1)/LogChunkSize; 102 l = vtmalloc(sizeof *l + nc*(sizeof(*l->chunk)+LogChunkSize) + strlen(name)+1); 103 memset(l, 0, sizeof *l); 104 l->chunk = (VtLogChunk*)(l+1); 105 l->nchunk = nc; 106 l->w = l->chunk; 107 p = (char*)(l->chunk+nc); 108 for(i=0; i<nc; i++){ 109 l->chunk[i].p = p; 110 l->chunk[i].wp = p; 111 p += LogChunkSize; 112 l->chunk[i].ep = p; 113 } 114 strcpy(p, name); 115 l->name = p; 116 117 /* insert */ 118 l->next = vl.hash[h]; 119 vl.hash[h] = l; 120 l->ref++; 121 122 l->ref++; 123 qunlock(&vl.lk); 124 return l; 125 } 126 127 void 128 vtlogclose(VtLog *l) 129 { 130 if(l == nil) 131 return; 132 133 qlock(&vl.lk); 134 if(--l->ref == 0){ 135 /* must not be in hash table */ 136 assert(l->name == Eremoved); 137 free(l); 138 }else 139 assert(l->ref > 0); 140 qunlock(&vl.lk); 141 } 142 143 void 144 vtlogremove(char *name) 145 { 146 uint h; 147 VtLog *last, *l; 148 149 h = hash(name)%nelem(vl.hash); 150 qlock(&vl.lk); 151 last = nil; 152 for(l=vl.hash[h]; l; last=l, l=l->next) 153 if(strcmp(l->name, name) == 0){ 154 if(last) 155 last->next = l->next; 156 else 157 vl.hash[h] = l->next; 158 l->name = Eremoved; 159 l->next = nil; 160 qunlock(&vl.lk); 161 vtlogclose(l); 162 return; 163 } 164 qunlock(&vl.lk); 165 } 166 167 static int 168 timefmt(Fmt *fmt) 169 { 170 static uvlong t0; 171 uvlong t; 172 173 if(t0 == 0) 174 t0 = nsec(); 175 t = nsec()-t0; 176 return fmtprint(fmt, "T+%d.%04d", (uint)(t/1000000000), (uint)(t%1000000000)/100000); 177 } 178 179 void 180 vtlogvprint(VtLog *l, char *fmt, va_list arg) 181 { 182 int n; 183 char *p; 184 VtLogChunk *c; 185 static int first = 1; 186 187 if(l == nil) 188 return; 189 190 if(first){ 191 fmtinstall('T', timefmt); 192 first = 0; 193 } 194 195 196 qlock(&l->lk); 197 c = l->w; 198 n = c->ep - c->wp; 199 if(n < 512){ 200 c++; 201 if(c == l->chunk+l->nchunk) 202 c = l->chunk; 203 c->wp = c->p; 204 l->w = c; 205 } 206 p = vseprint(c->wp, c->ep, fmt, arg); 207 if(p) 208 c->wp = p; 209 qunlock(&l->lk); 210 } 211 212 void 213 vtlogprint(VtLog *l, char *fmt, ...) 214 { 215 va_list arg; 216 217 if(l == nil) 218 return; 219 220 va_start(arg, fmt); 221 vtlogvprint(l, fmt, arg); 222 va_end(arg); 223 } 224 225 void 226 vtlog(char *name, char *fmt, ...) 227 { 228 VtLog *l; 229 va_list arg; 230 231 l = vtlogopen(name, LogSize); 232 if(l == nil) 233 return; 234 va_start(arg, fmt); 235 vtlogvprint(l, fmt, arg); 236 va_end(arg); 237 vtlogclose(l); 238 } 239 240 void 241 vtlogdump(int fd, VtLog *l) 242 { 243 int i; 244 VtLogChunk *c; 245 246 if(l == nil) 247 return; 248 249 c = l->w; 250 for(i=0; i<l->nchunk; i++){ 251 if(++c == l->chunk+l->nchunk) 252 c = l->chunk; 253 write(fd, c->p, c->wp-c->p); 254 } 255 } 256 257