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