71602b12dcf21ea4ac46320707dbffdd1aa88db8
[openafs.git] / src / ubik / udebug.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 <afs/param.h>
11 #include <sys/types.h>
12 #include <stdlib.h>
13 #ifdef AFS_NT40_ENV
14 #include <winsock2.h>
15 #else
16 #include <sys/file.h>
17 #include <sys/param.h>
18 #include <netinet/in.h>
19 #include <netdb.h>
20 #endif
21 #include <signal.h>
22 #include <time.h>
23
24 #include <lock.h>
25 #include <rx/xdr.h>
26 #include <rx/rx.h>
27 #include <afs/cmd.h>
28
29 #define UBIK_INTERNALS
30 #include "ubik.h"
31 #include "ubik_int.h"
32
33 extern struct hostent *hostutil_GetHostByName();
34
35 static short PortNumber(aport)
36 register char *aport; {
37     register int tc;
38     register afs_int32 total;
39
40     total = 0;
41     while (tc = *aport++) {
42         if (tc < '0' || tc > '9') return -1;    /* bad port number */
43         total *= 10;
44         total += tc - (int) '0';
45     }
46     return(total);
47 }
48
49 static short PortName(aname)
50     char *aname;
51 {
52     struct servent *ts;
53     int len;
54
55     ts = getservbyname(aname, (char *) 0);
56
57     if (ts)
58        return ntohs(ts->s_port);  /* returns it in host byte order */
59
60     len = strlen(aname);
61     if        (strncmp(aname,"vlserver",len) == 0) {
62        return 7003;
63     } else if (strncmp(aname,"ptserver",len) == 0) {
64        return 7002;
65     } else if (strncmp(aname,"kaserver",len) == 0) {
66        return 7004;
67     } else if (strncmp(aname,"buserver",len) == 0) {
68        return 7021;
69     }
70     return(-1);
71 }
72
73 static CommandProc(as, arock)
74 char *arock;
75 struct cmd_syndesc *as; {
76     char *hostName, *portName, *times;
77     afs_int32 hostAddr;
78     struct in_addr inhostAddr;
79     register afs_int32 i, j, code;
80     short port;
81     int int32p;
82     afs_int32 now, diff, newtime;
83     struct hostent *th;
84     struct rx_connection *tconn;
85     struct rx_securityClass *sc;
86     struct ubik_debug udebug;
87     struct ubik_sdebug usdebug;
88     int         oldServer =0;   /* are we talking to a pre 3.5 server? */
89
90     int32p = (as->parms[2].items ? 1 : 0);
91
92     if (as->parms[0].items)
93         hostName = as->parms[0].items->data;
94     else
95         hostName = (char *) 0;
96
97     if (as->parms[1].items)
98         portName = as->parms[1].items->data;
99     else
100         portName = (char *) 0;
101
102     /* lookup host */
103     if (hostName) {
104         th = hostutil_GetHostByName(hostName);
105         if (!th) {
106             printf("udebug: host %s not found in host table\n", hostName);
107             exit(1);
108         }
109         bcopy(th->h_addr, &hostAddr, sizeof(afs_int32));
110     }
111     else hostAddr = htonl(0x7f000001);  /* IP localhost */
112
113     if (!portName)
114         port = htons(3000);             /* default */
115     else {
116       port = PortNumber(portName);
117       if (port < 0)
118         port = PortName(portName);
119       if (port < 0) {
120         printf("udebug: can't resolve port name %s\n", portName);
121         exit(1);
122       }
123       port = htons(port);
124     }
125
126     rx_Init(0);
127     sc = (struct rx_securityClass *) rxnull_NewClientSecurityObject();
128     tconn = rx_NewConnection(hostAddr, port, VOTE_SERVICE_ID, sc, 0);
129     
130     /* now do the main call */
131     code = VOTE_Debug(tconn, &udebug);
132     if ( code == RXGEN_OPCODE ) 
133     {
134         oldServer = 1;                  /* talking to a pre 3.5 server */
135         memset(&udebug, 0, sizeof(udebug)); 
136         code = VOTE_DebugOld(tconn, &udebug);
137     }
138
139     if (code) {
140         printf("return code %d from VOTE_Debug\n", code);
141         exit(0);
142     }
143     now = time(0);
144
145     /* now print the main info */
146     times = ctime((time_t *)&udebug.now); times[24] = 0;
147     inhostAddr.s_addr = hostAddr;
148     if ( !oldServer )
149     {
150         printf("Host's addresses are: ");
151         for ( j=0; udebug.interfaceAddr[j] && ( j<UBIK_MAX_INTERFACE_ADDR );j++)
152             printf("%s ", afs_inet_ntoa(htonl(udebug.interfaceAddr[j])));
153         printf("\n");
154     }
155     printf("Host's %s time is %s\n",  inet_ntoa(inhostAddr), times);
156
157     times = ctime(&now); times[24] = 0;
158     diff = now - udebug.now;
159     printf("Local time is %s (time differential %d secs)\n", times, diff);
160     if (abs(diff) >= MAXSKEW)
161         printf("****clock may be bad\n");
162
163     /* UBIK skips the voting if 1 server - so we fudge it here */
164     if (udebug.amSyncSite && (udebug.nServers == 1)) {
165        udebug.lastYesHost  = hostAddr;
166        udebug.lastYesTime  = udebug.now;
167        udebug.lastYesState = 1;
168        udebug.lastYesClaim = udebug.now;
169        udebug.syncVersion.epoch   = udebug.localVersion.epoch;
170        udebug.syncVersion.counter = udebug.localVersion.counter;
171     }
172
173     /* sockaddr is always in net-order */
174     if (udebug.lastYesHost == 0xffffffff) {
175        printf("Last yes vote not cast yet \n");
176     } else {
177        inhostAddr.s_addr = htonl(udebug.lastYesHost);
178        diff = udebug.now - udebug.lastYesTime;
179        printf("Last yes vote for %s was %d secs ago (%ssync site); \n",
180               inet_ntoa(inhostAddr), diff, ((udebug.lastYesState)?"":"not "));
181
182        diff = udebug.now - udebug.lastYesClaim;
183        newtime = now - diff;
184        times = ctime(&newtime); times[24] = 0;
185        printf("Last vote started %d secs ago (at %s)\n", diff, times);
186     }
187
188     printf("Local db version is %d.%d\n", udebug.localVersion.epoch, udebug.localVersion.counter);
189
190     if (udebug.amSyncSite) {
191         if (udebug.syncSiteUntil == 0x7fffffff) {
192            printf("I am sync site forever (%d server%s)\n",
193                   udebug.nServers, ((udebug.nServers>1)?"s":""));
194         } else {
195            diff = udebug.syncSiteUntil - udebug.now;
196            newtime = now + diff;
197            times = ctime(&newtime); times[24] = 0;
198            printf("I am sync site until %d secs from now (at %s) (%d server%s)\n",
199                   diff, times, udebug.nServers,
200                   ((udebug.nServers>1)?"s":""));
201         }
202         printf("Recovery state %x\n", udebug.recoveryState);
203         if (udebug.activeWrite) {
204             printf("I am currently managing write trans %d.%d\n",
205                    udebug.epochTime, udebug.tidCounter);
206         }
207     } else {
208         printf("I am not sync site\n");
209         inhostAddr.s_addr = htonl(udebug.lowestHost);
210         diff = udebug.now - udebug.lowestTime;
211         printf("Lowest host %s was set %d secs ago\n", inet_ntoa(inhostAddr), diff);
212
213         inhostAddr.s_addr = htonl(udebug.syncHost);
214         diff = udebug.now - udebug.syncTime;
215         printf("Sync host %s was set %d secs ago\n", inet_ntoa(inhostAddr), diff);
216     }
217
218     printf("Sync site's db version is %d.%d\n",
219            udebug.syncVersion.epoch, udebug.syncVersion.counter);
220     printf("%d locked pages, %d of them for write\n",
221            udebug.lockedPages, udebug.writeLockedPages);
222     
223     if (udebug.anyReadLocks)  printf("There are read locks held\n");
224     if (udebug.anyWriteLocks) printf("There are write locks held\n");
225     
226     if (udebug.currentTrans) {
227         if (udebug.writeTrans) printf("There is an active write transaction\n");
228         else printf("There is at least one active read transaction\n");
229         printf("Transaction tid is %d.%d\n", udebug.syncTid.epoch, udebug.syncTid.counter);
230     }
231     if (udebug.epochTime) {
232         diff = udebug.now - udebug.epochTime;
233         newtime = now - diff;
234         times = ctime(&newtime); times[24] = 0;
235         printf("Last time a new db version was labelled was:\n\t %d secs ago (at %s)\n",
236                diff, times);
237     }
238
239     if (int32p || udebug.amSyncSite) {
240         /* now do the subcalls */
241         for(i=0;;i++) {
242             if ( oldServer )
243             {                           /* pre 3.5 server */
244                 memset(&usdebug, 0, sizeof(usdebug)); 
245                 code = VOTE_SDebugOld(tconn, i, &usdebug);
246             }
247             else
248                 code = VOTE_SDebug(tconn, i, &usdebug);
249             if (code > 0) break;        /* done */
250             if (code < 0) {
251                 printf("error code %d from VOTE_SDebug\n", code);
252                 break;
253             }
254             inhostAddr.s_addr = htonl(usdebug.addr);
255             /* otherwise print the structure */
256             printf("\nServer( %s", afs_inet_ntoa(htonl(usdebug.addr))); 
257             for ( j=0;((usdebug.altAddr[j]) && 
258                                 (j<UBIK_MAX_INTERFACE_ADDR-1)); j++)
259                 printf(" %s", afs_inet_ntoa(htonl(usdebug.altAddr[j])));
260             printf(" ): (db %d.%d)\n",
261                    usdebug.remoteVersion.epoch, usdebug.remoteVersion.counter);
262
263             if (usdebug.lastVoteTime == 0) {
264                printf("    last vote never rcvd \n");
265             } else {
266                diff = udebug.now - usdebug.lastVoteTime;
267                newtime = now - diff;
268                times = ctime(&newtime); times[24] = 0;
269                printf("    last vote rcvd %d secs ago (at %s),\n", diff, times);
270             }
271
272             if (usdebug.lastBeaconSent == 0) {
273                printf("    last beacon never sent \n");
274             } else {
275                diff = udebug.now - usdebug.lastBeaconSent;
276                newtime = now - diff;
277                times = ctime(&newtime); times[24] = 0;
278                printf("    last beacon sent %d secs ago (at %s), last vote was %s\n",
279                       diff, times, ((usdebug.lastVote)?"yes":"no"));
280             }
281
282             printf("    dbcurrent=%d, up=%d beaconSince=%d\n",
283                    usdebug.currentDB, usdebug.up, usdebug.beaconSinceDown);
284         }
285     }
286 }
287
288 #include "AFS_component_version_number.c"
289
290 main(argc, argv)
291     int argc;
292     char **argv; {
293     struct cmd_syndesc *ts;
294
295 #ifdef  AFS_AIX32_ENV
296     /*
297      * The following signal action for AIX is necessary so that in case of a 
298      * crash (i.e. core is generated) we can include the user's data section 
299      * in the core dump. Unfortunately, by default, only a partial core is
300      * generated which, in many cases, isn't too useful.
301      */
302     struct sigaction nsa;
303     
304     sigemptyset(&nsa.sa_mask);
305     nsa.sa_handler = SIG_DFL;
306     nsa.sa_flags = SA_FULLDUMP;
307     sigaction(SIGSEGV, &nsa, NULL);
308 #endif
309     ts = cmd_CreateSyntax((char *) 0, CommandProc, 0, "probe ubik server");
310     cmd_AddParm(ts, "-servers", CMD_SINGLE, CMD_REQUIRED, "server machine");
311     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "IP port");
312     cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL, "print all info");
313
314     cmd_Dispatch(argc, argv);
315     exit(0);
316 }