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