URI:
       tlog.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tlog.c (3410B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <venti.h>
            4 
            5 int ventilogging;
            6 #define log        not_the_log_library_call
            7 
            8 static char Eremoved[] = "[removed]";
            9 
           10 enum
           11 {        /* defaults */
           12         LogChunkSize = 8192,
           13         LogSize = 65536
           14 };
           15 
           16 static struct {
           17         QLock lk;
           18         VtLog *hash[1024];
           19 } vl;
           20 
           21 static uint
           22 hash(char *s)
           23 {
           24         uint h;
           25         uchar *p;
           26 
           27         h = 0;
           28         for(p=(uchar*)s; *p; p++)
           29                 h = h*37 + *p;
           30         return h;
           31 }
           32 
           33 char**
           34 vtlognames(int *pn)
           35 {
           36         int i, nname, size;
           37         VtLog *l;
           38         char **s, *a, *e;
           39 
           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         }
           48 
           49         s = vtmalloc(nname*sizeof(char*)+size);
           50         a = (char*)(s+nname);
           51         e = (char*)s+nname*sizeof(char*)+size;
           52 
           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);
           63 
           64         return s;
           65 }
           66 
           67 VtLog*
           68 vtlogopen(char *name, uint size)
           69 {
           70         uint h;
           71         int i, nc;
           72         char *p;
           73         VtLog *l, *last;
           74 
           75         if(!ventilogging)
           76                 return nil;
           77 
           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                 }
           92 
           93         if(size == 0){
           94                 qunlock(&vl.lk);
           95                 return nil;
           96         }
           97 
           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;
          114 
          115         /* insert */
          116         l->next = vl.hash[h];
          117         vl.hash[h] = l;
          118         l->ref++;
          119 
          120         l->ref++;
          121         qunlock(&vl.lk);
          122         return l;
          123 }
          124 
          125 void
          126 vtlogclose(VtLog *l)
          127 {
          128         if(l == nil)
          129                 return;
          130 
          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         }else
          137                 assert(l->ref > 0);
          138         qunlock(&vl.lk);
          139 }
          140 
          141 void
          142 vtlogremove(char *name)
          143 {
          144         uint h;
          145         VtLog *last, *l;
          146 
          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                         else
          155                                 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 }
          164 
          165 void
          166 vtlogvprint(VtLog *l, char *fmt, va_list arg)
          167 {
          168         int n;
          169         char *p;
          170         VtLogChunk *c;
          171 
          172         if(l == nil)
          173                 return;
          174 
          175         qlock(&l->lk);
          176         c = l->w;
          177         n = c->ep - c->wp;
          178         if(n < 512){
          179                 c++;
          180                 if(c == l->chunk+l->nchunk)
          181                         c = l->chunk;
          182                 c->wp = c->p;
          183                 l->w = c;
          184         }
          185         p = vseprint(c->wp, c->ep, fmt, arg);
          186         if(p)
          187                 c->wp = p;
          188         qunlock(&l->lk);
          189 }
          190 
          191 void
          192 vtlogprint(VtLog *l, char *fmt, ...)
          193 {
          194         va_list arg;
          195 
          196         if(l == nil)
          197                 return;
          198 
          199         va_start(arg, fmt);
          200         vtlogvprint(l, fmt, arg);
          201         va_end(arg);
          202 }
          203 
          204 void
          205 vtlog(char *name, char *fmt, ...)
          206 {
          207         VtLog *l;
          208         va_list arg;
          209 
          210         l = vtlogopen(name, LogSize);
          211         if(l == nil)
          212                 return;
          213         va_start(arg, fmt);
          214         vtlogvprint(l, fmt, arg);
          215         va_end(arg);
          216         vtlogclose(l);
          217 }
          218 
          219 void
          220 vtlogdump(int fd, VtLog *l)
          221 {
          222         int i;
          223         VtLogChunk *c;
          224 
          225         if(l == nil)
          226                 return;
          227 
          228         c = l->w;
          229         for(i=0; i<l->nchunk; i++){
          230                 if(++c == l->chunk+l->nchunk)
          231                         c = l->chunk;
          232                 write(fd, c->p, c->wp-c->p);
          233         }
          234 }