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