ded4722115c5460444eff3cf24c45e9298b1a51f
[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 #ifdef RXTRACEON
33 char rxi_tracename[80] = "/tmp/rxcalltrace";
34 #else
35 char rxi_tracename[80] =
36     "\0Change This pathname (and preceding NUL) to initiate tracing";
37 #endif
38 int rxi_logfd = -1;
39 char rxi_tracebuf[4096];
40 afs_uint32 rxi_tracepos = 0;
41
42 struct rx_trace {
43     afs_uint32 cid;
44     unsigned short call;
45     unsigned short qlen;
46     afs_uint32 now;
47     afs_uint32 waittime;
48     afs_uint32 servicetime;
49     afs_uint32 event;
50 };
51
52 void
53 rxi_flushtrace(void)
54 {
55     if (rxi_logfd >= 0)
56         write(rxi_logfd, rxi_tracebuf, rxi_tracepos);
57     rxi_tracepos = 0;
58 }
59
60 void
61 rxi_calltrace(unsigned int event, struct rx_call *call)
62 {
63     struct clock now;
64     struct rx_trace rxtinfo;
65
66     if (!rxi_tracename[0])
67         return;
68
69     if (rxi_logfd < 0) {
70         rxi_logfd = open(rxi_tracename, O_WRONLY | O_CREAT | O_TRUNC, 0777);
71         if (rxi_logfd < 0)
72             rxi_tracename[0] = '\0';
73     }
74     clock_GetTime(&now);
75
76     rxtinfo.event = event;
77     rxtinfo.now = now.sec * 1000 + now.usec / 1000;
78     rxtinfo.cid = call->conn->cid;
79     rxtinfo.call = *(call->callNumber);
80     rxtinfo.qlen = rx_atomic_read(&rx_nWaiting);
81     rxtinfo.servicetime = 0;
82     rxtinfo.waittime = 0;
83
84     switch (event) {
85     case RX_CALL_END:
86         clock_Sub(&now, &(call->traceStart));
87         rxtinfo.servicetime = now.sec * 10000 + now.usec / 100;
88         if (call->traceWait.sec) {
89             now = call->traceStart;
90             clock_Sub(&now, &(call->traceWait));
91             rxtinfo.waittime = now.sec * 10000 + now.usec / 100;
92         } else
93             rxtinfo.waittime = 0;
94         call->traceWait.sec = call->traceWait.usec = call->traceStart.sec =
95             call->traceStart.usec = 0;
96         break;
97
98     case RX_CALL_START:
99         call->traceStart = now;
100         if (call->traceWait.sec) {
101             clock_Sub(&now, &(call->traceWait));
102             rxtinfo.waittime = now.sec * 10000 + now.usec / 100;
103         } else
104             rxtinfo.waittime = 0;
105         break;
106
107     case RX_TRACE_DROP:
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_CALL_ARRIVAL:
116         call->traceWait = now;
117     default:
118         break;
119     }
120
121     memcpy(rxi_tracebuf + rxi_tracepos, &rxtinfo, sizeof(struct rx_trace));
122     rxi_tracepos += sizeof(struct rx_trace);
123     if (rxi_tracepos >= (4096 - sizeof(struct rx_trace)))
124         rxi_flushtrace();
125 }
126
127 #ifdef DUMPTRACE
128 #include <errno.h>
129 #ifdef AFS_NT40_ENV
130 #include <afs/afsutil.h>
131 #endif
132
133 int
134 main(int argc, char **argv)
135 {
136     struct rx_trace ip;
137     int err = 0;
138
139     setlinebuf(stdout);
140     argv++;
141     argc--;
142     while (argc && **argv == '-') {
143         if (strcmp(*argv, "-trace") == 0) {
144             strcpy(rxi_tracename, *(++argv));
145             argc--;
146         } else {
147             err++;
148             break;
149         }
150         argv++, argc--;
151     }
152     if (err || argc != 0) {
153         printf("usage: dumptrace [-trace pathname]");
154         exit(1);
155     }
156
157     rxi_logfd = open(rxi_tracename, O_RDONLY);
158     if (rxi_logfd < 0) {
159         perror("");
160         exit(errno);
161     }
162
163     while (read(rxi_logfd, &ip, sizeof(struct rx_trace))) {
164         printf("%9u ", ip.now);
165         switch (ip.event) {
166         case RX_CALL_END:
167             putchar('E');
168             break;
169         case RX_CALL_START:
170             putchar('S');
171             break;
172         case RX_CALL_ARRIVAL:
173             putchar('A');
174             break;
175         case RX_TRACE_DROP:
176             putchar('D');
177             break;
178         default:
179             putchar('U');
180             break;
181         }
182         printf(" %3u %7u %7u      %x.%x\n", ip.qlen, ip.servicetime,
183                ip.waittime, ip.cid, ip.call);
184     }
185     return 0;
186 }
187
188 #endif /* DUMPTRACE */
189 #endif /* RXDEBUG */