logf.c (3960B)
1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <thread.h> 5 #include <cursor.h> 6 #include <mouse.h> 7 #include <keyboard.h> 8 #include <frame.h> 9 #include <fcall.h> 10 #include <plumb.h> 11 #include <libsec.h> 12 #include "dat.h" 13 #include "fns.h" 14 15 // State for global log file. 16 typedef struct Log Log; 17 struct Log 18 { 19 QLock lk; 20 Rendez r; 21 22 vlong start; // msg[0] corresponds to 'start' in the global sequence of events 23 24 // queued events (nev=entries in ev, mev=capacity of p) 25 char **ev; 26 int nev; 27 int mev; 28 29 // open acme/put files that need to read events 30 Fid **f; 31 int nf; 32 int mf; 33 34 // active (blocked) reads waiting for events 35 Xfid **read; 36 int nread; 37 int mread; 38 }; 39 40 static Log eventlog; 41 42 void 43 xfidlogopen(Xfid *x) 44 { 45 qlock(&eventlog.lk); 46 if(eventlog.nf >= eventlog.mf) { 47 eventlog.mf = eventlog.mf*2; 48 if(eventlog.mf == 0) 49 eventlog.mf = 8; 50 eventlog.f = erealloc(eventlog.f, eventlog.mf*sizeof eventlog.f[0]); 51 } 52 eventlog.f[eventlog.nf++] = x->f; 53 x->f->logoff = eventlog.start + eventlog.nev; 54 55 qunlock(&eventlog.lk); 56 } 57 58 void 59 xfidlogclose(Xfid *x) 60 { 61 int i; 62 63 qlock(&eventlog.lk); 64 for(i=0; i<eventlog.nf; i++) { 65 if(eventlog.f[i] == x->f) { 66 eventlog.f[i] = eventlog.f[--eventlog.nf]; 67 break; 68 } 69 } 70 qunlock(&eventlog.lk); 71 } 72 73 void 74 xfidlogread(Xfid *x) 75 { 76 char *p; 77 int i; 78 Fcall fc; 79 80 qlock(&eventlog.lk); 81 if(eventlog.nread >= eventlog.mread) { 82 eventlog.mread = eventlog.mread*2; 83 if(eventlog.mread == 0) 84 eventlog.mread = 8; 85 eventlog.read = erealloc(eventlog.read, eventlog.mread*sizeof eventlog.read[0]); 86 } 87 eventlog.read[eventlog.nread++] = x; 88 89 if(eventlog.r.l == nil) 90 eventlog.r.l = &eventlog.lk; 91 x->flushed = FALSE; 92 while(x->f->logoff >= eventlog.start+eventlog.nev && !x->flushed) 93 rsleep(&eventlog.r); 94 95 for(i=0; i<eventlog.nread; i++) { 96 if(eventlog.read[i] == x) { 97 eventlog.read[i] = eventlog.read[--eventlog.nread]; 98 break; 99 } 100 } 101 102 if(x->flushed) { 103 qunlock(&eventlog.lk); 104 return; 105 } 106 107 i = x->f->logoff - eventlog.start; 108 p = estrdup(eventlog.ev[i]); 109 x->f->logoff++; 110 qunlock(&eventlog.lk); 111 112 fc.data = p; 113 fc.count = strlen(p); 114 respond(x, &fc, nil); 115 free(p); 116 } 117 118 void 119 xfidlogflush(Xfid *x) 120 { 121 int i; 122 Xfid *rx; 123 124 qlock(&eventlog.lk); 125 for(i=0; i<eventlog.nread; i++) { 126 rx = eventlog.read[i]; 127 if(rx->fcall.tag == x->fcall.oldtag) { 128 rx->flushed = TRUE; 129 rwakeupall(&eventlog.r); 130 } 131 } 132 qunlock(&eventlog.lk); 133 } 134 135 /* 136 * add a log entry for op on w. 137 * expected calls: 138 * 139 * op == "new" for each new window 140 * - caller of coladd or makenewwindow responsible for calling 141 * xfidlog after setting window name 142 * - exception: zerox 143 * 144 * op == "zerox" for new window created via zerox 145 * - called from zeroxx 146 * 147 * op == "get" for Get executed on window 148 * - called from get 149 * 150 * op == "put" for Put executed on window 151 * - called from put 152 * 153 * op == "del" for deleted window 154 * - called from winclose 155 */ 156 void 157 xfidlog(Window *w, char *op) 158 { 159 int i, n; 160 vlong min; 161 File *f; 162 char *name; 163 164 qlock(&eventlog.lk); 165 if(eventlog.nev >= eventlog.mev) { 166 // Remove and free any entries that all readers have read. 167 min = eventlog.start + eventlog.nev; 168 for(i=0; i<eventlog.nf; i++) { 169 if(min > eventlog.f[i]->logoff) 170 min = eventlog.f[i]->logoff; 171 } 172 if(min > eventlog.start) { 173 n = min - eventlog.start; 174 for(i=0; i<n; i++) 175 free(eventlog.ev[i]); 176 eventlog.nev -= n; 177 eventlog.start += n; 178 memmove(eventlog.ev, eventlog.ev+n, eventlog.nev*sizeof eventlog.ev[0]); 179 } 180 181 // Otherwise grow. 182 if(eventlog.nev >= eventlog.mev) { 183 eventlog.mev = eventlog.mev*2; 184 if(eventlog.mev == 0) 185 eventlog.mev = 8; 186 eventlog.ev = erealloc(eventlog.ev, eventlog.mev*sizeof eventlog.ev[0]); 187 } 188 } 189 f = w->body.file; 190 name = runetobyte(f->name, f->nname); 191 if(name == nil) 192 name = estrdup(""); 193 eventlog.ev[eventlog.nev++] = smprint("%d %s %s\n", w->id, op, name); 194 free(name); 195 if(eventlog.r.l == nil) 196 eventlog.r.l = &eventlog.lk; 197 rwakeupall(&eventlog.r); 198 qunlock(&eventlog.lk); 199 }