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