more-prototyping-20030513
[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(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') return -1;    /* bad port number */
57         total *= 10;
58         total += tc - (int) '0';
59     }
60     return(total);
61 }
62
63 static short 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 CommandProc(struct cmd_syndesc *as, char *arock)
87 {
88     char *hostName, *portName, *times;
89     afs_int32 hostAddr;
90     struct in_addr inhostAddr;
91     register afs_int32 i, j, code;
92     short port;
93     int int32p;
94     afs_int32 now, 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
103     int32p = (as->parms[2].items ? 1 : 0);
104
105     if (as->parms[0].items)
106         hostName = as->parms[0].items->data;
107     else
108         hostName = NULL;
109
110     if (as->parms[1].items)
111         portName = as->parms[1].items->data;
112     else
113         portName = NULL;
114
115     /* lookup host */
116     if (hostName) {
117         th = hostutil_GetHostByName(hostName);
118         if (!th) {
119             printf("udebug: host %s not found in host table\n", hostName);
120             exit(1);
121         }
122         memcpy(&hostAddr, th->h_addr, sizeof(afs_int32));
123     }
124     else hostAddr = htonl(0x7f000001);  /* IP localhost */
125
126     if (!portName)
127         port = htons(3000);             /* default */
128     else {
129       port = PortNumber(portName);
130       if (port < 0)
131         port = PortName(portName);
132       if (port < 0) {
133         printf("udebug: can't resolve port name %s\n", portName);
134         exit(1);
135       }
136       port = htons(port);
137     }
138
139     rx_Init(0);
140     sc = rxnull_NewClientSecurityObject();
141     tconn = rx_NewConnection(hostAddr, port, VOTE_SERVICE_ID, sc, 0);
142     
143     /* now do the main call */
144     code = VOTE_XDebug(tconn, &udebug, &isClone);
145     if (code) code = VOTE_Debug(tconn, &udebug);
146     if ( code == RXGEN_OPCODE ) 
147     {
148         oldServer = 1;                  /* talking to a pre 3.5 server */
149         memset(&udebug, 0, sizeof(udebug)); 
150         code = VOTE_DebugOld(tconn, &udebug);
151     }
152
153     if (code) {
154         printf("return code %d from VOTE_Debug\n", code);
155         exit(0);
156     }
157     now = time(0);
158
159     /* now print the main info */
160     times = ctime((time_t *)&udebug.now); times[24] = 0;
161     inhostAddr.s_addr = hostAddr;
162     if ( !oldServer )
163     {
164         printf("Host's addresses are: ");
165         for ( j=0; udebug.interfaceAddr[j] && ( j<UBIK_MAX_INTERFACE_ADDR );j++)
166             printf("%s ", afs_inet_ntoa(htonl(udebug.interfaceAddr[j])));
167         printf("\n");
168     }
169     printf("Host's %s time is %s\n",  inet_ntoa(inhostAddr), times);
170
171     times = ctime(&now); times[24] = 0;
172     diff = now - udebug.now;
173     printf("Local time is %s (time differential %d secs)\n", times, diff);
174     if (abs(diff) >= MAXSKEW)
175         printf("****clock may be bad\n");
176
177     /* UBIK skips the voting if 1 server - so we fudge it here */
178     if (udebug.amSyncSite && (udebug.nServers == 1)) {
179        udebug.lastYesHost  = hostAddr;
180        udebug.lastYesTime  = udebug.now;
181        udebug.lastYesState = 1;
182        udebug.lastYesClaim = udebug.now;
183        udebug.syncVersion.epoch   = udebug.localVersion.epoch;
184        udebug.syncVersion.counter = udebug.localVersion.counter;
185     }
186
187     /* sockaddr is always in net-order */
188     if (udebug.lastYesHost == 0xffffffff) {
189        printf("Last yes vote not cast yet \n");
190     } else {
191        inhostAddr.s_addr = htonl(udebug.lastYesHost);
192        diff = udebug.now - udebug.lastYesTime;
193        printf("Last yes vote for %s was %d secs ago (%ssync site); \n",
194               inet_ntoa(inhostAddr), diff, ((udebug.lastYesState)?"":"not "));
195
196        diff = udebug.now - udebug.lastYesClaim;
197        newtime = now - diff;
198        times = ctime(&newtime); times[24] = 0;
199        printf("Last vote started %d secs ago (at %s)\n", diff, times);
200     }
201
202     printf("Local db version is %d.%d\n", udebug.localVersion.epoch, udebug.localVersion.counter);
203
204     if (udebug.amSyncSite) {
205         if (udebug.syncSiteUntil == 0x7fffffff) {
206            printf("I am sync site forever (%d server%s)\n",
207                   udebug.nServers, ((udebug.nServers>1)?"s":""));
208         } else {
209            diff = udebug.syncSiteUntil - udebug.now;
210            newtime = now + diff;
211            times = ctime(&newtime); times[24] = 0;
212            printf("I am sync site until %d secs from now (at %s) (%d server%s)\n",
213                   diff, times, udebug.nServers,
214                   ((udebug.nServers>1)?"s":""));
215         }
216         printf("Recovery state %x\n", udebug.recoveryState);
217         if (udebug.activeWrite) {
218             printf("I am currently managing write trans %d.%d\n",
219                    udebug.epochTime, udebug.tidCounter);
220         }
221     } else {
222         if (isClone) 
223             printf("I am a clone and never can become sync site\n");
224         else
225             printf("I am not sync site\n");
226         inhostAddr.s_addr = htonl(udebug.lowestHost);
227         diff = udebug.now - udebug.lowestTime;
228         printf("Lowest host %s was set %d secs ago\n", inet_ntoa(inhostAddr), diff);
229
230         inhostAddr.s_addr = htonl(udebug.syncHost);
231         diff = udebug.now - udebug.syncTime;
232         printf("Sync host %s was set %d secs ago\n", inet_ntoa(inhostAddr), diff);
233     }
234
235     printf("Sync site's db version is %d.%d\n",
236            udebug.syncVersion.epoch, udebug.syncVersion.counter);
237     printf("%d locked pages, %d of them for write\n",
238            udebug.lockedPages, udebug.writeLockedPages);
239     
240     if (udebug.anyReadLocks)  printf("There are read locks held\n");
241     if (udebug.anyWriteLocks) printf("There are write locks held\n");
242     
243     if (udebug.currentTrans) {
244         if (udebug.writeTrans) printf("There is an active write transaction\n");
245         else printf("There is at least one active read transaction\n");
246         printf("Transaction tid is %d.%d\n", udebug.syncTid.epoch, udebug.syncTid.counter);
247     }
248     if (udebug.epochTime) {
249         diff = udebug.now - udebug.epochTime;
250         newtime = now - diff;
251         times = ctime(&newtime); times[24] = 0;
252         printf("Last time a new db version was labelled was:\n\t %d secs ago (at %s)\n",
253                diff, times);
254     }
255
256     if (int32p || udebug.amSyncSite) {
257         /* now do the subcalls */
258         for(i=0;;i++) {
259             isClone = 0;
260             code = VOTE_XSDebug(tconn, i, &usdebug, &isClone);
261             if (code < 0) {
262                 if ( oldServer ) {                      /* pre 3.5 server */
263                     memset(&usdebug, 0, sizeof(usdebug)); 
264                     code = VOTE_SDebugOld(tconn, i, &usdebug);
265                 }
266                 else
267                     code = VOTE_SDebug(tconn, i, &usdebug);
268             }
269             if (code > 0) break;        /* done */
270             if (code < 0) {
271                 printf("error code %d from VOTE_SDebug\n", code);
272                 break;
273             }
274             inhostAddr.s_addr = htonl(usdebug.addr);
275             /* otherwise print the structure */
276             printf("\nServer (%s", afs_inet_ntoa(htonl(usdebug.addr))); 
277             for ( j=0;((usdebug.altAddr[j]) && 
278                                 (j<UBIK_MAX_INTERFACE_ADDR-1)); j++)
279                 printf(" %s", afs_inet_ntoa(htonl(usdebug.altAddr[j])));
280             printf("): (db %d.%d)",
281                    usdebug.remoteVersion.epoch, usdebug.remoteVersion.counter);
282             if (isClone)
283                 printf("    is only a clone!");
284             printf("\n");
285
286             if (usdebug.lastVoteTime == 0) {
287                printf("    last vote never rcvd \n");
288             } else {
289                diff = udebug.now - usdebug.lastVoteTime;
290                newtime = now - diff;
291                times = ctime(&newtime); times[24] = 0;
292                printf("    last vote rcvd %d secs ago (at %s),\n", diff, times);
293             }
294
295             if (usdebug.lastBeaconSent == 0) {
296                printf("    last beacon never sent \n");
297             } else {
298                diff = udebug.now - usdebug.lastBeaconSent;
299                newtime = now - diff;
300                times = ctime(&newtime); times[24] = 0;
301                printf("    last beacon sent %d secs ago (at %s), last vote was %s\n",
302                       diff, times, ((usdebug.lastVote)?"yes":"no"));
303             }
304
305             printf("    dbcurrent=%d, up=%d beaconSince=%d\n",
306                    usdebug.currentDB, usdebug.up, usdebug.beaconSinceDown);
307         }
308     }
309     return (0);
310 }
311
312 #include "AFS_component_version_number.c"
313
314 int main(int argc, char **argv)
315 {
316     struct cmd_syndesc *ts;
317
318 #ifdef  AFS_AIX32_ENV
319     /*
320      * The following signal action for AIX is necessary so that in case of a 
321      * crash (i.e. core is generated) we can include the user's data section 
322      * in the core dump. Unfortunately, by default, only a partial core is
323      * generated which, in many cases, isn't too useful.
324      */
325     struct sigaction nsa;
326     
327     sigemptyset(&nsa.sa_mask);
328     nsa.sa_handler = SIG_DFL;
329     nsa.sa_flags = SA_FULLDUMP;
330     sigaction(SIGSEGV, &nsa, NULL);
331 #endif
332     ts = cmd_CreateSyntax(NULL, CommandProc, 0, "probe ubik server");
333     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "server machine");
334     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "IP port");
335     cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL, "print all info");
336
337     cmd_Dispatch(argc, argv);
338     exit(0);
339 }