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