bozo: Introduce bnode_Wait()
[openafs.git] / src / rx / rx_trace.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14
15 #ifndef RXDEBUG
16 char rxi_tracename[80] = "\0Tracing not compiled in";
17 #ifdef DUMPTRACE
18 int
19 main(int argc, char **argv)
20 {
21     return 0;
22 }
23 #endif
24 #else
25
26 #include "rx.h"
27 #include "rx_atomic.h"
28 #include "rx_globals.h"
29 #include "rx_internal.h"
30 #include "rx_trace.h"
31
32 #include "rx_conn.h"
33 #include "rx_call.h"
34
35 #ifdef RXTRACEON
36 char rxi_tracename[80] = "/tmp/rxcalltrace";
37 #else
38 char rxi_tracename[80] =
39     "\0Change This pathname (and preceding NUL) to initiate tracing";
40 #endif
41 int rxi_logfd = -1;
42 char rxi_tracebuf[4096];
43 afs_uint32 rxi_tracepos = 0;
44
45 struct rx_trace {
46     afs_uint32 cid;
47     unsigned short call;
48     unsigned short qlen;
49     afs_uint32 now;
50     afs_uint32 waittime;
51     afs_uint32 servicetime;
52     afs_uint32 event;
53 };
54
55 void
56 rxi_flushtrace(void)
57 {
58     afs_uint32 len = rxi_tracepos;
59
60     rxi_tracepos = 0;
61     if (rxi_logfd < 0)
62         return;
63     if (write(rxi_logfd, rxi_tracebuf, len) < 0) {
64         /* don't care */
65     }
66 }
67
68 void
69 rxi_calltrace(unsigned int event, struct rx_call *call)
70 {
71     struct clock now;
72     struct rx_trace rxtinfo;
73
74     if (!rxi_tracename[0])
75         return;
76
77     if (rxi_logfd < 0) {
78         rxi_logfd = open(rxi_tracename, O_WRONLY | O_CREAT | O_TRUNC, 0777);
79         if (rxi_logfd < 0)
80             rxi_tracename[0] = '\0';
81     }
82     clock_GetTime(&now);
83
84     rxtinfo.event = event;
85     rxtinfo.now = now.sec * 1000 + now.usec / 1000;
86     rxtinfo.cid = call->conn->cid;
87     rxtinfo.call = *(call->callNumber);
88     rxtinfo.qlen = rx_atomic_read(&rx_nWaiting);
89     rxtinfo.servicetime = 0;
90     rxtinfo.waittime = 0;
91
92     switch (event) {
93     case RX_CALL_END:
94         clock_Sub(&now, &(call->traceStart));
95         rxtinfo.servicetime = now.sec * 10000 + now.usec / 100;
96         if (call->traceWait.sec) {
97             now = call->traceStart;
98             clock_Sub(&now, &(call->traceWait));
99             rxtinfo.waittime = now.sec * 10000 + now.usec / 100;
100         } else
101             rxtinfo.waittime = 0;
102         call->traceWait.sec = call->traceWait.usec = call->traceStart.sec =
103             call->traceStart.usec = 0;
104         break;
105
106     case RX_CALL_START:
107         call->traceStart = now;
108         if (call->traceWait.sec) {
109             clock_Sub(&now, &(call->traceWait));
110             rxtinfo.waittime = now.sec * 10000 + now.usec / 100;
111         } else
112             rxtinfo.waittime = 0;
113         break;
114
115     case RX_TRACE_DROP:
116         if (call->traceWait.sec) {
117             clock_Sub(&now, &(call->traceWait));
118             rxtinfo.waittime = now.sec * 10000 + now.usec / 100;
119         } else
120             rxtinfo.waittime = 0;
121         break;
122
123     case RX_CALL_ARRIVAL:
124         call->traceWait = now;
125         break;
126
127     default:
128         break;
129     }
130
131     memcpy(rxi_tracebuf + rxi_tracepos, &rxtinfo, sizeof(struct rx_trace));
132     rxi_tracepos += sizeof(struct rx_trace);
133     if (rxi_tracepos >= (4096 - sizeof(struct rx_trace)))
134         rxi_flushtrace();
135 }
136
137 #ifdef DUMPTRACE
138 #ifdef AFS_NT40_ENV
139 #include <afs/afsutil.h>
140 #endif
141
142 int
143 main(int argc, char **argv)
144 {
145     struct rx_trace ip;
146     int err = 0;
147
148     setlinebuf(stdout);
149     argv++;
150     argc--;
151     while (argc && **argv == '-') {
152         if (strcmp(*argv, "-trace") == 0) {
153             strcpy(rxi_tracename, *(++argv));
154             argc--;
155         } else {
156             err++;
157             break;
158         }
159         argv++, argc--;
160     }
161     if (err || argc != 0) {
162         printf("usage: dumptrace [-trace pathname]");
163         exit(1);
164     }
165
166     rxi_logfd = open(rxi_tracename, O_RDONLY);
167     if (rxi_logfd < 0) {
168         perror("");
169         exit(errno);
170     }
171
172     while (read(rxi_logfd, &ip, sizeof(struct rx_trace))) {
173         printf("%9u ", ip.now);
174         switch (ip.event) {
175         case RX_CALL_END:
176             putchar('E');
177             break;
178         case RX_CALL_START:
179             putchar('S');
180             break;
181         case RX_CALL_ARRIVAL:
182             putchar('A');
183             break;
184         case RX_TRACE_DROP:
185             putchar('D');
186             break;
187         default:
188             putchar('U');
189             break;
190         }
191         printf(" %3u %7u %7u      %x.%x\n", ip.qlen, ip.servicetime,
192                ip.waittime, ip.cid, ip.call);
193     }
194     return 0;
195 }
196
197 #endif /* DUMPTRACE */
198 #endif /* RXDEBUG */