Some doc path fixes from Anders
[pkg-k5-afs_openafs.git] / src / xstat / xstat_cm_test.c
blobb284237aa9136a7e1c800dba17f8cdbc312d45cb
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
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 */
11 * Description:
12 * Test of the xstat_cm module.
14 *------------------------------------------------------------------------*/
16 #include <afsconfig.h>
17 #include <afs/param.h>
19 #include <roken.h>
21 #include "xstat_cm.h" /*Interface for xstat_cm module */
22 #include <afs/cmd.h> /*Command line interpreter */
23 #include <afs/afsutil.h>
26 * Command line parameter indices.
27 * P_CM_NAMES : List of CacheManager names.
28 * P_COLL_IDS : List of collection IDs to pick up.
29 * P_ONESHOT : Are we gathering exactly one round of data?
30 * P_DEBUG : Enable debugging output?
32 #define P_CM_NAMES 0
33 #define P_COLL_IDS 1
34 #define P_ONESHOT 2
35 #define P_FREQUENCY 3
36 #define P_PERIOD 4
37 #define P_DEBUG 5
40 * Private globals.
42 static int debugging_on = 0; /*Are we debugging? */
43 static int one_shot = 0; /*Single round of data collection? */
45 static char *fsOpNames[] = {
46 "FetchData",
47 "FetchACL",
48 "FetchStatus",
49 "StoreData",
50 "StoreACL",
51 "StoreStatus",
52 "RemoveFile",
53 "CreateFile",
54 "Rename",
55 "Symlink",
56 "Link",
57 "MakeDir",
58 "RemoveDir",
59 "SetLock",
60 "ExtendLock",
61 "ReleaseLock",
62 "GetStatistics",
63 "GiveUpCallbacks",
64 "GetVolumeInfo",
65 "GetVolumeStatus",
66 "SetVolumeStatus",
67 "GetRootVolume",
68 "CheckToken",
69 "GetTime",
70 "NGetVolumeInfo",
71 "BulkStatus",
72 "XStatsVersion",
73 "GetXStats",
74 "XLookup",
75 "ResidencyRpc"
78 static char *cmOpNames[] = {
79 "CallBack",
80 "InitCallBackState",
81 "Probe",
82 "GetLock",
83 "GetCE",
84 "XStatsVersion",
85 "GetXStats"
88 static char *xferOpNames[] = {
89 "FetchData",
90 "StoreData"
94 /* Print detailed functional call statistics */
96 void
97 print_cmCallStats(void)
99 char *printableTime; /*Ptr to printable time string */
100 afs_int32 nitems;
101 struct afs_CMStats *cmp;
102 time_t probeTime = xstat_cm_Results.probeTime;
104 printableTime = ctime(&probeTime);
105 printableTime[strlen(printableTime) - 1] = '\0';
107 printf
108 ("AFSCB_XSTATSCOLL_CALL_INFO (coll %d) for CM %s\n[Probe %u, %s]\n\n",
109 xstat_cm_Results.collectionNumber, xstat_cm_Results.connP->hostName,
110 xstat_cm_Results.probeNum, printableTime);
112 cmp = (struct afs_CMStats *)(xstat_cm_Results.data.AFSCB_CollData_val);
113 nitems = xstat_cm_Results.data.AFSCB_CollData_len;
115 #define AFS_CS(call) \
116 if (nitems > 0) { \
117 printf("\t%10u %s\n", cmp->callInfo.C_ ## call, #call); \
118 nitems--; \
121 AFS_CM_CALL_STATS
122 #undef AFS_CS
126 /*------------------------------------------------------------------------
127 * PrintUpDownStats
129 * Description:
130 * Print the up/downtime stats for the given class of server records
131 * provided.
133 * Arguments:
134 * a_upDownP : Ptr to the server up/down info.
136 * Returns:
137 * Nothing.
139 * Environment:
140 * Nothing interesting.
142 * Side Effects:
143 * As advertised.
144 *------------------------------------------------------------------------*/
146 void
147 PrintUpDownStats(struct afs_stats_SrvUpDownInfo *a_upDownP)
148 { /*PrintUpDownStats */
151 * First, print the simple values.
153 printf("\t\t%10u numTtlRecords\n", a_upDownP->numTtlRecords);
154 printf("\t\t%10u numUpRecords\n", a_upDownP->numUpRecords);
155 printf("\t\t%10u numDownRecords\n", a_upDownP->numDownRecords);
156 printf("\t\t%10u sumOfRecordAges\n", a_upDownP->sumOfRecordAges);
157 printf("\t\t%10u ageOfYoungestRecord\n", a_upDownP->ageOfYoungestRecord);
158 printf("\t\t%10u ageOfOldestRecord\n", a_upDownP->ageOfOldestRecord);
159 printf("\t\t%10u numDowntimeIncidents\n",
160 a_upDownP->numDowntimeIncidents);
161 printf("\t\t%10u numRecordsNeverDown\n", a_upDownP->numRecordsNeverDown);
162 printf("\t\t%10u maxDowntimesInARecord\n",
163 a_upDownP->maxDowntimesInARecord);
164 printf("\t\t%10u sumOfDowntimes\n", a_upDownP->sumOfDowntimes);
165 printf("\t\t%10u shortestDowntime\n", a_upDownP->shortestDowntime);
166 printf("\t\t%10u longestDowntime\n", a_upDownP->longestDowntime);
169 * Now, print the array values.
171 printf("\t\tDowntime duration distribution:\n");
172 printf("\t\t\t%8u: 0 min .. 10 min\n", a_upDownP->downDurations[0]);
173 printf("\t\t\t%8u: 10 min .. 30 min\n", a_upDownP->downDurations[1]);
174 printf("\t\t\t%8u: 30 min .. 1 hr\n", a_upDownP->downDurations[2]);
175 printf("\t\t\t%8u: 1 hr .. 2 hr\n", a_upDownP->downDurations[3]);
176 printf("\t\t\t%8u: 2 hr .. 4 hr\n", a_upDownP->downDurations[4]);
177 printf("\t\t\t%8u: 4 hr .. 8 hr\n", a_upDownP->downDurations[5]);
178 printf("\t\t\t%8u: > 8 hr\n", a_upDownP->downDurations[6]);
180 printf("\t\tDowntime incident distribution:\n");
181 printf("\t\t\t%8u: 0 times\n", a_upDownP->downIncidents[0]);
182 printf("\t\t\t%8u: 1 time\n", a_upDownP->downIncidents[1]);
183 printf("\t\t\t%8u: 2 .. 5 times\n", a_upDownP->downIncidents[2]);
184 printf("\t\t\t%8u: 6 .. 10 times\n", a_upDownP->downIncidents[3]);
185 printf("\t\t\t%8u: 10 .. 50 times\n", a_upDownP->downIncidents[4]);
186 printf("\t\t\t%8u: > 50 times\n", a_upDownP->downIncidents[5]);
188 } /*PrintUpDownStats */
191 /*------------------------------------------------------------------------
192 * PrintOverallPerfInfo
194 * Description:
195 * Print out overall performance numbers.
197 * Arguments:
198 * a_ovP : Ptr to the overall performance numbers.
200 * Returns:
201 * Nothing.
203 * Environment:
204 * All the info we need is nestled into xstat_cm_Results.
206 * Side Effects:
207 * As advertised.
208 *------------------------------------------------------------------------*/
210 void
211 PrintOverallPerfInfo(struct afs_stats_CMPerf *a_ovP)
212 { /*PrintOverallPerfInfo */
214 printf("\t%10u numPerfCalls\n", a_ovP->numPerfCalls);
216 printf("\t%10u epoch\n", a_ovP->epoch);
217 printf("\t%10u numCellsVisible\n", a_ovP->numCellsVisible);
218 printf("\t%10u numCellsContacted\n", a_ovP->numCellsContacted);
219 printf("\t%10u dlocalAccesses\n", a_ovP->dlocalAccesses);
220 printf("\t%10u vlocalAccesses\n", a_ovP->vlocalAccesses);
221 printf("\t%10u dremoteAccesses\n", a_ovP->dremoteAccesses);
222 printf("\t%10u vremoteAccesses\n", a_ovP->vremoteAccesses);
223 printf("\t%10u cacheNumEntries\n", a_ovP->cacheNumEntries);
224 printf("\t%10u cacheBlocksTotal\n", a_ovP->cacheBlocksTotal);
225 printf("\t%10u cacheBlocksInUse\n", a_ovP->cacheBlocksInUse);
226 printf("\t%10u cacheBlocksOrig\n", a_ovP->cacheBlocksOrig);
227 printf("\t%10u cacheMaxDirtyChunks\n", a_ovP->cacheMaxDirtyChunks);
228 printf("\t%10u cacheCurrDirtyChunks\n", a_ovP->cacheCurrDirtyChunks);
229 printf("\t%10u dcacheHits\n", a_ovP->dcacheHits);
230 printf("\t%10u vcacheHits\n", a_ovP->vcacheHits);
231 printf("\t%10u dcacheMisses\n", a_ovP->dcacheMisses);
232 printf("\t%10u vcacheMisses\n", a_ovP->vcacheMisses);
233 printf("\t%10u cacheFilesReused\n", a_ovP->cacheFilesReused);
234 printf("\t%10u vcacheXAllocs\n", a_ovP->vcacheXAllocs);
235 printf("\t%10u dcacheXAllocs\n", a_ovP->dcacheXAllocs);
237 printf("\t%10u bufAlloced\n", a_ovP->bufAlloced);
238 printf("\t%10u bufHits\n", a_ovP->bufHits);
239 printf("\t%10u bufMisses\n", a_ovP->bufMisses);
240 printf("\t%10u bufFlushDirty\n", a_ovP->bufFlushDirty);
242 printf("\t%10u LargeBlocksActive\n", a_ovP->LargeBlocksActive);
243 printf("\t%10u LargeBlocksAlloced\n", a_ovP->LargeBlocksAlloced);
244 printf("\t%10u SmallBlocksActive\n", a_ovP->SmallBlocksActive);
245 printf("\t%10u SmallBlocksAlloced\n", a_ovP->SmallBlocksAlloced);
246 printf("\t%10u OutStandingMemUsage\n", a_ovP->OutStandingMemUsage);
247 printf("\t%10u OutStandingAllocs\n", a_ovP->OutStandingAllocs);
248 printf("\t%10u CallBackAlloced\n", a_ovP->CallBackAlloced);
249 printf("\t%10u CallBackFlushes\n", a_ovP->CallBackFlushes);
250 printf("\t%10u CallBackLoops\n", a_ovP->cbloops);
252 printf("\t%10u srvRecords\n", a_ovP->srvRecords);
253 printf("\t%10u srvNumBuckets\n", a_ovP->srvNumBuckets);
254 printf("\t%10u srvMaxChainLength\n", a_ovP->srvMaxChainLength);
255 printf("\t%10u srvMaxChainLengthHWM\n", a_ovP->srvMaxChainLengthHWM);
256 printf("\t%10u srvRecordsHWM\n", a_ovP->srvRecordsHWM);
258 printf("\t%10u cacheBucket0_Discarded\n", a_ovP->cacheBucket0_Discarded);
259 printf("\t%10u cacheBucket1_Discarded\n", a_ovP->cacheBucket1_Discarded);
260 printf("\t%10u cacheBucket2_Discarded\n", a_ovP->cacheBucket2_Discarded);
262 printf("\t%10u sysName_ID\n", a_ovP->sysName_ID);
264 printf("\tFile Server up/downtimes, same cell:\n");
265 PrintUpDownStats(&(a_ovP->fs_UpDown[0]));
267 printf("\tFile Server up/downtimes, diff cell:\n");
268 PrintUpDownStats(&(a_ovP->fs_UpDown[1]));
270 printf("\tVL Server up/downtimes, same cell:\n");
271 PrintUpDownStats(&(a_ovP->vl_UpDown[0]));
273 printf("\tVL Server up/downtimes, diff cell:\n");
274 PrintUpDownStats(&(a_ovP->vl_UpDown[1]));
276 } /*PrintOverallPerfInfo */
279 /*------------------------------------------------------------------------
280 * PrintPerfInfo
282 * Description:
283 * Print out the AFSCB_XSTATSCOLL_PERF_INFO collection we just
284 * received.
286 * Arguments:
287 * None.
289 * Returns:
290 * Nothing.
292 * Environment:
293 * All the info we need is nestled into xstat_cm_Results.
295 * Side Effects:
296 * As advertised.
297 *------------------------------------------------------------------------*/
299 void
300 PrintPerfInfo(void)
301 { /*PrintPerfInfo */
303 static afs_int32 perfInt32s = (sizeof(struct afs_stats_CMPerf) >> 2); /*Correct # int32s to rcv */
304 afs_int32 numInt32s; /*# int32words received */
305 struct afs_stats_CMPerf *perfP; /*Ptr to performance stats */
306 char *printableTime; /*Ptr to printable time string */
307 time_t probeTime = xstat_cm_Results.probeTime;
309 numInt32s = xstat_cm_Results.data.AFSCB_CollData_len;
310 if (numInt32s != perfInt32s) {
311 printf("** Data size mismatch in performance collection!");
312 printf("** Expecting %u, got %u\n", perfInt32s, numInt32s);
313 printf("** Version mismatch with Cache Manager\n");
314 return;
317 printableTime = ctime(&probeTime);
318 printableTime[strlen(printableTime) - 1] = '\0';
319 perfP = (struct afs_stats_CMPerf *)
320 (xstat_cm_Results.data.AFSCB_CollData_val);
322 printf
323 ("AFSCB_XSTATSCOLL_PERF_INFO (coll %d) for CM %s\n[Probe %u, %s]\n\n",
324 xstat_cm_Results.collectionNumber, xstat_cm_Results.connP->hostName,
325 xstat_cm_Results.probeNum, printableTime);
327 PrintOverallPerfInfo(perfP);
329 } /*PrintPerfInfo */
332 /*------------------------------------------------------------------------
333 * PrintOpTiming
335 * Description:
336 * Print out the contents of an FS RPC op timing structure.
338 * Arguments:
339 * a_opIdx : Index of the AFS operation we're printing number on.
340 * a_opNames : Ptr to table of operaton names.
341 * a_opTimeP : Ptr to the op timing structure to print.
343 * Returns:
344 * Nothing.
346 * Environment:
347 * Nothing interesting.
349 * Side Effects:
350 * As advertised.
351 *------------------------------------------------------------------------*/
353 void
354 PrintOpTiming(int a_opIdx, char *a_opNames[],
355 struct afs_stats_opTimingData *a_opTimeP)
356 { /*PrintOpTiming */
358 printf
359 ("%15s: %u ops (%u OK); sum=%lu.%06lu, sqr=%lu.%06lu, min=%lu.%06lu, max=%lu.%06lu\n",
360 a_opNames[a_opIdx], a_opTimeP->numOps, a_opTimeP->numSuccesses,
361 (long)a_opTimeP->sumTime.tv_sec, (long)a_opTimeP->sumTime.tv_usec,
362 (long)a_opTimeP->sqrTime.tv_sec, (long)a_opTimeP->sqrTime.tv_usec,
363 (long)a_opTimeP->minTime.tv_sec, (long)a_opTimeP->minTime.tv_usec,
364 (long)a_opTimeP->maxTime.tv_sec, (long)a_opTimeP->maxTime.tv_usec);
366 } /*PrintOpTiming */
369 /*------------------------------------------------------------------------
370 * PrintXferTiming
372 * Description:
373 * Print out the contents of a data transfer structure.
375 * Arguments:
376 * a_opIdx : Index of the AFS operation we're printing number on.
377 * a_opNames : Ptr to table of operation names.
378 * a_xferP : Ptr to the data transfer structure to print.
380 * Returns:
381 * Nothing.
383 * Environment:
384 * Nothing interesting.
386 * Side Effects:
387 * As advertised.
388 *------------------------------------------------------------------------*/
390 void
391 PrintXferTiming(int a_opIdx, char *a_opNames[],
392 struct afs_stats_xferData *a_xferP)
393 { /*PrintXferTiming */
395 printf
396 ("%s: %u xfers (%u OK), time sum=%lu.%06lu, sqr=%lu.%06lu, min=%lu.%06lu, max=%lu.%06lu\n",
397 a_opNames[a_opIdx], a_xferP->numXfers, a_xferP->numSuccesses,
398 (long)a_xferP->sumTime.tv_sec, (long)a_xferP->sumTime.tv_usec,
399 (long)a_xferP->sqrTime.tv_sec, (long)a_xferP->sqrTime.tv_usec,
400 (long)a_xferP->minTime.tv_sec, (long)a_xferP->minTime.tv_usec,
401 (long)a_xferP->maxTime.tv_sec, (long)a_xferP->maxTime.tv_usec);
402 printf("\t[bytes: sum=%u, min=%u, max=%u]\n", a_xferP->sumBytes,
403 a_xferP->minBytes, a_xferP->maxBytes);
404 printf
405 ("\t[buckets: 0: %u, 1: %u, 2: %u, 3: %u, 4: %u, 5: %u, 6: %u, 7: %u, 8: %u]\n",
406 a_xferP->count[0], a_xferP->count[1], a_xferP->count[2],
407 a_xferP->count[3], a_xferP->count[4], a_xferP->count[5],
408 a_xferP->count[6], a_xferP->count[7], a_xferP->count[8]);
411 } /*PrintXferTiming */
414 /*------------------------------------------------------------------------
415 * PrintErrInfo
417 * Description:
418 * Print out the contents of an FS RPC error info structure.
420 * Arguments:
421 * a_opIdx : Index of the AFS operation we're printing.
422 * a_opNames : Ptr to table of operation names.
423 * a_opErrP : Ptr to the op timing structure to print.
425 * Returns:
426 * Nothing.
428 * Environment:
429 * Nothing interesting.
431 * Side Effects:
432 * As advertised.
433 *------------------------------------------------------------------------*/
435 void
436 PrintErrInfo(int a_opIdx, char *a_opNames[],
437 struct afs_stats_RPCErrors *a_opErrP)
438 { /*PrintErrInfo */
440 printf
441 ("%15s: %u server, %u network, %u prot, %u vol, %u busies, %u other\n",
442 a_opNames[a_opIdx], a_opErrP->err_Server, a_opErrP->err_Network,
443 a_opErrP->err_Protection, a_opErrP->err_Volume,
444 a_opErrP->err_VolumeBusies, a_opErrP->err_Other);
446 } /*PrintErrInfo */
449 /*------------------------------------------------------------------------
450 * PrintRPCPerfInfo
452 * Description:
453 * Print out a set of RPC performance numbers.
455 * Arguments:
456 * a_rpcP : Ptr to RPC perf numbers to print.
458 * Returns:
459 * Nothing.
461 * Environment:
462 * Nothing interesting.
464 * Side Effects:
465 * As advertised.
466 *------------------------------------------------------------------------*/
468 void
469 PrintRPCPerfInfo(struct afs_stats_RPCOpInfo *a_rpcP)
470 { /*PrintRPCPerfInfo */
472 int currIdx; /*Loop variable */
475 * Print the contents of each of the opcode-related arrays.
477 printf("FS Operation Timings:\n---------------------\n");
478 for (currIdx = 0; currIdx < AFS_STATS_NUM_FS_RPC_OPS; currIdx++)
479 PrintOpTiming(currIdx, fsOpNames, &(a_rpcP->fsRPCTimes[currIdx]));
481 printf("\nError Info:\n-----------\n");
482 for (currIdx = 0; currIdx < AFS_STATS_NUM_FS_RPC_OPS; currIdx++)
483 PrintErrInfo(currIdx, fsOpNames, &(a_rpcP->fsRPCErrors[currIdx]));
485 printf("\nTransfer timings:\n-----------------\n");
486 for (currIdx = 0; currIdx < AFS_STATS_NUM_FS_XFER_OPS; currIdx++)
487 PrintXferTiming(currIdx, xferOpNames,
488 &(a_rpcP->fsXferTimes[currIdx]));
490 printf("\nCM Operation Timings:\n---------------------\n");
491 for (currIdx = 0; currIdx < AFS_STATS_NUM_CM_RPC_OPS; currIdx++)
492 PrintOpTiming(currIdx, cmOpNames, &(a_rpcP->cmRPCTimes[currIdx]));
494 } /*PrintRPCPerfInfo */
497 /*------------------------------------------------------------------------
498 * PrintFullPerfInfo
500 * Description:
501 * Print out a set of full performance numbers.
503 * Arguments:
504 * None.
506 * Returns:
507 * Nothing.
509 * Environment:
510 * Nothing interesting.
512 * Side Effects:
513 * As advertised.
514 *------------------------------------------------------------------------*/
516 void
517 PrintFullPerfInfo(void)
518 { /*PrintFullPerfInfo */
520 struct afs_stats_AuthentInfo *authentP; /*Ptr to authentication stats */
521 struct afs_stats_AccessInfo *accessinfP; /*Ptr to access stats */
522 static afs_int32 fullPerfInt32s = (sizeof(struct afs_stats_CMFullPerf) >> 2); /*Correct #int32s */
523 afs_int32 numInt32s; /*# int32s actually received */
524 struct afs_stats_CMFullPerf *fullP; /*Ptr to full perf info */
526 char *printableTime; /*Ptr to printable time string */
527 time_t probeTime = xstat_cm_Results.probeTime;
529 numInt32s = xstat_cm_Results.data.AFSCB_CollData_len;
530 if (numInt32s != fullPerfInt32s) {
531 printf("** Data size mismatch in performance collection!");
532 printf("** Expecting %u, got %u\n", fullPerfInt32s, numInt32s);
533 printf("** Version mismatch with Cache Manager\n");
534 return;
537 printableTime = ctime(&probeTime);
538 printableTime[strlen(printableTime) - 1] = '\0';
539 fullP = (struct afs_stats_CMFullPerf *)
540 (xstat_cm_Results.data.AFSCB_CollData_val);
542 printf
543 ("AFSCB_XSTATSCOLL_FULL_PERF_INFO (coll %d) for CM %s\n[Probe %u, %s]\n\n",
544 xstat_cm_Results.collectionNumber, xstat_cm_Results.connP->hostName,
545 xstat_cm_Results.probeNum, printableTime);
548 * Print the overall numbers first, followed by all of the RPC numbers,
549 * then each of the other groupings.
551 printf("Overall Performance Info:\n-------------------------\n");
552 PrintOverallPerfInfo(&(fullP->perf));
553 printf("\n");
554 PrintRPCPerfInfo(&(fullP->rpc));
556 authentP = &(fullP->authent);
557 printf("\nAuthentication info:\n--------------------\n");
558 printf
559 ("\t%u PAGS, %u records (%u auth, %u unauth), %u max in PAG, chain max: %u\n",
560 authentP->curr_PAGs, authentP->curr_Records,
561 authentP->curr_AuthRecords, authentP->curr_UnauthRecords,
562 authentP->curr_MaxRecordsInPAG, authentP->curr_LongestChain);
563 printf("\t%u PAG creations, %u tkt updates\n", authentP->PAGCreations,
564 authentP->TicketUpdates);
565 printf("\t[HWMs: %u PAGS, %u records, %u max in PAG, chain max: %u]\n",
566 authentP->HWM_PAGs, authentP->HWM_Records,
567 authentP->HWM_MaxRecordsInPAG, authentP->HWM_LongestChain);
569 accessinfP = &(fullP->accessinf);
570 printf("\n[Un]replicated accesses:\n------------------------\n");
571 printf
572 ("\t%u unrep, %u rep, %u reps accessed, %u max reps/ref, %u first OK\n\n",
573 accessinfP->unreplicatedRefs, accessinfP->replicatedRefs,
574 accessinfP->numReplicasAccessed, accessinfP->maxReplicasPerRef,
575 accessinfP->refFirstReplicaOK);
577 /* There really isn't any authorship info
578 * authorP = &(fullP->author); */
580 } /*PrintFullPerfInfo */
583 /*------------------------------------------------------------------------
584 * CM_Handler
586 * Description:
587 * Handler routine passed to the xstat_cm module. This handler is
588 * called immediately after a poll of one of the Cache Managers has
589 * taken place. All it needs to know is exported by the xstat_cm
590 * module, namely the data structure where the probe results are
591 * stored.
593 * Arguments:
594 * None.
596 * Returns:
597 * 0 on success,
598 * -1 otherwise.
600 * Environment:
601 * See above. All we do now is print out what we got.
603 * Side Effects:
604 * As advertised.
605 *------------------------------------------------------------------------*/
608 CM_Handler(void)
609 { /*CM_Handler */
611 static char rn[] = "CM_Handler"; /*Routine name */
613 printf("\n-----------------------------------------------------------\n");
616 * If the probe failed, there isn't much we can do except gripe.
618 if (xstat_cm_Results.probeOK) {
619 printf("%s: Probe %u, collection %d to CM on '%s' failed, code=%d\n",
620 rn, xstat_cm_Results.probeNum,
621 xstat_cm_Results.collectionNumber,
622 xstat_cm_Results.connP->hostName, xstat_cm_Results.probeOK);
623 return (0);
626 if (debugging_on) {
627 int i;
628 int numInt32s = xstat_cm_Results.data.AFSCB_CollData_len;
629 afs_int32 *entry = xstat_cm_Results.data.AFSCB_CollData_val;
631 printf("debug: got collection number %d\n", xstat_cm_Results.collectionNumber);
632 printf("debug: collection data length is %d\n", numInt32s);
633 for (i = 0; i < numInt32s; i++) {
634 printf("debug: entry %d %u\n", i, entry[i]);
636 printf("\n");
639 switch (xstat_cm_Results.collectionNumber) {
640 case AFSCB_XSTATSCOLL_CALL_INFO:
641 print_cmCallStats();
642 break;
644 case AFSCB_XSTATSCOLL_PERF_INFO:
645 /* we will do nothing here */
646 /* PrintPerfInfo(); */
647 break;
649 case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
650 PrintFullPerfInfo();
651 break;
653 default:
654 printf("** Unknown collection: %d\n",
655 xstat_cm_Results.collectionNumber);
659 * Return the happy news.
661 return (0);
663 } /*CM_Handler */
666 /*------------------------------------------------------------------------
667 * CountListItems
669 * Description:
670 * Given a pointer to the list of Cache Managers we'll be polling
671 * (or, in fact, any list at all), compute the length of the list.
673 * Arguments:
674 * struct cmd_item *a_firstItem : Ptr to first item in list.
676 * Returns:
677 * Length of the above list.
679 * Environment:
680 * Nothing interesting.
682 * Side Effects:
683 * As advertised.
684 *------------------------------------------------------------------------*/
686 static int
687 CountListItems(struct cmd_item *a_firstItem)
688 { /*CountListItems */
690 int list_len; /*List length */
691 struct cmd_item *curr_item; /*Ptr to current item */
693 list_len = 0;
694 curr_item = a_firstItem;
697 * Count 'em up.
699 while (curr_item) {
700 list_len++;
701 curr_item = curr_item->next;
705 * Return our tally.
707 return (list_len);
709 } /*CountListItems */
712 /*------------------------------------------------------------------------
713 * RunTheTest
715 * Description:
716 * Routine called by the command line interpreter to execute the
717 * meat of the program. We count the number of Cache Managers
718 * to watch, allocate enough space to remember all the connection
719 * info for them, then go for it.
722 * Arguments:
723 * a_s : Ptr to the command line syntax descriptor.
725 * Returns:
726 * 0, but may exit the whole program on an error!
728 * Environment:
729 * Nothing interesting.
731 * Side Effects:
732 * As advertised.
733 *------------------------------------------------------------------------*/
736 RunTheTest(struct cmd_syndesc *a_s, void *arock)
737 { /*RunTheTest */
739 static char rn[] = "RunTheTest"; /*Routine name */
740 int code; /*Return code */
741 int numCMs; /*# Cache Managers to monitor */
742 int numCollIDs; /*# collections to fetch */
743 int currCM; /*Loop index */
744 int currCollIDIdx; /*Index of current collection ID */
745 afs_int32 *collIDP; /*Ptr to array of collection IDs */
746 afs_int32 *currCollIDP; /*Ptr to current collection ID */
747 struct cmd_item *curr_item; /*Current CM cmd line record */
748 struct sockaddr_in *CMSktArray; /*Cache Manager socket array */
749 struct hostent *he; /*Host entry */
750 struct timeval tv; /*Time structure */
751 int sleep_secs; /*Number of seconds to sleep */
752 int initFlags; /*Flags passed to the init fcn */
753 int waitCode; /*Result of LWP_WaitProcess() */
754 int freq; /*Frequency of polls */
755 int period; /*Time in minutes of data collection */
758 * Are we doing one-shot measurements?
760 if (a_s->parms[P_ONESHOT].items != 0)
761 one_shot = 1;
764 * Are we doing debugging output?
766 if (a_s->parms[P_DEBUG].items != 0)
767 debugging_on = 1;
770 * Pull out the number of Cache Managers to watch and the number of
771 * collections to get.
773 numCMs = CountListItems(a_s->parms[P_CM_NAMES].items);
774 numCollIDs = CountListItems(a_s->parms[P_COLL_IDS].items);
776 /* Get the polling frequency */
777 if (a_s->parms[P_FREQUENCY].items != 0)
778 freq = atoi(a_s->parms[P_FREQUENCY].items->data);
779 else
780 freq = 30; /* default to 30 seconds */
782 /* Get the time duration to run the tests */
783 if (a_s->parms[P_PERIOD].items != 0)
784 period = atoi(a_s->parms[P_PERIOD].items->data);
785 else
786 period = 10; /* default to 10 minutes */
789 * Allocate the socket array.
791 if (debugging_on)
792 printf("%s: Allocating socket array for %d Cache Manager(s)\n", rn,
793 numCMs);
794 if (numCMs > 0) {
795 CMSktArray = calloc(numCMs, sizeof(struct sockaddr_in));
796 if (CMSktArray == NULL) {
797 printf("%s: Can't allocate socket array for %d Cache Managers\n",
798 rn, numCMs);
799 exit(1);
801 } else {
802 CMSktArray = NULL;
806 * Fill in the socket array for each of the Cache Managers listed.
808 curr_item = a_s->parms[P_CM_NAMES].items;
809 for (currCM = 0; currCM < numCMs; currCM++) {
810 CMSktArray[currCM].sin_family = AF_INET;
811 CMSktArray[currCM].sin_port = htons(7001); /* Cache Manager port */
812 he = hostutil_GetHostByName(curr_item->data);
813 if (he == NULL) {
814 fprintf(stderr, "[%s] Can't get host info for '%s'\n", rn,
815 curr_item->data);
816 exit(-1);
818 memcpy(&(CMSktArray[currCM].sin_addr.s_addr), he->h_addr, 4);
821 * Move to the next CM name.
823 curr_item = curr_item->next;
825 } /*Get socket info for each Cache Manager */
828 * Create and fill up the array of desired collection IDs.
830 if (debugging_on)
831 printf("Allocating %d long(s) for coll ID\n", numCollIDs);
833 if (numCollIDs > 0)
834 collIDP = calloc(numCollIDs, sizeof(afs_int32));
835 else
836 collIDP = NULL;
838 currCollIDP = collIDP;
839 curr_item = a_s->parms[P_COLL_IDS].items;
840 for (currCollIDIdx = 0; currCollIDIdx < numCollIDs; currCollIDIdx++) {
841 *currCollIDP = (afs_int32) (atoi(curr_item->data));
842 if (debugging_on)
843 printf("CollID at index %d is %d\n", currCollIDIdx, *currCollIDP);
844 curr_item = curr_item->next;
845 currCollIDP++;
849 * Crank up the Cache Manager prober, then sit back and have fun.
851 printf("\nStarting up the xstat_cm service, ");
852 initFlags = 0;
853 if (debugging_on) {
854 initFlags |= XSTAT_CM_INITFLAG_DEBUGGING;
855 printf("debugging enabled, ");
856 } else
857 printf("no debugging, ");
858 if (one_shot) {
859 initFlags |= XSTAT_CM_INITFLAG_ONE_SHOT;
860 printf("one-shot operation\n");
861 } else
862 printf("continuous operation\n");
864 code = xstat_cm_Init(numCMs, /*Num CMs */
865 CMSktArray, /*File Server socket array */
866 freq, /*Probe every 30 seconds */
867 CM_Handler, /*Handler routine */
868 initFlags, /*Initialization flags */
869 numCollIDs, /*Number of collection IDs */
870 collIDP); /*Ptr to collection ID array */
871 if (code) {
872 fprintf(stderr, "[%s] Error returned by xstat_cm_Init: %d\n", rn,
873 code);
874 xstat_cm_Cleanup(1); /*Get rid of malloc'ed structures */
875 exit(-1);
878 if (one_shot) {
880 * One-shot operation; just wait for the collection to be done.
882 if (debugging_on)
883 printf("[%s] Calling LWP_WaitProcess() on event %" AFS_PTR_FMT
884 "\n", rn, &terminationEvent);
885 waitCode = LWP_WaitProcess(&terminationEvent);
886 if (debugging_on)
887 printf("[%s] Returned from LWP_WaitProcess()\n", rn);
888 if (waitCode) {
889 if (debugging_on)
890 fprintf(stderr,
891 "[%s] Error %d encountered by LWP_WaitProcess()\n",
892 rn, waitCode);
894 } else {
896 * Continuous operation.
898 sleep_secs = 60 * period; /*length of data collection */
899 printf
900 ("xstat_cm service started, main thread sleeping for %d secs.\n",
901 sleep_secs);
904 * Let's just fall asleep for a while, then we'll clean up.
906 tv.tv_sec = sleep_secs;
907 tv.tv_usec = 0;
908 code = IOMGR_Select(0, /*Num fds */
909 0, /*Descriptors ready for reading */
910 0, /*Descriptors ready for writing */
911 0, /*Descriptors with exceptional conditions */
912 &tv); /*Timeout structure */
913 if (code) {
914 fprintf(stderr,
915 "[%s] IOMGR_Select() returned non-zero value: %d\n", rn,
916 code);
921 * We're all done. Clean up, put the last nail in Rx, then
922 * exit happily.
924 if (debugging_on)
925 printf("\nYawn, main thread just woke up. Cleaning things out...\n");
926 xstat_cm_Cleanup(1); /*Get rid of malloc'ed data */
927 rx_Finalize();
928 return (0);
930 } /*RunTheTest */
933 #include "AFS_component_version_number.c"
935 main(int argc, char **argv)
936 { /*Main routine */
938 static char rn[] = "xstat_cm_test"; /*Routine name */
939 afs_int32 code; /*Return code */
940 struct cmd_syndesc *ts; /*Ptr to cmd line syntax desc */
943 * Set up the commands we understand.
945 ts = cmd_CreateSyntax("initcmd", RunTheTest, NULL, 0, "initialize the program");
946 cmd_AddParm(ts, "-cmname", CMD_LIST, CMD_REQUIRED,
947 "Cache Manager name(s) to monitor");
948 cmd_AddParm(ts, "-collID", CMD_LIST, CMD_REQUIRED,
949 "Collection(s) to fetch");
950 cmd_AddParm(ts, "-onceonly", CMD_FLAG, CMD_OPTIONAL,
951 "Collect results exactly once, then quit");
952 cmd_AddParm(ts, "-frequency", CMD_SINGLE, CMD_OPTIONAL,
953 "poll frequency, in seconds");
954 cmd_AddParm(ts, "-period", CMD_SINGLE, CMD_OPTIONAL,
955 "data collection time, in minutes");
956 cmd_AddParm(ts, "-debug", CMD_FLAG, CMD_OPTIONAL,
957 "turn on debugging output");
960 * Parse command-line switches & execute the test, then get the
961 * heck out of here.
963 code = cmd_Dispatch(argc, argv);
964 if (code) {
965 fprintf(stderr, "[%s] Call to cmd_Dispatch() failed; code is %d\n",
966 rn, code);
969 exit(code);
971 } /*Main routine */