ref: 7c8d75a3092a81102436c6446c59a41a9d2a8f8e
parent: 29fee6a8edab12acceea7bc54e30979477d6a6f7
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Jun 7 13:06:33 EDT 2020
acme: add missing logf.c
--- /dev/null
+++ b/sys/src/cmd/acme/logf.c
@@ -1,0 +1,202 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <cursor.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include <frame.h>
+#include <fcall.h>
+#include <plumb.h>
+#include <libsec.h>
+#include "dat.h"
+#include "fns.h"
+
+// State for global log file.
+typedef struct Log Log;
+struct Log
+{
+ QLock lk;
+ Rendez r;
+
+ vlong start; // msg[0] corresponds to 'start' in the global sequence of events
+
+ // queued events (nev=entries in ev, mev=capacity of p)
+ char **ev;
+ int nev;
+ int mev;
+
+ // open acme/put files that need to read events
+ Fid **f;
+ int nf;
+ int mf;
+
+ // active (blocked) reads waiting for events
+ Xfid **read;
+ int nread;
+ int mread;
+};
+
+static Log eventlog;
+
+void
+xfidlogopen(Xfid *x)
+{
+ qlock(&eventlog.lk);
+ if(eventlog.nf >= eventlog.mf) {
+ eventlog.mf = eventlog.mf*2;
+ if(eventlog.mf == 0)
+ eventlog.mf = 8;
+ eventlog.f = erealloc(eventlog.f, eventlog.mf*sizeof eventlog.f[0]);
+ }
+ eventlog.f[eventlog.nf++] = x->f;
+ x->f->logoff = eventlog.start + eventlog.nev;
+
+ qunlock(&eventlog.lk);
+}
+
+void
+xfidlogclose(Xfid *x)
+{
+ int i;
+
+ qlock(&eventlog.lk);
+ for(i=0; i<eventlog.nf; i++) {
+ if(eventlog.f[i] == x->f) {
+ eventlog.f[i] = eventlog.f[--eventlog.nf];
+ break;
+ }
+ }
+ qunlock(&eventlog.lk);
+}
+
+void
+xfidlogread(Xfid *x)
+{
+ char *p;
+ int i;
+ Fcall fc;
+
+ qlock(&eventlog.lk);
+ if(eventlog.nread >= eventlog.mread) {
+ eventlog.mread = eventlog.mread*2;
+ if(eventlog.mread == 0)
+ eventlog.mread = 8;
+ eventlog.read = erealloc(eventlog.read, eventlog.mread*sizeof eventlog.read[0]);
+ }
+ eventlog.read[eventlog.nread++] = x;
+
+ if(eventlog.r.l == nil)
+ eventlog.r.l = &eventlog.lk;
+ x->flushed = FALSE;
+ while(x->f->logoff >= eventlog.start+eventlog.nev && !x->flushed)
+ rsleep(&eventlog.r);
+
+ for(i=0; i<eventlog.nread; i++) {
+ if(eventlog.read[i] == x) {
+ eventlog.read[i] = eventlog.read[--eventlog.nread];
+ break;
+ }
+ }
+
+ if(x->flushed) {
+ qunlock(&eventlog.lk);
+ return;
+ }
+
+ i = x->f->logoff - eventlog.start;
+ p = estrdup(eventlog.ev[i]);
+ x->f->logoff++;
+ qunlock(&eventlog.lk);
+
+ fc.data = p;
+ fc.count = strlen(p);
+ respond(x, &fc, nil);
+ free(p);
+}
+
+void
+xfidlogflush(Xfid *x)
+{
+ int i;
+ Xfid *rx;
+
+ qlock(&eventlog.lk);
+ for(i=0; i<eventlog.nread; i++) {
+ rx = eventlog.read[i];
+ if(rx->tag == x->oldtag) {
+ rx->flushed = TRUE;
+ rwakeupall(&eventlog.r);
+ }
+ }
+ qunlock(&eventlog.lk);
+}
+
+/*
+ * add a log entry for op on w.
+ * expected calls:
+ *
+ * op == "new" for each new window
+ * - caller of coladd or makenewwindow responsible for calling
+ * xfidlog after setting window name
+ * - exception: zerox
+ *
+ * op == "zerox" for new window created via zerox
+ * - called from zeroxx
+ *
+ * op == "get" for Get executed on window
+ * - called from get
+ *
+ * op == "put" for Put executed on window
+ * - called from put
+ *
+ * op == "del" for deleted window
+ * - called from winclose
+ *
+ * op == "focus" for window focus change
+ * - called from mousethread
+ */
+void
+xfidlog(Window *w, char *op)
+{
+ int i, n;
+ vlong min;
+ File *f;
+ char *name;
+
+ qlock(&eventlog.lk);
+ if(eventlog.nev >= eventlog.mev) {
+ // Remove and free any entries that all readers have read.
+ min = eventlog.start + eventlog.nev;
+ for(i=0; i<eventlog.nf; i++) {
+ if(min > eventlog.f[i]->logoff)
+ min = eventlog.f[i]->logoff;
+ }
+ if(min > eventlog.start) {
+ n = min - eventlog.start;
+ for(i=0; i<n; i++)
+ free(eventlog.ev[i]);
+ eventlog.nev -= n;
+ eventlog.start += n;
+ memmove(eventlog.ev, eventlog.ev+n, eventlog.nev*sizeof eventlog.ev[0]);
+ }
+
+ // Otherwise grow.
+ if(eventlog.nev >= eventlog.mev) {
+ eventlog.mev = eventlog.mev*2;
+ if(eventlog.mev == 0)
+ eventlog.mev = 8;
+ eventlog.ev = erealloc(eventlog.ev, eventlog.mev*sizeof eventlog.ev[0]);
+ }
+ }
+ f = w->body.file;
+ name = runetobyte(f->name, f->nname);
+ if(name == nil)
+ name = estrdup("");
+ eventlog.ev[eventlog.nev++] = smprint("%d %s %s\n", w->id, op, name);
+ free(name);
+ if(eventlog.r.l == nil)
+ eventlog.r.l = &eventlog.lk;
+ rwakeupall(&eventlog.r);
+ qunlock(&eventlog.lk);
+}