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[] = {
77 static char *cmOpNames[] = {
87 static char *xferOpNames[] = {
93 /* Print detailed functional call statistics */
96 print_cmCallStats(void)
98 char *printableTime; /*Ptr to printable time string */
100 struct afs_CMStats *cmp;
101 time_t probeTime = xstat_cm_Results.probeTime;
103 printableTime = ctime(&probeTime);
104 printableTime[strlen(printableTime) - 1] = '\0';
107 ("AFSCB_XSTATSCOLL_CALL_INFO (coll %d) for CM %s\n[Probe %u, %s]\n\n",
108 xstat_cm_Results.collectionNumber, xstat_cm_Results.connP->hostName,
109 xstat_cm_Results.probeNum, printableTime);
111 cmp = (struct afs_CMStats *)(xstat_cm_Results.data.AFSCB_CollData_val);
112 nitems = xstat_cm_Results.data.AFSCB_CollData_len;
114 #define AFS_CS(call) \
116 printf("\t%10u %s\n", cmp->callInfo.C_ ## call, #call); \
125 /*------------------------------------------------------------------------
129 * Print the up/downtime stats for the given class of server records
133 * a_upDownP : Ptr to the server up/down info.
139 * Nothing interesting.
143 *------------------------------------------------------------------------*/
146 PrintUpDownStats(struct afs_stats_SrvUpDownInfo *a_upDownP)
147 { /*PrintUpDownStats */
150 * First, print the simple values.
152 printf("\t\t%10u numTtlRecords\n", a_upDownP->numTtlRecords);
153 printf("\t\t%10u numUpRecords\n", a_upDownP->numUpRecords);
154 printf("\t\t%10u numDownRecords\n", a_upDownP->numDownRecords);
155 printf("\t\t%10u sumOfRecordAges\n", a_upDownP->sumOfRecordAges);
156 printf("\t\t%10u ageOfYoungestRecord\n", a_upDownP->ageOfYoungestRecord);
157 printf("\t\t%10u ageOfOldestRecord\n", a_upDownP->ageOfOldestRecord);
158 printf("\t\t%10u numDowntimeIncidents\n",
159 a_upDownP->numDowntimeIncidents);
160 printf("\t\t%10u numRecordsNeverDown\n", a_upDownP->numRecordsNeverDown);
161 printf("\t\t%10u maxDowntimesInARecord\n",
162 a_upDownP->maxDowntimesInARecord);
163 printf("\t\t%10u sumOfDowntimes\n", a_upDownP->sumOfDowntimes);
164 printf("\t\t%10u shortestDowntime\n", a_upDownP->shortestDowntime);
165 printf("\t\t%10u longestDowntime\n", a_upDownP->longestDowntime);
168 * Now, print the array values.
170 printf("\t\tDowntime duration distribution:\n");
171 printf("\t\t\t%8u: 0 min .. 10 min\n", a_upDownP->downDurations[0]);
172 printf("\t\t\t%8u: 10 min .. 30 min\n", a_upDownP->downDurations[1]);
173 printf("\t\t\t%8u: 30 min .. 1 hr\n", a_upDownP->downDurations[2]);
174 printf("\t\t\t%8u: 1 hr .. 2 hr\n", a_upDownP->downDurations[3]);
175 printf("\t\t\t%8u: 2 hr .. 4 hr\n", a_upDownP->downDurations[4]);
176 printf("\t\t\t%8u: 4 hr .. 8 hr\n", a_upDownP->downDurations[5]);
177 printf("\t\t\t%8u: > 8 hr\n", a_upDownP->downDurations[6]);
179 printf("\t\tDowntime incident distribution:\n");
180 printf("\t\t\t%8u: 0 times\n", a_upDownP->downIncidents[0]);
181 printf("\t\t\t%8u: 1 time\n", a_upDownP->downIncidents[1]);
182 printf("\t\t\t%8u: 2 .. 5 times\n", a_upDownP->downIncidents[2]);
183 printf("\t\t\t%8u: 6 .. 10 times\n", a_upDownP->downIncidents[3]);
184 printf("\t\t\t%8u: 10 .. 50 times\n", a_upDownP->downIncidents[4]);
185 printf("\t\t\t%8u: > 50 times\n", a_upDownP->downIncidents[5]);
187 } /*PrintUpDownStats */
190 /*------------------------------------------------------------------------
191 * PrintOverallPerfInfo
194 * Print out overall performance numbers.
197 * a_ovP : Ptr to the overall performance numbers.
203 * All the info we need is nestled into xstat_cm_Results.
207 *------------------------------------------------------------------------*/
210 PrintOverallPerfInfo(struct afs_stats_CMPerf *a_ovP)
211 { /*PrintOverallPerfInfo */
213 printf("\t%10u numPerfCalls\n", a_ovP->numPerfCalls);
215 printf("\t%10u epoch\n", a_ovP->epoch);
216 printf("\t%10u numCellsVisible\n", a_ovP->numCellsVisible);
217 printf("\t%10u numCellsContacted\n", a_ovP->numCellsContacted);
218 printf("\t%10u dlocalAccesses\n", a_ovP->dlocalAccesses);
219 printf("\t%10u vlocalAccesses\n", a_ovP->vlocalAccesses);
220 printf("\t%10u dremoteAccesses\n", a_ovP->dremoteAccesses);
221 printf("\t%10u vremoteAccesses\n", a_ovP->vremoteAccesses);
222 printf("\t%10u cacheNumEntries\n", a_ovP->cacheNumEntries);
223 printf("\t%10u cacheBlocksTotal\n", a_ovP->cacheBlocksTotal);
224 printf("\t%10u cacheBlocksInUse\n", a_ovP->cacheBlocksInUse);
225 printf("\t%10u cacheBlocksOrig\n", a_ovP->cacheBlocksOrig);
226 printf("\t%10u cacheMaxDirtyChunks\n", a_ovP->cacheMaxDirtyChunks);
227 printf("\t%10u cacheCurrDirtyChunks\n", a_ovP->cacheCurrDirtyChunks);
228 printf("\t%10u dcacheHits\n", a_ovP->dcacheHits);
229 printf("\t%10u vcacheHits\n", a_ovP->vcacheHits);
230 printf("\t%10u dcacheMisses\n", a_ovP->dcacheMisses);
231 printf("\t%10u vcacheMisses\n", a_ovP->vcacheMisses);
232 printf("\t%10u cacheFilesReused\n", a_ovP->cacheFilesReused);
233 printf("\t%10u vcacheXAllocs\n", a_ovP->vcacheXAllocs);
234 printf("\t%10u dcacheXAllocs\n", a_ovP->dcacheXAllocs);
236 printf("\t%10u bufAlloced\n", a_ovP->bufAlloced);
237 printf("\t%10u bufHits\n", a_ovP->bufHits);
238 printf("\t%10u bufMisses\n", a_ovP->bufMisses);
239 printf("\t%10u bufFlushDirty\n", a_ovP->bufFlushDirty);
241 printf("\t%10u LargeBlocksActive\n", a_ovP->LargeBlocksActive);
242 printf("\t%10u LargeBlocksAlloced\n", a_ovP->LargeBlocksAlloced);
243 printf("\t%10u SmallBlocksActive\n", a_ovP->SmallBlocksActive);
244 printf("\t%10u SmallBlocksAlloced\n", a_ovP->SmallBlocksAlloced);
245 printf("\t%10u OutStandingMemUsage\n", a_ovP->OutStandingMemUsage);
246 printf("\t%10u OutStandingAllocs\n", a_ovP->OutStandingAllocs);
247 printf("\t%10u CallBackAlloced\n", a_ovP->CallBackAlloced);
248 printf("\t%10u CallBackFlushes\n", a_ovP->CallBackFlushes);
249 printf("\t%10u CallBackLoops\n", a_ovP->cbloops);
251 printf("\t%10u srvRecords\n", a_ovP->srvRecords);
252 printf("\t%10u srvNumBuckets\n", a_ovP->srvNumBuckets);
253 printf("\t%10u srvMaxChainLength\n", a_ovP->srvMaxChainLength);
254 printf("\t%10u srvMaxChainLengthHWM\n", a_ovP->srvMaxChainLengthHWM);
255 printf("\t%10u srvRecordsHWM\n", a_ovP->srvRecordsHWM);
257 printf("\t%10u cacheBucket0_Discarded\n", a_ovP->cacheBucket0_Discarded);
258 printf("\t%10u cacheBucket1_Discarded\n", a_ovP->cacheBucket1_Discarded);
259 printf("\t%10u cacheBucket2_Discarded\n", a_ovP->cacheBucket2_Discarded);
261 printf("\t%10u sysName_ID\n", a_ovP->sysName_ID);
263 printf("\tFile Server up/downtimes, same cell:\n");
264 PrintUpDownStats(&(a_ovP->fs_UpDown[0]));
266 printf("\tFile Server up/downtimes, diff cell:\n");
267 PrintUpDownStats(&(a_ovP->fs_UpDown[1]));
269 printf("\tVL Server up/downtimes, same cell:\n");
270 PrintUpDownStats(&(a_ovP->vl_UpDown[0]));
272 printf("\tVL Server up/downtimes, diff cell:\n");
273 PrintUpDownStats(&(a_ovP->vl_UpDown[1]));
275 } /*PrintOverallPerfInfo */
278 /*------------------------------------------------------------------------
282 * Print out the AFSCB_XSTATSCOLL_PERF_INFO collection we just
292 * All the info we need is nestled into xstat_cm_Results.
296 *------------------------------------------------------------------------*/
302 static afs_int32 perfInt32s = (sizeof(struct afs_stats_CMPerf) >> 2); /*Correct # int32s to rcv */
303 afs_int32 numInt32s; /*# int32words received */
304 struct afs_stats_CMPerf *perfP; /*Ptr to performance stats */
305 char *printableTime; /*Ptr to printable time string */
306 time_t probeTime = xstat_cm_Results.probeTime;
308 numInt32s = xstat_cm_Results.data.AFSCB_CollData_len;
309 if (numInt32s != perfInt32s) {
310 printf("** Data size mismatch in performance collection!");
311 printf("** Expecting %u, got %u\n", perfInt32s, numInt32s);
312 printf("** Version mismatch with Cache Manager\n");
316 printableTime = ctime(&probeTime);
317 printableTime[strlen(printableTime) - 1] = '\0';
318 perfP = (struct afs_stats_CMPerf *)
319 (xstat_cm_Results.data.AFSCB_CollData_val);
322 ("AFSCB_XSTATSCOLL_PERF_INFO (coll %d) for CM %s\n[Probe %u, %s]\n\n",
323 xstat_cm_Results.collectionNumber, xstat_cm_Results.connP->hostName,
324 xstat_cm_Results.probeNum, printableTime);
326 PrintOverallPerfInfo(perfP);
331 /*------------------------------------------------------------------------
335 * Print out the contents of an FS RPC op timing structure.
338 * a_opIdx : Index of the AFS operation we're printing number on.
339 * a_opNames : Ptr to table of operaton names.
340 * a_opTimeP : Ptr to the op timing structure to print.
346 * Nothing interesting.
350 *------------------------------------------------------------------------*/
353 PrintOpTiming(int a_opIdx, char *a_opNames[],
354 struct afs_stats_opTimingData *a_opTimeP)
358 ("%15s: %u ops (%u OK); sum=%lu.%06lu, sqr=%lu.%06lu, min=%lu.%06lu, max=%lu.%06lu\n",
359 a_opNames[a_opIdx], a_opTimeP->numOps, a_opTimeP->numSuccesses,
360 (long)a_opTimeP->sumTime.tv_sec, (long)a_opTimeP->sumTime.tv_usec,
361 (long)a_opTimeP->sqrTime.tv_sec, (long)a_opTimeP->sqrTime.tv_usec,
362 (long)a_opTimeP->minTime.tv_sec, (long)a_opTimeP->minTime.tv_usec,
363 (long)a_opTimeP->maxTime.tv_sec, (long)a_opTimeP->maxTime.tv_usec);
368 /*------------------------------------------------------------------------
372 * Print out the contents of a data transfer structure.
375 * a_opIdx : Index of the AFS operation we're printing number on.
376 * a_opNames : Ptr to table of operation names.
377 * a_xferP : Ptr to the data transfer structure to print.
383 * Nothing interesting.
387 *------------------------------------------------------------------------*/
390 PrintXferTiming(int a_opIdx, char *a_opNames[],
391 struct afs_stats_xferData *a_xferP)
392 { /*PrintXferTiming */
395 ("%s: %u xfers (%u OK), time sum=%lu.%06lu, sqr=%lu.%06lu, min=%lu.%06lu, max=%lu.%06lu\n",
396 a_opNames[a_opIdx], a_xferP->numXfers, a_xferP->numSuccesses,
397 (long)a_xferP->sumTime.tv_sec, (long)a_xferP->sumTime.tv_usec,
398 (long)a_xferP->sqrTime.tv_sec, (long)a_xferP->sqrTime.tv_usec,
399 (long)a_xferP->minTime.tv_sec, (long)a_xferP->minTime.tv_usec,
400 (long)a_xferP->maxTime.tv_sec, (long)a_xferP->maxTime.tv_usec);
401 printf("\t[bytes: sum=%u, min=%u, max=%u]\n", a_xferP->sumBytes,
402 a_xferP->minBytes, a_xferP->maxBytes);
404 ("\t[buckets: 0: %u, 1: %u, 2: %u, 3: %u, 4: %u, 5: %u, 6: %u, 7: %u, 8: %u]\n",
405 a_xferP->count[0], a_xferP->count[1], a_xferP->count[2],
406 a_xferP->count[3], a_xferP->count[4], a_xferP->count[5],
407 a_xferP->count[6], a_xferP->count[7], a_xferP->count[8]);
410 } /*PrintXferTiming */
413 /*------------------------------------------------------------------------
417 * Print out the contents of an FS RPC error info structure.
420 * a_opIdx : Index of the AFS operation we're printing.
421 * a_opNames : Ptr to table of operation names.
422 * a_opErrP : Ptr to the op timing structure to print.
428 * Nothing interesting.
432 *------------------------------------------------------------------------*/
435 PrintErrInfo(int a_opIdx, char *a_opNames[],
436 struct afs_stats_RPCErrors *a_opErrP)
440 ("%15s: %u server, %u network, %u prot, %u vol, %u busies, %u other\n",
441 a_opNames[a_opIdx], a_opErrP->err_Server, a_opErrP->err_Network,
442 a_opErrP->err_Protection, a_opErrP->err_Volume,
443 a_opErrP->err_VolumeBusies, a_opErrP->err_Other);
448 /*------------------------------------------------------------------------
452 * Print out a set of RPC performance numbers.
455 * a_rpcP : Ptr to RPC perf numbers to print.
461 * Nothing interesting.
465 *------------------------------------------------------------------------*/
468 PrintRPCPerfInfo(struct afs_stats_RPCOpInfo *a_rpcP)
469 { /*PrintRPCPerfInfo */
471 int currIdx; /*Loop variable */
474 * Print the contents of each of the opcode-related arrays.
476 printf("FS Operation Timings:\n---------------------\n");
477 for (currIdx = 0; currIdx < AFS_STATS_NUM_FS_RPC_OPS; currIdx++)
478 PrintOpTiming(currIdx, fsOpNames, &(a_rpcP->fsRPCTimes[currIdx]));
480 printf("\nError Info:\n-----------\n");
481 for (currIdx = 0; currIdx < AFS_STATS_NUM_FS_RPC_OPS; currIdx++)
482 PrintErrInfo(currIdx, fsOpNames, &(a_rpcP->fsRPCErrors[currIdx]));
484 printf("\nTransfer timings:\n-----------------\n");
485 for (currIdx = 0; currIdx < AFS_STATS_NUM_FS_XFER_OPS; currIdx++)
486 PrintXferTiming(currIdx, xferOpNames,
487 &(a_rpcP->fsXferTimes[currIdx]));
489 printf("\nCM Operation Timings:\n---------------------\n");
490 for (currIdx = 0; currIdx < AFS_STATS_NUM_CM_RPC_OPS; currIdx++)
491 PrintOpTiming(currIdx, cmOpNames, &(a_rpcP->cmRPCTimes[currIdx]));
493 } /*PrintRPCPerfInfo */
496 /*------------------------------------------------------------------------
500 * Print out a set of full performance numbers.
509 * Nothing interesting.
513 *------------------------------------------------------------------------*/
516 PrintFullPerfInfo(void)
517 { /*PrintFullPerfInfo */
519 struct afs_stats_AuthentInfo *authentP; /*Ptr to authentication stats */
520 struct afs_stats_AccessInfo *accessinfP; /*Ptr to access stats */
521 static afs_int32 fullPerfInt32s = (sizeof(struct afs_stats_CMFullPerf) >> 2); /*Correct #int32s */
522 afs_int32 numInt32s; /*# int32s actually received */
523 struct afs_stats_CMFullPerf *fullP; /*Ptr to full perf info */
525 char *printableTime; /*Ptr to printable time string */
526 time_t probeTime = xstat_cm_Results.probeTime;
528 numInt32s = xstat_cm_Results.data.AFSCB_CollData_len;
529 if (numInt32s != fullPerfInt32s) {
530 printf("** Data size mismatch in performance collection!");
531 printf("** Expecting %u, got %u\n", fullPerfInt32s, numInt32s);
532 printf("** Version mismatch with Cache Manager\n");
536 printableTime = ctime(&probeTime);
537 printableTime[strlen(printableTime) - 1] = '\0';
538 fullP = (struct afs_stats_CMFullPerf *)
539 (xstat_cm_Results.data.AFSCB_CollData_val);
542 ("AFSCB_XSTATSCOLL_FULL_PERF_INFO (coll %d) for CM %s\n[Probe %u, %s]\n\n",
543 xstat_cm_Results.collectionNumber, xstat_cm_Results.connP->hostName,
544 xstat_cm_Results.probeNum, printableTime);
547 * Print the overall numbers first, followed by all of the RPC numbers,
548 * then each of the other groupings.
550 printf("Overall Performance Info:\n-------------------------\n");
551 PrintOverallPerfInfo(&(fullP->perf));
553 PrintRPCPerfInfo(&(fullP->rpc));
555 authentP = &(fullP->authent);
556 printf("\nAuthentication info:\n--------------------\n");
558 ("\t%u PAGS, %u records (%u auth, %u unauth), %u max in PAG, chain max: %u\n",
559 authentP->curr_PAGs, authentP->curr_Records,
560 authentP->curr_AuthRecords, authentP->curr_UnauthRecords,
561 authentP->curr_MaxRecordsInPAG, authentP->curr_LongestChain);
562 printf("\t%u PAG creations, %u tkt updates\n", authentP->PAGCreations,
563 authentP->TicketUpdates);
564 printf("\t[HWMs: %u PAGS, %u records, %u max in PAG, chain max: %u]\n",
565 authentP->HWM_PAGs, authentP->HWM_Records,
566 authentP->HWM_MaxRecordsInPAG, authentP->HWM_LongestChain);
568 accessinfP = &(fullP->accessinf);
569 printf("\n[Un]replicated accesses:\n------------------------\n");
571 ("\t%u unrep, %u rep, %u reps accessed, %u max reps/ref, %u first OK\n\n",
572 accessinfP->unreplicatedRefs, accessinfP->replicatedRefs,
573 accessinfP->numReplicasAccessed, accessinfP->maxReplicasPerRef,
574 accessinfP->refFirstReplicaOK);
576 /* There really isn't any authorship info
577 * authorP = &(fullP->author); */
579 } /*PrintFullPerfInfo */
582 /*------------------------------------------------------------------------
586 * Handler routine passed to the xstat_cm module. This handler is
587 * called immediately after a poll of one of the Cache Managers has
588 * taken place. All it needs to know is exported by the xstat_cm
589 * module, namely the data structure where the probe results are
600 * See above. All we do now is print out what we got.
604 *------------------------------------------------------------------------*/
610 static char rn[] = "CM_Handler"; /*Routine name */
612 printf("\n-----------------------------------------------------------\n");
615 * If the probe failed, there isn't much we can do except gripe.
617 if (xstat_cm_Results.probeOK) {
618 printf("%s: Probe %u, collection %d to CM on '%s' failed, code=%d\n",
619 rn, xstat_cm_Results.probeNum,
620 xstat_cm_Results.collectionNumber,
621 xstat_cm_Results.connP->hostName, xstat_cm_Results.probeOK);
627 int numInt32s = xstat_cm_Results.data.AFSCB_CollData_len;
628 afs_int32 *entry = xstat_cm_Results.data.AFSCB_CollData_val;
630 printf("debug: got collection number %d\n", xstat_cm_Results.collectionNumber);
631 printf("debug: collection data length is %d\n", numInt32s);
632 for (i = 0; i < numInt32s; i++) {
633 printf("debug: entry %d %u\n", i, entry[i]);
638 switch (xstat_cm_Results.collectionNumber) {
639 case AFSCB_XSTATSCOLL_CALL_INFO:
643 case AFSCB_XSTATSCOLL_PERF_INFO:
644 /* we will do nothing here */
645 /* PrintPerfInfo(); */
648 case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
653 printf("** Unknown collection: %d\n",
654 xstat_cm_Results.collectionNumber);
658 * Return the happy news.
665 /*------------------------------------------------------------------------
669 * Given a pointer to the list of Cache Managers we'll be polling
670 * (or, in fact, any list at all), compute the length of the list.
673 * struct cmd_item *a_firstItem : Ptr to first item in list.
676 * Length of the above list.
679 * Nothing interesting.
683 *------------------------------------------------------------------------*/
686 CountListItems(struct cmd_item *a_firstItem)
687 { /*CountListItems */
689 int list_len; /*List length */
690 struct cmd_item *curr_item; /*Ptr to current item */
693 curr_item = a_firstItem;
700 curr_item = curr_item->next;
708 } /*CountListItems */
711 /*------------------------------------------------------------------------
715 * Routine called by the command line interpreter to execute the
716 * meat of the program. We count the number of Cache Managers
717 * to watch, allocate enough space to remember all the connection
718 * info for them, then go for it.
722 * a_s : Ptr to the command line syntax descriptor.
725 * 0, but may exit the whole program on an error!
728 * Nothing interesting.
732 *------------------------------------------------------------------------*/
735 RunTheTest(struct cmd_syndesc *a_s, void *arock)
738 static char rn[] = "RunTheTest"; /*Routine name */
739 int code; /*Return code */
740 int numCMs; /*# Cache Managers to monitor */
741 int numCollIDs; /*# collections to fetch */
742 int currCM; /*Loop index */
743 int currCollIDIdx; /*Index of current collection ID */
744 afs_int32 *collIDP; /*Ptr to array of collection IDs */
745 afs_int32 *currCollIDP; /*Ptr to current collection ID */
746 struct cmd_item *curr_item; /*Current CM cmd line record */
747 struct sockaddr_in *CMSktArray; /*Cache Manager socket array */
748 struct hostent *he; /*Host entry */
749 struct timeval tv; /*Time structure */
750 int sleep_secs; /*Number of seconds to sleep */
751 int initFlags; /*Flags passed to the init fcn */
752 int waitCode; /*Result of LWP_WaitProcess() */
753 int freq; /*Frequency of polls */
754 int period; /*Time in minutes of data collection */
757 * Are we doing one-shot measurements?
759 if (a_s->parms[P_ONESHOT].items != 0)
763 * Are we doing debugging output?
765 if (a_s->parms[P_DEBUG].items != 0)
769 * Pull out the number of Cache Managers to watch and the number of
770 * collections to get.
772 numCMs = CountListItems(a_s->parms[P_CM_NAMES].items);
773 numCollIDs = CountListItems(a_s->parms[P_COLL_IDS].items);
775 /* Get the polling frequency */
776 if (a_s->parms[P_FREQUENCY].items != 0)
777 freq = atoi(a_s->parms[P_FREQUENCY].items->data);
779 freq = 30; /* default to 30 seconds */
781 /* Get the time duration to run the tests */
782 if (a_s->parms[P_PERIOD].items != 0)
783 period = atoi(a_s->parms[P_PERIOD].items->data);
785 period = 10; /* default to 10 minutes */
788 * Allocate the socket array.
791 printf("%s: Allocating socket array for %d Cache Manager(s)\n", rn,
794 CMSktArray = calloc(numCMs, sizeof(struct sockaddr_in));
795 if (CMSktArray == NULL) {
796 printf("%s: Can't allocate socket array for %d Cache Managers\n",
805 * Fill in the socket array for each of the Cache Managers listed.
807 curr_item = a_s->parms[P_CM_NAMES].items;
808 for (currCM = 0; currCM < numCMs; currCM++) {
809 CMSktArray[currCM].sin_family = AF_INET;
810 CMSktArray[currCM].sin_port = htons(7001); /* Cache Manager port */
811 he = hostutil_GetHostByName(curr_item->data);
813 fprintf(stderr, "[%s] Can't get host info for '%s'\n", rn,
817 memcpy(&(CMSktArray[currCM].sin_addr.s_addr), he->h_addr, 4);
820 * Move to the next CM name.
822 curr_item = curr_item->next;
824 } /*Get socket info for each Cache Manager */
827 * Create and fill up the array of desired collection IDs.
830 printf("Allocating %d long(s) for coll ID\n", numCollIDs);
833 collIDP = calloc(numCollIDs, sizeof(afs_int32));
837 currCollIDP = collIDP;
838 curr_item = a_s->parms[P_COLL_IDS].items;
839 for (currCollIDIdx = 0; currCollIDIdx < numCollIDs; currCollIDIdx++) {
840 *currCollIDP = (afs_int32) (atoi(curr_item->data));
842 printf("CollID at index %d is %d\n", currCollIDIdx, *currCollIDP);
843 curr_item = curr_item->next;
848 * Crank up the Cache Manager prober, then sit back and have fun.
850 printf("\nStarting up the xstat_cm service, ");
853 initFlags |= XSTAT_CM_INITFLAG_DEBUGGING;
854 printf("debugging enabled, ");
856 printf("no debugging, ");
858 initFlags |= XSTAT_CM_INITFLAG_ONE_SHOT;
859 printf("one-shot operation\n");
861 printf("continuous operation\n");
863 code = xstat_cm_Init(numCMs, /*Num CMs */
864 CMSktArray, /*File Server socket array */
865 freq, /*Probe every 30 seconds */
866 CM_Handler, /*Handler routine */
867 initFlags, /*Initialization flags */
868 numCollIDs, /*Number of collection IDs */
869 collIDP); /*Ptr to collection ID array */
871 fprintf(stderr, "[%s] Error returned by xstat_cm_Init: %d\n", rn,
873 xstat_cm_Cleanup(1); /*Get rid of malloc'ed structures */
879 * One-shot operation; just wait for the collection to be done.
882 printf("[%s] Calling LWP_WaitProcess() on event %" AFS_PTR_FMT
883 "\n", rn, &terminationEvent);
884 waitCode = LWP_WaitProcess(&terminationEvent);
886 printf("[%s] Returned from LWP_WaitProcess()\n", rn);
890 "[%s] Error %d encountered by LWP_WaitProcess()\n",
895 * Continuous operation.
897 sleep_secs = 60 * period; /*length of data collection */
899 ("xstat_cm service started, main thread sleeping for %d secs.\n",
903 * Let's just fall asleep for a while, then we'll clean up.
905 tv.tv_sec = sleep_secs;
907 code = IOMGR_Select(0, /*Num fds */
908 0, /*Descriptors ready for reading */
909 0, /*Descriptors ready for writing */
910 0, /*Descriptors with exceptional conditions */
911 &tv); /*Timeout structure */
914 "[%s] IOMGR_Select() returned non-zero value: %d\n", rn,
920 * We're all done. Clean up, put the last nail in Rx, then
924 printf("\nYawn, main thread just woke up. Cleaning things out...\n");
925 code = xstat_cm_Cleanup(1); /*Get rid of malloc'ed data */
932 #include "AFS_component_version_number.c"
934 main(int argc, char **argv)
937 static char rn[] = "xstat_cm_test"; /*Routine name */
938 afs_int32 code; /*Return code */
939 struct cmd_syndesc *ts; /*Ptr to cmd line syntax desc */
942 * Set up the commands we understand.
944 ts = cmd_CreateSyntax("initcmd", RunTheTest, NULL, "initialize the program");
945 cmd_AddParm(ts, "-cmname", CMD_LIST, CMD_REQUIRED,
946 "Cache Manager name(s) to monitor");
947 cmd_AddParm(ts, "-collID", CMD_LIST, CMD_REQUIRED,
948 "Collection(s) to fetch");
949 cmd_AddParm(ts, "-onceonly", CMD_FLAG, CMD_OPTIONAL,
950 "Collect results exactly once, then quit");
951 cmd_AddParm(ts, "-frequency", CMD_SINGLE, CMD_OPTIONAL,
952 "poll frequency, in seconds");
953 cmd_AddParm(ts, "-period", CMD_SINGLE, CMD_OPTIONAL,
954 "data collection time, in minutes");
955 cmd_AddParm(ts, "-debug", CMD_FLAG, CMD_OPTIONAL,
956 "turn on debugging output");
959 * Parse command-line switches & execute the test, then get the
962 code = cmd_Dispatch(argc, argv);
964 fprintf(stderr, "[%s] Call to cmd_Dispatch() failed; code is %d\n",