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