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