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