acme9k/logf.c

193 lines
4.1 KiB
C
Raw Permalink Normal View History

2019-11-14 23:15:48 +00:00
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <cursor.h>
#include <mouse.h>
#include <keyboard.h>
#include "libframe/frame.h"
2019-11-14 23:15:48 +00:00
#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;
2019-11-14 23:15:48 +00:00
};
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);
2019-11-14 23:15:48 +00:00
}
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);
2019-11-14 23:15:48 +00:00
}
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);
2019-11-14 23:15:48 +00:00
}
void xfidlogflush(Xfid* x) {
int i;
Xfid* rx;
qlock(&eventlog.lk);
for (i = 0; i < eventlog.nread; i++) {
rx = eventlog.read[i];
if (rx->fcall.tag == x->fcall.oldtag) {
rx->flushed = TRUE;
rwakeupall(&eventlog.r);
}
}
qunlock(&eventlog.lk);
2019-11-14 23:15:48 +00:00
}
/*
* 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
*/
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);
2019-11-14 23:15:48 +00:00
}