Blob


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"
15 // State for global log file.
16 typedef struct Log Log;
17 struct Log
18 {
19 QLock lk;
20 Rendez r;
22 vlong start; // msg[0] corresponds to 'start' in the global sequence of events
24 // queued events (nev=entries in ev, mev=capacity of p)
25 char **ev;
26 int nev;
27 int mev;
29 // open acme/put files that need to read events
30 Fid **f;
31 int nf;
32 int mf;
34 // active (blocked) reads waiting for events
35 Xfid **read;
36 int nread;
37 int mread;
38 };
40 static Log eventlog;
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;
55 qunlock(&eventlog.lk);
56 }
58 void
59 xfidlogclose(Xfid *x)
60 {
61 int i;
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 }
73 void
74 xfidlogread(Xfid *x)
75 {
76 char *p;
77 int i;
78 Fcall fc;
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;
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);
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 }
102 if(x->flushed) {
103 qunlock(&eventlog.lk);
104 return;
107 i = x->f->logoff - eventlog.start;
108 p = estrdup(eventlog.ev[i]);
109 x->f->logoff++;
110 qunlock(&eventlog.lk);
112 fc.data = p;
113 fc.count = strlen(p);
114 respond(x, &fc, nil);
115 free(p);
118 void
119 xfidlogflush(Xfid *x)
121 int i;
122 Xfid *rx;
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);
132 qunlock(&eventlog.lk);
135 /*
136 * add a log entry for op on w.
137 * expected calls:
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
144 * op == "zerox" for new window created via zerox
145 * - called from zeroxx
147 * op == "get" for Get executed on window
148 * - called from get
150 * op == "put" for Put executed on window
151 * - called from put
153 * op == "del" for deleted window
154 * - called from winclose
155 */
156 void
157 xfidlog(Window *w, char *op)
159 int i, n;
160 vlong min;
161 File *f;
162 char *name;
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;
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]);
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]);
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);