plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }