Commit | Line | Data |
---|---|---|
805e021f CE |
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 | } |