2 * Copyright 2000, International Business Machines Corporation and others.
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
12 * Test of the xstat_cm module.
14 *------------------------------------------------------------------------*/
16 #include <afsconfig.h>
17 #include <afs/param.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?
42 static int debugging_on
= 0; /*Are we debugging? */
43 static int one_shot
= 0; /*Single round of data collection? */
45 static char *fsOpNames
[] = {
78 static char *cmOpNames
[] = {
88 static char *xferOpNames
[] = {
94 /* Print detailed functional call statistics */
97 print_cmCallStats(void)
99 char *printableTime
; /*Ptr to printable time string */
101 struct afs_CMStats
*cmp
;
102 time_t probeTime
= xstat_cm_Results
.probeTime
;
104 printableTime
= ctime(&probeTime
);
105 printableTime
[strlen(printableTime
) - 1] = '\0';
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) \
117 printf("\t%10u %s\n", cmp->callInfo.C_ ## call, #call); \
126 /*------------------------------------------------------------------------
130 * Print the up/downtime stats for the given class of server records
134 * a_upDownP : Ptr to the server up/down info.
140 * Nothing interesting.
144 *------------------------------------------------------------------------*/
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
195 * Print out overall performance numbers.
198 * a_ovP : Ptr to the overall performance numbers.
204 * All the info we need is nestled into xstat_cm_Results.
208 *------------------------------------------------------------------------*/
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 /*------------------------------------------------------------------------
283 * Print out the AFSCB_XSTATSCOLL_PERF_INFO collection we just
293 * All the info we need is nestled into xstat_cm_Results.
297 *------------------------------------------------------------------------*/
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");
317 printableTime
= ctime(&probeTime
);
318 printableTime
[strlen(printableTime
) - 1] = '\0';
319 perfP
= (struct afs_stats_CMPerf
*)
320 (xstat_cm_Results
.data
.AFSCB_CollData_val
);
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
);
332 /*------------------------------------------------------------------------
336 * Print out the contents of an FS RPC op timing structure.
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.
347 * Nothing interesting.
351 *------------------------------------------------------------------------*/
354 PrintOpTiming(int a_opIdx
, char *a_opNames
[],
355 struct afs_stats_opTimingData
*a_opTimeP
)
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
);
369 /*------------------------------------------------------------------------
373 * Print out the contents of a data transfer structure.
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.
384 * Nothing interesting.
388 *------------------------------------------------------------------------*/
391 PrintXferTiming(int a_opIdx
, char *a_opNames
[],
392 struct afs_stats_xferData
*a_xferP
)
393 { /*PrintXferTiming */
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
);
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 /*------------------------------------------------------------------------
418 * Print out the contents of an FS RPC error info structure.
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.
429 * Nothing interesting.
433 *------------------------------------------------------------------------*/
436 PrintErrInfo(int a_opIdx
, char *a_opNames
[],
437 struct afs_stats_RPCErrors
*a_opErrP
)
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
);
449 /*------------------------------------------------------------------------
453 * Print out a set of RPC performance numbers.
456 * a_rpcP : Ptr to RPC perf numbers to print.
462 * Nothing interesting.
466 *------------------------------------------------------------------------*/
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 /*------------------------------------------------------------------------
501 * Print out a set of full performance numbers.
510 * Nothing interesting.
514 *------------------------------------------------------------------------*/
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");
537 printableTime
= ctime(&probeTime
);
538 printableTime
[strlen(printableTime
) - 1] = '\0';
539 fullP
= (struct afs_stats_CMFullPerf
*)
540 (xstat_cm_Results
.data
.AFSCB_CollData_val
);
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
));
554 PrintRPCPerfInfo(&(fullP
->rpc
));
556 authentP
= &(fullP
->authent
);
557 printf("\nAuthentication info:\n--------------------\n");
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");
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 /*------------------------------------------------------------------------
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
601 * See above. All we do now is print out what we got.
605 *------------------------------------------------------------------------*/
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
);
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
]);
639 switch (xstat_cm_Results
.collectionNumber
) {
640 case AFSCB_XSTATSCOLL_CALL_INFO
:
644 case AFSCB_XSTATSCOLL_PERF_INFO
:
645 /* we will do nothing here */
646 /* PrintPerfInfo(); */
649 case AFSCB_XSTATSCOLL_FULL_PERF_INFO
:
654 printf("** Unknown collection: %d\n",
655 xstat_cm_Results
.collectionNumber
);
659 * Return the happy news.
666 /*------------------------------------------------------------------------
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.
674 * struct cmd_item *a_firstItem : Ptr to first item in list.
677 * Length of the above list.
680 * Nothing interesting.
684 *------------------------------------------------------------------------*/
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 */
694 curr_item
= a_firstItem
;
701 curr_item
= curr_item
->next
;
709 } /*CountListItems */
712 /*------------------------------------------------------------------------
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.
723 * a_s : Ptr to the command line syntax descriptor.
726 * 0, but may exit the whole program on an error!
729 * Nothing interesting.
733 *------------------------------------------------------------------------*/
736 RunTheTest(struct cmd_syndesc
*a_s
, void *arock
)
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)
764 * Are we doing debugging output?
766 if (a_s
->parms
[P_DEBUG
].items
!= 0)
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
);
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
);
786 period
= 10; /* default to 10 minutes */
789 * Allocate the socket array.
792 printf("%s: Allocating socket array for %d Cache Manager(s)\n", rn
,
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",
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
);
814 fprintf(stderr
, "[%s] Can't get host info for '%s'\n", rn
,
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.
831 printf("Allocating %d long(s) for coll ID\n", numCollIDs
);
834 collIDP
= calloc(numCollIDs
, sizeof(afs_int32
));
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
));
843 printf("CollID at index %d is %d\n", currCollIDIdx
, *currCollIDP
);
844 curr_item
= curr_item
->next
;
849 * Crank up the Cache Manager prober, then sit back and have fun.
851 printf("\nStarting up the xstat_cm service, ");
854 initFlags
|= XSTAT_CM_INITFLAG_DEBUGGING
;
855 printf("debugging enabled, ");
857 printf("no debugging, ");
859 initFlags
|= XSTAT_CM_INITFLAG_ONE_SHOT
;
860 printf("one-shot operation\n");
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 */
872 fprintf(stderr
, "[%s] Error returned by xstat_cm_Init: %d\n", rn
,
874 xstat_cm_Cleanup(1); /*Get rid of malloc'ed structures */
880 * One-shot operation; just wait for the collection to be done.
883 printf("[%s] Calling LWP_WaitProcess() on event %" AFS_PTR_FMT
884 "\n", rn
, &terminationEvent
);
885 waitCode
= LWP_WaitProcess(&terminationEvent
);
887 printf("[%s] Returned from LWP_WaitProcess()\n", rn
);
891 "[%s] Error %d encountered by LWP_WaitProcess()\n",
896 * Continuous operation.
898 sleep_secs
= 60 * period
; /*length of data collection */
900 ("xstat_cm service started, main thread sleeping for %d secs.\n",
904 * Let's just fall asleep for a while, then we'll clean up.
906 tv
.tv_sec
= sleep_secs
;
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 */
915 "[%s] IOMGR_Select() returned non-zero value: %d\n", rn
,
921 * We're all done. Clean up, put the last nail in Rx, then
925 printf("\nYawn, main thread just woke up. Cleaning things out...\n");
926 xstat_cm_Cleanup(1); /*Get rid of malloc'ed data */
933 #include "AFS_component_version_number.c"
935 main(int argc
, char **argv
)
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
963 code
= cmd_Dispatch(argc
, argv
);
965 fprintf(stderr
, "[%s] Call to cmd_Dispatch() failed; code is %d\n",