xref: /plan9-contrib/sys/src/9/port/log.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "../port/error.h"
7 
8 static char Ebadlogctl[] = "unknown log ctl message";
9 
10 enum {
11 	Nlog		= 4*1024,
12 };
13 
14 void
15 logopen(Log *alog)
16 {
17 	lock(alog);
18 	if(waserror()){
19 		unlock(alog);
20 		nexterror();
21 	}
22 	if(alog->opens == 0){
23 		if(alog->buf == nil)
24 			alog->buf = malloc(Nlog);
25 		alog->rptr = alog->buf;
26 		alog->end = alog->buf + Nlog;
27 	}
28 	alog->opens++;
29 	unlock(alog);
30 	poperror();
31 }
32 
33 void
34 logclose(Log *alog)
35 {
36 	lock(alog);
37 	if(waserror()){
38 		unlock(alog);
39 		nexterror();
40 	}
41 	alog->opens--;
42 	if(alog->opens == 0){
43 		free(alog->buf);
44 		alog->buf = nil;
45 	}
46 	unlock(alog);
47 	poperror();
48 }
49 
50 static int
51 logready(void *a)
52 {
53 	Log *alog = a;
54 
55 	return alog->len;
56 }
57 
58 long
59 logread(Log *alog, void *a, ulong, long n)
60 {
61 	int i, d;
62 	char *p, *rptr;
63 
64 	qlock(&alog->readq);
65 	if(waserror()){
66 		qunlock(&alog->readq);
67 		nexterror();
68 	}
69 
70 	for(;;){
71 		lock(alog);
72 		if(alog->len){
73 			if(n > alog->len)
74 				n = alog->len;
75 			d = 0;
76 			rptr = alog->rptr;
77 			alog->rptr += n;
78 			if(alog->rptr >= alog->end){
79 				d = alog->rptr - alog->end;
80 				alog->rptr = alog->buf + d;
81 			}
82 			alog->len -= n;
83 			unlock(alog);
84 
85 			i = n-d;
86 			p = a;
87 			memmove(p, rptr, i);
88 			memmove(p+i, alog->buf, d);
89 			break;
90 		}
91 		else
92 			unlock(alog);
93 
94 		sleep(&alog->readr, logready, alog);
95 	}
96 
97 	qunlock(&alog->readq);
98 	poperror();
99 
100 	return n;
101 }
102 
103 char*
104 logctl(Log *alog, int argc, char *argv[], Logflag *flags)
105 {
106 	int i, set;
107 	Logflag *fp;
108 
109 	if(argc < 2)
110 		return Ebadlogctl;
111 
112 	if(strcmp("set", argv[0]) == 0)
113 		set = 1;
114 	else if(strcmp("clear", argv[0]) == 0)
115 		set = 0;
116 	else
117 		return Ebadlogctl;
118 
119 	for(i = 1; i < argc; i++){
120 		for(fp = flags; fp->name; fp++)
121 			if(strcmp(fp->name, argv[i]) == 0)
122 				break;
123 		if(fp->name == nil)
124 			continue;
125 		if(set)
126 			alog->logmask |= fp->mask;
127 		else
128 			alog->logmask &= ~fp->mask;
129 	}
130 
131 	return nil;
132 }
133 
134 void
135 log(Log *alog, int mask, char *fmt, ...)
136 {
137 	char buf[128], *t, *fp;
138 	int i, n;
139 	va_list arg;
140 
141 	if(!(alog->logmask & mask))
142 		return;
143 
144 	va_start(arg, fmt);
145 	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
146 	va_end(arg);
147 
148 	if(alog->opens == 0)
149 		return;
150 
151 	lock(alog);
152 	i = alog->len + n - Nlog;
153 	if(i > 0){
154 		alog->len -= i;
155 		alog->rptr += i;
156 		if(alog->rptr >= alog->end)
157 			alog->rptr = alog->buf + (alog->rptr - alog->end);
158 	}
159 	t = alog->rptr + alog->len;
160 	fp = buf;
161 	alog->len += n;
162 	while(n-- > 0){
163 		if(t >= alog->end)
164 			t = alog->buf + (t - alog->end);
165 		*t++ = *fp++;
166 	}
167 	unlock(alog);
168 
169 	wakeup(&alog->readr);
170 }
171