xref: /plan9/sys/src/9/port/log.c (revision 5b0becee20e2ad09361e92534029bcec8c4db5e6)
17dd7cddfSDavid du Colombier #include "u.h"
27dd7cddfSDavid du Colombier #include "../port/lib.h"
37dd7cddfSDavid du Colombier #include "mem.h"
47dd7cddfSDavid du Colombier #include "dat.h"
57dd7cddfSDavid du Colombier #include "fns.h"
67dd7cddfSDavid du Colombier #include "../port/error.h"
77dd7cddfSDavid du Colombier 
87dd7cddfSDavid du Colombier static char Ebadlogctl[] = "unknown log ctl message";
97dd7cddfSDavid du Colombier 
107dd7cddfSDavid du Colombier void
logopen(Log * alog)117dd7cddfSDavid du Colombier logopen(Log *alog)
127dd7cddfSDavid du Colombier {
137dd7cddfSDavid du Colombier 	lock(alog);
147dd7cddfSDavid du Colombier 	if(waserror()){
157dd7cddfSDavid du Colombier 		unlock(alog);
167dd7cddfSDavid du Colombier 		nexterror();
177dd7cddfSDavid du Colombier 	}
187dd7cddfSDavid du Colombier 	if(alog->opens == 0){
1980ee5cbfSDavid du Colombier 		if(alog->nlog == 0)
2080ee5cbfSDavid du Colombier 			alog->nlog = 4*1024;
2180ee5cbfSDavid du Colombier 		if(alog->minread == 0)
2280ee5cbfSDavid du Colombier 			alog->minread = 1;
23*5b0beceeSDavid du Colombier 		if(alog->buf == nil && (alog->buf = malloc(alog->nlog)) == nil)
24aa72973aSDavid du Colombier 			error(Enomem);
257dd7cddfSDavid du Colombier 		alog->rptr = alog->buf;
2680ee5cbfSDavid du Colombier 		alog->end = alog->buf + alog->nlog;
2780ee5cbfSDavid du Colombier 		alog->len = 0;
287dd7cddfSDavid du Colombier 	}
297dd7cddfSDavid du Colombier 	alog->opens++;
307dd7cddfSDavid du Colombier 	unlock(alog);
317dd7cddfSDavid du Colombier 	poperror();
327dd7cddfSDavid du Colombier }
337dd7cddfSDavid du Colombier 
347dd7cddfSDavid du Colombier void
logclose(Log * alog)357dd7cddfSDavid du Colombier logclose(Log *alog)
367dd7cddfSDavid du Colombier {
377dd7cddfSDavid du Colombier 	lock(alog);
387dd7cddfSDavid du Colombier 	alog->opens--;
397dd7cddfSDavid du Colombier 	if(alog->opens == 0){
407dd7cddfSDavid du Colombier 		free(alog->buf);
417dd7cddfSDavid du Colombier 		alog->buf = nil;
427dd7cddfSDavid du Colombier 	}
437dd7cddfSDavid du Colombier 	unlock(alog);
447dd7cddfSDavid du Colombier }
457dd7cddfSDavid du Colombier 
467dd7cddfSDavid du Colombier static int
logready(void * a)477dd7cddfSDavid du Colombier logready(void *a)
487dd7cddfSDavid du Colombier {
497dd7cddfSDavid du Colombier 	Log *alog = a;
507dd7cddfSDavid du Colombier 
5180ee5cbfSDavid du Colombier 	return alog->len >= alog->minread;
527dd7cddfSDavid du Colombier }
537dd7cddfSDavid du Colombier 
547dd7cddfSDavid du Colombier long
logread(Log * alog,void * a,ulong,long n)557dd7cddfSDavid du Colombier logread(Log *alog, void *a, ulong, long n)
567dd7cddfSDavid du Colombier {
577dd7cddfSDavid du Colombier 	int i, d;
587dd7cddfSDavid du Colombier 	char *p, *rptr;
597dd7cddfSDavid du Colombier 
607dd7cddfSDavid du Colombier 	qlock(&alog->readq);
617dd7cddfSDavid du Colombier 	if(waserror()){
627dd7cddfSDavid du Colombier 		qunlock(&alog->readq);
637dd7cddfSDavid du Colombier 		nexterror();
647dd7cddfSDavid du Colombier 	}
657dd7cddfSDavid du Colombier 
667dd7cddfSDavid du Colombier 	for(;;){
677dd7cddfSDavid du Colombier 		lock(alog);
6880ee5cbfSDavid du Colombier 		if(alog->len >= alog->minread || alog->len >= n){
697dd7cddfSDavid du Colombier 			if(n > alog->len)
707dd7cddfSDavid du Colombier 				n = alog->len;
717dd7cddfSDavid du Colombier 			d = 0;
727dd7cddfSDavid du Colombier 			rptr = alog->rptr;
737dd7cddfSDavid du Colombier 			alog->rptr += n;
747dd7cddfSDavid du Colombier 			if(alog->rptr >= alog->end){
757dd7cddfSDavid du Colombier 				d = alog->rptr - alog->end;
767dd7cddfSDavid du Colombier 				alog->rptr = alog->buf + d;
777dd7cddfSDavid du Colombier 			}
787dd7cddfSDavid du Colombier 			alog->len -= n;
797dd7cddfSDavid du Colombier 			unlock(alog);
807dd7cddfSDavid du Colombier 
817dd7cddfSDavid du Colombier 			i = n-d;
827dd7cddfSDavid du Colombier 			p = a;
837dd7cddfSDavid du Colombier 			memmove(p, rptr, i);
847dd7cddfSDavid du Colombier 			memmove(p+i, alog->buf, d);
857dd7cddfSDavid du Colombier 			break;
867dd7cddfSDavid du Colombier 		}
877dd7cddfSDavid du Colombier 		else
887dd7cddfSDavid du Colombier 			unlock(alog);
897dd7cddfSDavid du Colombier 
907dd7cddfSDavid du Colombier 		sleep(&alog->readr, logready, alog);
917dd7cddfSDavid du Colombier 	}
927dd7cddfSDavid du Colombier 
937dd7cddfSDavid du Colombier 	qunlock(&alog->readq);
947dd7cddfSDavid du Colombier 	poperror();
957dd7cddfSDavid du Colombier 
967dd7cddfSDavid du Colombier 	return n;
977dd7cddfSDavid du Colombier }
987dd7cddfSDavid du Colombier 
997dd7cddfSDavid du Colombier char*
logctl(Log * alog,int argc,char * argv[],Logflag * flags)1007dd7cddfSDavid du Colombier logctl(Log *alog, int argc, char *argv[], Logflag *flags)
1017dd7cddfSDavid du Colombier {
1027dd7cddfSDavid du Colombier 	int i, set;
1037dd7cddfSDavid du Colombier 	Logflag *fp;
1047dd7cddfSDavid du Colombier 
1057dd7cddfSDavid du Colombier 	if(argc < 2)
1067dd7cddfSDavid du Colombier 		return Ebadlogctl;
1077dd7cddfSDavid du Colombier 
1087dd7cddfSDavid du Colombier 	if(strcmp("set", argv[0]) == 0)
1097dd7cddfSDavid du Colombier 		set = 1;
1107dd7cddfSDavid du Colombier 	else if(strcmp("clear", argv[0]) == 0)
1117dd7cddfSDavid du Colombier 		set = 0;
1127dd7cddfSDavid du Colombier 	else
1137dd7cddfSDavid du Colombier 		return Ebadlogctl;
1147dd7cddfSDavid du Colombier 
1157dd7cddfSDavid du Colombier 	for(i = 1; i < argc; i++){
1167dd7cddfSDavid du Colombier 		for(fp = flags; fp->name; fp++)
1177dd7cddfSDavid du Colombier 			if(strcmp(fp->name, argv[i]) == 0)
1187dd7cddfSDavid du Colombier 				break;
1197dd7cddfSDavid du Colombier 		if(fp->name == nil)
1207dd7cddfSDavid du Colombier 			continue;
1217dd7cddfSDavid du Colombier 		if(set)
1227dd7cddfSDavid du Colombier 			alog->logmask |= fp->mask;
1237dd7cddfSDavid du Colombier 		else
1247dd7cddfSDavid du Colombier 			alog->logmask &= ~fp->mask;
1257dd7cddfSDavid du Colombier 	}
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier 	return nil;
1287dd7cddfSDavid du Colombier }
1297dd7cddfSDavid du Colombier 
1307dd7cddfSDavid du Colombier void
logn(Log * alog,int mask,void * buf,int n)13180ee5cbfSDavid du Colombier logn(Log *alog, int mask, void *buf, int n)
1327dd7cddfSDavid du Colombier {
13380ee5cbfSDavid du Colombier 	char *fp, *t;
13480ee5cbfSDavid du Colombier 	int dowake, i;
1357dd7cddfSDavid du Colombier 
1367dd7cddfSDavid du Colombier 	if(!(alog->logmask & mask))
1377dd7cddfSDavid du Colombier 		return;
1387dd7cddfSDavid du Colombier 
1397dd7cddfSDavid du Colombier 	if(alog->opens == 0)
1407dd7cddfSDavid du Colombier 		return;
1417dd7cddfSDavid du Colombier 
14280ee5cbfSDavid du Colombier 	if(n > alog->nlog)
14380ee5cbfSDavid du Colombier 		return;
14480ee5cbfSDavid du Colombier 
1457dd7cddfSDavid du Colombier 	lock(alog);
14680ee5cbfSDavid du Colombier 	i = alog->len + n - alog->nlog;
1477dd7cddfSDavid du Colombier 	if(i > 0){
1487dd7cddfSDavid du Colombier 		alog->len -= i;
1497dd7cddfSDavid du Colombier 		alog->rptr += i;
1507dd7cddfSDavid du Colombier 		if(alog->rptr >= alog->end)
1517dd7cddfSDavid du Colombier 			alog->rptr = alog->buf + (alog->rptr - alog->end);
1527dd7cddfSDavid du Colombier 	}
1537dd7cddfSDavid du Colombier 	t = alog->rptr + alog->len;
1547dd7cddfSDavid du Colombier 	fp = buf;
1557dd7cddfSDavid du Colombier 	alog->len += n;
1567dd7cddfSDavid du Colombier 	while(n-- > 0){
1577dd7cddfSDavid du Colombier 		if(t >= alog->end)
1587dd7cddfSDavid du Colombier 			t = alog->buf + (t - alog->end);
1597dd7cddfSDavid du Colombier 		*t++ = *fp++;
1607dd7cddfSDavid du Colombier 	}
16180ee5cbfSDavid du Colombier 	dowake = alog->len >= alog->minread;
1627dd7cddfSDavid du Colombier 	unlock(alog);
1637dd7cddfSDavid du Colombier 
16480ee5cbfSDavid du Colombier 	if(dowake)
1657dd7cddfSDavid du Colombier 		wakeup(&alog->readr);
1667dd7cddfSDavid du Colombier }
16780ee5cbfSDavid du Colombier 
16880ee5cbfSDavid du Colombier void
log(Log * alog,int mask,char * fmt,...)1699a747e4fSDavid du Colombier log(Log *alog, int mask, char *fmt, ...)
17080ee5cbfSDavid du Colombier {
17180ee5cbfSDavid du Colombier 	int n;
1729a747e4fSDavid du Colombier 	va_list arg;
1739a747e4fSDavid du Colombier 	char buf[128];
17480ee5cbfSDavid du Colombier 
17580ee5cbfSDavid du Colombier 	if(!(alog->logmask & mask))
17680ee5cbfSDavid du Colombier 		return;
17780ee5cbfSDavid du Colombier 
17880ee5cbfSDavid du Colombier 	if(alog->opens == 0)
17980ee5cbfSDavid du Colombier 		return;
18080ee5cbfSDavid du Colombier 
1819a747e4fSDavid du Colombier 	va_start(arg, fmt);
1829a747e4fSDavid du Colombier 	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
1839a747e4fSDavid du Colombier 	va_end(arg);
18480ee5cbfSDavid du Colombier 
18580ee5cbfSDavid du Colombier 	logn(alog, mask, buf, n);
18680ee5cbfSDavid du Colombier }
187