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 int initFlags; /*Flags passed to the init fcn */
751 int freq; /*Frequency of polls */
752 int period; /*Time in minutes of data collection */
755 * Are we doing one-shot measurements?
757 if (a_s->parms[P_ONESHOT].items != 0)
761 * Are we doing debugging output?
763 if (a_s->parms[P_DEBUG].items != 0)
767 * Pull out the number of Cache Managers to watch and the number of
768 * collections to get.
770 numCMs = CountListItems(a_s->parms[P_CM_NAMES].items);
771 numCollIDs = CountListItems(a_s->parms[P_COLL_IDS].items);
773 /* Get the polling frequency */
774 if (a_s->parms[P_FREQUENCY].items != 0)
775 freq = atoi(a_s->parms[P_FREQUENCY].items->data);
777 freq = 30; /* default to 30 seconds */
779 /* Get the time duration to run the tests */
780 if (a_s->parms[P_PERIOD].items != 0)
781 period = atoi(a_s->parms[P_PERIOD].items->data);
783 period = 10; /* default to 10 minutes */
786 * Allocate the socket array.
789 printf("%s: Allocating socket array for %d Cache Manager(s)\n", rn,
792 CMSktArray = calloc(numCMs, sizeof(struct sockaddr_in));
793 if (CMSktArray == NULL) {
794 printf("%s: Can't allocate socket array for %d Cache Managers\n",
803 * Fill in the socket array for each of the Cache Managers listed.
805 curr_item = a_s->parms[P_CM_NAMES].items;
806 for (currCM = 0; currCM < numCMs; currCM++) {
807 CMSktArray[currCM].sin_family = AF_INET;
808 CMSktArray[currCM].sin_port = htons(7001); /* Cache Manager port */
809 he = hostutil_GetHostByName(curr_item->data);
811 fprintf(stderr, "[%s] Can't get host info for '%s'\n", rn,
815 memcpy(&(CMSktArray[currCM].sin_addr.s_addr), he->h_addr, 4);
818 * Move to the next CM name.
820 curr_item = curr_item->next;
822 } /*Get socket info for each Cache Manager */
825 * Create and fill up the array of desired collection IDs.
828 printf("Allocating %d long(s) for coll ID\n", numCollIDs);
831 collIDP = calloc(numCollIDs, sizeof(afs_int32));
835 currCollIDP = collIDP;
836 curr_item = a_s->parms[P_COLL_IDS].items;
837 for (currCollIDIdx = 0; currCollIDIdx < numCollIDs; currCollIDIdx++) {
838 *currCollIDP = (afs_int32) (atoi(curr_item->data));
840 printf("CollID at index %d is %d\n", currCollIDIdx, *currCollIDP);
841 curr_item = curr_item->next;
846 * Crank up the Cache Manager prober, then sit back and have fun.
848 printf("\nStarting up the xstat_cm service, ");
851 initFlags |= XSTAT_CM_INITFLAG_DEBUGGING;
852 printf("debugging enabled, ");
854 printf("no debugging, ");
856 initFlags |= XSTAT_CM_INITFLAG_ONE_SHOT;
857 printf("one-shot operation\n");
859 printf("continuous operation\n");
861 code = xstat_cm_Init(numCMs, /*Num CMs */
862 CMSktArray, /*File Server socket array */
863 freq, /*Probe every 30 seconds */
864 CM_Handler, /*Handler routine */
865 initFlags, /*Initialization flags */
866 numCollIDs, /*Number of collection IDs */
867 collIDP); /*Ptr to collection ID array */
869 fprintf(stderr, "[%s] Error returned by xstat_cm_Init: %d\n", rn,
871 xstat_cm_Cleanup(1); /*Get rid of malloc'ed structures */
875 /* Wait for the collection complete. */
876 xstat_cm_Wait(60 * period);
879 * We're all done. Clean up, put the last nail in Rx, then
883 printf("\nYawn, main thread just woke up. Cleaning things out...\n");
884 xstat_cm_Cleanup(1); /*Get rid of malloc'ed data */
891 #include "AFS_component_version_number.c"
893 main(int argc, char **argv)
896 static char rn[] = "xstat_cm_test"; /*Routine name */
897 afs_int32 code; /*Return code */
898 struct cmd_syndesc *ts; /*Ptr to cmd line syntax desc */
901 * Set up the commands we understand.
903 ts = cmd_CreateSyntax("initcmd", RunTheTest, NULL, 0, "initialize the program");
904 cmd_AddParm(ts, "-cmname", CMD_LIST, CMD_REQUIRED,
905 "Cache Manager name(s) to monitor");
906 cmd_AddParm(ts, "-collID", CMD_LIST, CMD_REQUIRED,
907 "Collection(s) to fetch");
908 cmd_AddParm(ts, "-onceonly", CMD_FLAG, CMD_OPTIONAL,
909 "Collect results exactly once, then quit");
910 cmd_AddParm(ts, "-frequency", CMD_SINGLE, CMD_OPTIONAL,
911 "poll frequency, in seconds");
912 cmd_AddParm(ts, "-period", CMD_SINGLE, CMD_OPTIONAL,
913 "data collection time, in minutes");
914 cmd_AddParm(ts, "-debug", CMD_FLAG, CMD_OPTIONAL,
915 "turn on debugging output");
918 * Parse command-line switches & execute the test, then get the
921 code = cmd_Dispatch(argc, argv);
923 fprintf(stderr, "[%s] Call to cmd_Dispatch() failed; code is %d\n",