Standardize License information
[openafs.git] / src / xstat / xstat_fs_test.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Description:
12  *      Test of the xstat_fs module.
13  *
14  *------------------------------------------------------------------------*/
15
16 #include "xstat_fs.h"           /*Interface for xstat_fs module*/
17 #include <cmd.h>                /*Command line interpreter*/
18 #include <time.h>
19
20 /*
21  * External routines that don't have explicit include file definitions.
22  */
23 extern struct hostent *hostutil_GetHostByName();
24
25 /*
26  * Command line parameter indices.
27  *      P_FS_NAMES : List of FileServer 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?
31  */
32 #define P_FS_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
38
39 /*
40  * Private globals.
41  */
42 static int debugging_on = 0;    /*Are we debugging?*/
43 static int one_shot     = 0;    /*Single round of data collection?*/
44
45 static char *opNames[] = {
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 };
75
76 static char *xferOpNames[] = {
77     "FetchData",
78     "StoreData"
79 };
80
81
82 /*------------------------------------------------------------------------
83  * PrintCallInfo
84  *
85  * Description:
86  *      Print out the AFS_XSTATSCOLL_CALL_INFO collection we just
87  *      received.
88  *
89  * Arguments:
90  *      None.
91  *
92  * Returns:
93  *      Nothing.
94  *
95  * Environment:
96  *      All the info we need is nestled into xstat_fs_Results.
97  *
98  * Side Effects:
99  *      As advertised.
100  *------------------------------------------------------------------------*/
101
102 void PrintCallInfo()
103
104 { /*PrintCallInfo*/
105
106     static char rn[] = "PrintCallInfo"; /*Routine name*/
107     register int i;                     /*Loop variable*/
108     int numInt32s;                      /*# int32words returned*/
109     afs_int32 *currInt32;                       /*Ptr to current afs_int32 value*/
110     char *printableTime;                /*Ptr to printable time string*/
111
112     /*
113      * Just print out the results of the particular probe.
114      */
115     numInt32s = xstat_fs_Results.data.AFS_CollData_len;
116     currInt32 = (afs_int32 *)(xstat_fs_Results.data.AFS_CollData_val);
117     printableTime = ctime((time_t *)&(xstat_fs_Results.probeTime));
118     printableTime[strlen(printableTime)-1] = '\0';
119
120     printf("AFS_XSTATSCOLL_CALL_INFO (coll %d) for FS %s\n[Probe %d, %s]\n\n",
121            xstat_fs_Results.collectionNumber,
122            xstat_fs_Results.connP->hostName,
123            xstat_fs_Results.probeNum,
124            printableTime);
125
126     if (debugging_on)
127         printf("\n[%d entries returned at 0x%x]\n\n",
128                numInt32s, currInt32);
129
130     for (i = 0; i < numInt32s; i++)
131         printf("%d ", *currInt32++);
132     fprintf(stderr, "\n");
133
134 } /*PrintCallInfo*/
135
136
137 /*------------------------------------------------------------------------
138  * PrintOverallPerfInfo
139  *
140  * Description:
141  *      Print out overall performance numbers.
142  *
143  * Arguments:
144  *      a_ovP : Ptr to the overall performance numbers.
145  *
146  * Returns:
147  *      Nothing.
148  *
149  * Environment:
150  *      Nothing interesting.
151  *
152  * Side Effects:
153  *      As advertised.
154  *------------------------------------------------------------------------*/
155
156 void PrintOverallPerfInfo(a_ovP)
157     struct afs_PerfStats *a_ovP;
158
159 { /*PrintOverallPerfInfo*/
160
161     printf("\t%10d numPerfCalls\n\n", a_ovP->numPerfCalls);
162
163     /*
164      * Vnode cache section.
165      */
166     printf("\t%10d vcache_L_Entries\n",         a_ovP->vcache_L_Entries);
167     printf("\t%10d vcache_L_Allocs\n",          a_ovP->vcache_L_Allocs);
168     printf("\t%10d vcache_L_Gets\n",            a_ovP->vcache_L_Gets);
169     printf("\t%10d vcache_L_Reads\n",           a_ovP->vcache_L_Reads);
170     printf("\t%10d vcache_L_Writes\n\n",        a_ovP->vcache_L_Writes);
171
172     printf("\t%10d vcache_S_Entries\n",         a_ovP->vcache_S_Entries);
173     printf("\t%10d vcache_S_Allocs\n",          a_ovP->vcache_S_Allocs);
174     printf("\t%10d vcache_S_Gets\n",            a_ovP->vcache_S_Gets);
175     printf("\t%10d vcache_S_Reads\n",           a_ovP->vcache_S_Reads);
176     printf("\t%10d vcache_S_Writes\n\n",        a_ovP->vcache_S_Writes);
177
178     printf("\t%10d vcache_H_Entries\n",         a_ovP->vcache_H_Entries);
179     printf("\t%10d vcache_H_Gets\n",            a_ovP->vcache_H_Gets);
180     printf("\t%10d vcache_H_Replacements\n\n",  a_ovP->vcache_H_Replacements);
181
182     /*
183      * Directory package section.
184      */
185     printf("\t%10d dir_Buffers\n",              a_ovP->dir_Buffers);
186     printf("\t%10d dir_Calls\n",                a_ovP->dir_Calls);
187     printf("\t%10d dir_IOs\n\n",                a_ovP->dir_IOs);
188
189     /*
190      * Rx section.
191      */
192     printf("\t%10d rx_packetRequests\n",        a_ovP->rx_packetRequests);
193     printf("\t%10d rx_noPackets_RcvClass\n",    a_ovP->rx_noPackets_RcvClass);
194     printf("\t%10d rx_noPackets_SendClass\n",   a_ovP->rx_noPackets_SendClass);
195     printf("\t%10d rx_noPackets_SpecialClass\n", a_ovP->rx_noPackets_SpecialClass);
196     printf("\t%10d rx_socketGreedy\n",          a_ovP->rx_socketGreedy);
197     printf("\t%10d rx_bogusPacketOnRead\n",     a_ovP->rx_bogusPacketOnRead);
198     printf("\t%10d rx_bogusHost\n",             a_ovP->rx_bogusHost);
199     printf("\t%10d rx_noPacketOnRead\n",        a_ovP->rx_noPacketOnRead);
200     printf("\t%10d rx_noPacketBuffersOnRead\n", a_ovP->rx_noPacketBuffersOnRead);
201     printf("\t%10d rx_selects\n",               a_ovP->rx_selects);
202     printf("\t%10d rx_sendSelects\n",           a_ovP->rx_sendSelects);
203     printf("\t%10d rx_packetsRead_RcvClass\n",  a_ovP->rx_packetsRead_RcvClass);
204     printf("\t%10d rx_packetsRead_SendClass\n", a_ovP->rx_packetsRead_SendClass);
205     printf("\t%10d rx_packetsRead_SpecialClass\n", a_ovP->rx_packetsRead_SpecialClass);
206     printf("\t%10d rx_dataPacketsRead\n",       a_ovP->rx_dataPacketsRead);
207     printf("\t%10d rx_ackPacketsRead\n",        a_ovP->rx_ackPacketsRead);
208     printf("\t%10d rx_dupPacketsRead\n",        a_ovP->rx_dupPacketsRead);
209     printf("\t%10d rx_spuriousPacketsRead\n",   a_ovP->rx_spuriousPacketsRead);
210     printf("\t%10d rx_packetsSent_RcvClass\n",  a_ovP->rx_packetsSent_RcvClass);
211     printf("\t%10d rx_packetsSent_SendClass\n", a_ovP->rx_packetsSent_SendClass);
212     printf("\t%10d rx_packetsSent_SpecialClass\n", a_ovP->rx_packetsSent_SpecialClass);
213     printf("\t%10d rx_ackPacketsSent\n",        a_ovP->rx_ackPacketsSent);
214     printf("\t%10d rx_pingPacketsSent\n",       a_ovP->rx_pingPacketsSent);
215     printf("\t%10d rx_abortPacketsSent\n",      a_ovP->rx_abortPacketsSent);
216     printf("\t%10d rx_busyPacketsSent\n",       a_ovP->rx_busyPacketsSent);
217     printf("\t%10d rx_dataPacketsSent\n",       a_ovP->rx_dataPacketsSent);
218     printf("\t%10d rx_dataPacketsReSent\n",     a_ovP->rx_dataPacketsReSent);
219     printf("\t%10d rx_dataPacketsPushed\n",     a_ovP->rx_dataPacketsPushed);
220     printf("\t%10d rx_ignoreAckedPacket\n",     a_ovP->rx_ignoreAckedPacket);
221     printf("\t%10d rx_totalRtt_Sec\n",          a_ovP->rx_totalRtt_Sec);
222     printf("\t%10d rx_totalRtt_Usec\n",         a_ovP->rx_totalRtt_Usec);
223     printf("\t%10d rx_minRtt_Sec\n",            a_ovP->rx_minRtt_Sec);
224     printf("\t%10d rx_minRtt_Usec\n",           a_ovP->rx_minRtt_Usec);
225     printf("\t%10d rx_maxRtt_Sec\n",            a_ovP->rx_maxRtt_Sec);
226     printf("\t%10d rx_maxRtt_Usec\n",           a_ovP->rx_maxRtt_Usec);
227     printf("\t%10d rx_nRttSamples\n",           a_ovP->rx_nRttSamples);
228     printf("\t%10d rx_nServerConns\n",          a_ovP->rx_nServerConns);
229     printf("\t%10d rx_nClientConns\n",          a_ovP->rx_nClientConns);
230     printf("\t%10d rx_nPeerStructs\n",          a_ovP->rx_nPeerStructs);
231     printf("\t%10d rx_nCallStructs\n",          a_ovP->rx_nCallStructs);
232     printf("\t%10d rx_nFreeCallStructs\n\n",    a_ovP->rx_nFreeCallStructs);
233
234     /*
235      * Host module fields.
236      */
237     printf("\t%10d host_NumHostEntries\n",      a_ovP->host_NumHostEntries);
238     printf("\t%10d host_HostBlocks\n",          a_ovP->host_HostBlocks);
239     printf("\t%10d host_NonDeletedHosts\n",     a_ovP->host_NonDeletedHosts);
240     printf("\t%10d host_HostsInSameNetOrSubnet\n", a_ovP->host_HostsInSameNetOrSubnet);
241     printf("\t%10d host_HostsInDiffSubnet\n",   a_ovP->host_HostsInDiffSubnet);
242     printf("\t%10d host_HostsInDiffNetwork\n",  a_ovP->host_HostsInDiffNetwork);
243     printf("\t%10d host_NumClients\n",          a_ovP->host_NumClients);
244     printf("\t%10d host_ClientBlocks\n\n",      a_ovP->host_ClientBlocks);
245
246     printf("\t%10d sysname_ID\n",               a_ovP->sysname_ID);
247
248 } /*PrintOverallPerfInfo*/
249
250
251 /*------------------------------------------------------------------------
252  * PrintOpTiming
253  *
254  * Description:
255  *      Print out the contents of an RPC op timing structure.
256  *
257  * Arguments:
258  *      a_opIdx   : Index of the AFS operation we're printing number on.
259  *      a_opTimeP : Ptr to the op timing structure to print.
260  *
261  * Returns:
262  *      Nothing.
263  *
264  * Environment:
265  *      Nothing interesting.
266  *
267  * Side Effects:
268  *      As advertised.
269  *------------------------------------------------------------------------*/
270
271 void PrintOpTiming(a_opIdx, a_opTimeP)
272     int a_opIdx;
273     struct fs_stats_opTimingData *a_opTimeP;
274
275 { /*PrintOpTiming*/
276
277     double fSumTime, avg;
278
279     fSumTime = ((double)(a_opTimeP->sumTime.tv_sec)) +
280         (((double)(a_opTimeP->sumTime.tv_usec))/((double)(1000000)));
281 /*    printf("Double sum time is %f\n", fSumTime);*/
282     avg = fSumTime/((double)(a_opTimeP->numSuccesses));
283
284     printf("%15s: %d ops (%d OK); sum=%d.%06d, sqr=%d.%06d, min=%d.%06d, max=%d.%06d\n",
285            opNames[a_opIdx],
286            a_opTimeP->numOps, a_opTimeP->numSuccesses,
287            a_opTimeP->sumTime.tv_sec, a_opTimeP->sumTime.tv_usec,
288            a_opTimeP->sqrTime.tv_sec, a_opTimeP->sqrTime.tv_usec,
289            a_opTimeP->minTime.tv_sec, a_opTimeP->minTime.tv_usec,
290            a_opTimeP->maxTime.tv_sec, a_opTimeP->maxTime.tv_usec);
291
292 } /*PrintOpTiming*/
293
294
295 /*------------------------------------------------------------------------
296  * PrintXferTiming
297  *
298  * Description:
299  *      Print out the contents of a data transfer structure.
300  *
301  * Arguments:
302  *      a_opIdx : Index of the AFS operation we're printing number on.
303  *      a_xferP : Ptr to the data transfer structure to print.
304  *
305  * Returns:
306  *      Nothing.
307  *
308  * Environment:
309  *      Nothing interesting.
310  *
311  * Side Effects:
312  *      As advertised.
313  *------------------------------------------------------------------------*/
314
315 void PrintXferTiming(a_opIdx, a_xferP)
316     int a_opIdx;
317     struct fs_stats_xferData *a_xferP;
318
319 { /*PrintXferTiming*/
320
321     double fSumTime, avg;
322
323     fSumTime = ((double)(a_xferP->sumTime.tv_sec)) +
324         ((double)(a_xferP->sumTime.tv_usec))/((double)(1000000));
325
326     avg = fSumTime/((double)(a_xferP->numSuccesses));
327
328     printf("%s: %d xfers (%d OK), time sum=%d.%06d, sqr=%d.%06d, min=%d.%06d, max=%d.%06d\n",
329            xferOpNames[a_opIdx],
330            a_xferP->numXfers, a_xferP->numSuccesses,
331            a_xferP->sumTime.tv_sec, a_xferP->sumTime.tv_usec,
332            a_xferP->sqrTime.tv_sec, a_xferP->sqrTime.tv_usec,
333            a_xferP->minTime.tv_sec, a_xferP->minTime.tv_usec,
334            a_xferP->maxTime.tv_sec, a_xferP->maxTime.tv_usec);
335     printf("\t[bytes: sum=%lu, min=%d, max=%d]\n",
336            a_xferP->sumBytes, a_xferP->minBytes, a_xferP->maxBytes);
337     printf("\t[buckets: 0: %d, 1: %d, 2: %d, 3: %d, 4: %d, 5: %d, 6: %d, 7: %d, 8: %d]\n",
338            a_xferP->count[0],
339            a_xferP->count[1],
340            a_xferP->count[2],
341            a_xferP->count[3],
342            a_xferP->count[4],
343            a_xferP->count[5],
344            a_xferP->count[6],
345            a_xferP->count[7],
346            a_xferP->count[8]);
347            
348
349 } /*PrintXferTiming*/
350
351
352 /*------------------------------------------------------------------------
353  * PrintDetailedPerfInfo
354  *
355  * Description:
356  *      Print out a set of detailed performance numbers.
357  *
358  * Arguments:
359  *      a_detP : Ptr to detailed perf numbers to print.
360  *
361  * Returns:
362  *      Nothing.
363  *
364  * Environment:
365  *      Nothing interesting.
366  *
367  * Side Effects:
368  *      As advertised.
369  *------------------------------------------------------------------------*/
370
371 void PrintDetailedPerfInfo(a_detP)
372     struct fs_stats_DetailedStats *a_detP;
373
374 { /*PrintDetailedPerfInfo*/
375
376     int currIdx;        /*Loop variable*/
377
378     printf("\t%10d epoch\n", a_detP->epoch);
379
380     for (currIdx = 0; currIdx < FS_STATS_NUM_RPC_OPS; currIdx++)
381         PrintOpTiming(currIdx, &(a_detP->rpcOpTimes[currIdx]));
382
383     for (currIdx = 0; currIdx < FS_STATS_NUM_XFER_OPS; currIdx++)
384         PrintXferTiming(currIdx, &(a_detP->xferOpTimes[currIdx]));
385
386 } /*PrintDetailedPerfInfo*/
387
388
389 /*------------------------------------------------------------------------
390  * PrintFullPerfInfo
391  *
392  * Description:
393  *      Print out the AFS_XSTATSCOLL_FULL_PERF_INFO collection we just
394  *      received.
395  *
396  * Arguments:
397  *      None.
398  *
399  * Returns:
400  *      Nothing.
401  *
402  * Environment:
403  *      All the info we need is nestled into xstat_fs_Results.
404  *
405  * Side Effects:
406  *      As advertised.
407  *------------------------------------------------------------------------*/
408
409 void PrintFullPerfInfo()
410
411 { /*PrintFullPerfInfo*/
412
413     static char rn[] = "PrintFullPerfInfo";             /*Routine name*/
414     static afs_int32 fullPerfInt32s =
415         (sizeof(struct fs_stats_FullPerfStats) >> 2);   /*Correct # int32s to rcv*/
416     afs_int32 numInt32s;                                        /*# int32words received*/
417     struct fs_stats_FullPerfStats *fullPerfP;           /*Ptr to full perf stats*/
418     char *printableTime;                                /*Ptr to printable time
419                                                           string*/
420
421     numInt32s = xstat_fs_Results.data.AFS_CollData_len;
422     if (numInt32s != fullPerfInt32s) {
423         printf("** Data size mismatch in full performance collection!");
424         printf("** Expecting %d, got %d\n", fullPerfInt32s, numInt32s);
425         return;
426     }
427
428     printableTime = ctime((time_t *)&(xstat_fs_Results.probeTime));
429     printableTime[strlen(printableTime)-1] = '\0';
430     fullPerfP = (struct fs_stats_FullPerfStats *)
431         (xstat_fs_Results.data.AFS_CollData_val);
432
433     printf("AFS_XSTATSCOLL_FULL_PERF_INFO (coll %d) for FS %s\n[Probe %d, %s]\n\n",
434            xstat_fs_Results.collectionNumber,
435            xstat_fs_Results.connP->hostName,
436            xstat_fs_Results.probeNum,
437            printableTime);
438
439     PrintOverallPerfInfo(&(fullPerfP->overall));
440     PrintDetailedPerfInfo(&(fullPerfP->det));
441
442 } /*PrintFullPerfInfo*/
443
444
445 /*------------------------------------------------------------------------
446  * PrintPerfInfo
447  *
448  * Description:
449  *      Print out the AFS_XSTATSCOLL_PERF_INFO collection we just
450  *      received.
451  *
452  * Arguments:
453  *      None.
454  *
455  * Returns:
456  *      Nothing.
457  *
458  * Environment:
459  *      All the info we need is nestled into xstat_fs_Results.
460  *
461  * Side Effects:
462  *      As advertised.
463  *------------------------------------------------------------------------*/
464
465 void PrintPerfInfo()
466
467 { /*PrintPerfInfo*/
468
469     static char rn[] = "PrintPerfInfo"; /*Routine name*/
470     static afs_int32 perfInt32s =
471         (sizeof(struct afs_PerfStats) >> 2); /*Correct # int32s to rcv*/
472     afs_int32 numInt32s;                        /*# int32words received*/
473     struct afs_PerfStats *perfP;        /*Ptr to performance stats*/
474     char *printableTime;                /*Ptr to printable time string*/
475
476     numInt32s = xstat_fs_Results.data.AFS_CollData_len;
477     if (numInt32s != perfInt32s) {
478         printf("** Data size mismatch in performance collection!");
479         printf("** Expecting %d, got %d\n", perfInt32s, numInt32s);
480         return;
481     }
482
483     printableTime = ctime((time_t *)&(xstat_fs_Results.probeTime));
484     printableTime[strlen(printableTime)-1] = '\0';
485     perfP = (struct afs_PerfStats *)
486         (xstat_fs_Results.data.AFS_CollData_val);
487
488     printf("AFS_XSTATSCOLL_PERF_INFO (coll %d) for FS %s\n[Probe %d, %s]\n\n",
489            xstat_fs_Results.collectionNumber,
490            xstat_fs_Results.connP->hostName,
491            xstat_fs_Results.probeNum,
492            printableTime);
493
494     PrintOverallPerfInfo(perfP);
495
496 } /*PrintPerfInfo*/
497
498
499 /*------------------------------------------------------------------------
500  * FS_Handler
501  *
502  * Description:
503  *      Handler routine passed to the xstat_fs module.  This handler is
504  *      called immediately after a poll of one of the File Servers has
505  *      taken place.  All it needs to know is exported by the xstat_fs
506  *      module, namely the data structure where the probe results are
507  *      stored.
508  *
509  * Arguments:
510  *      None.
511  *
512  * Returns:
513  *      0 on success,
514  *      -1 otherwise.
515  *
516  * Environment:
517  *      See above.  All we do now is print out what we got.
518  *
519  * Side Effects:
520  *      As advertised.
521  *------------------------------------------------------------------------*/
522
523 int FS_Handler()
524
525 { /*FS_Handler*/
526
527     static char rn[] = "FS_Handler";    /*Routine name*/
528
529     printf("\n------------------------------------------------------------\n");
530
531     /*
532      * If the probe failed, there isn't much we can do except gripe.
533      */
534     if (xstat_fs_Results.probeOK) {
535         printf("%s: Probe %d to File Server '%s' failed, code=%d\n",
536                rn, xstat_fs_Results.probeNum,
537                xstat_fs_Results.connP->hostName,
538                xstat_fs_Results.probeOK);
539         return(0);
540     }
541
542     switch(xstat_fs_Results.collectionNumber) {
543       case AFS_XSTATSCOLL_CALL_INFO:
544         PrintCallInfo();
545         break;
546
547       case AFS_XSTATSCOLL_PERF_INFO:
548         PrintPerfInfo();
549         break;
550
551       case AFS_XSTATSCOLL_FULL_PERF_INFO:
552         PrintFullPerfInfo();
553         break;
554
555       default:
556         printf("** Unknown collection: %d\n",
557                xstat_fs_Results.collectionNumber);
558     }
559
560     /*
561      * Return the happy news.
562      */
563     return(0);
564
565 } /*FS_Handler*/
566
567
568 /*------------------------------------------------------------------------
569  * CountListItems
570  *
571  * Description:
572  *      Given a pointer to the list of File Servers we'll be polling
573  *      (or, in fact, any list at all), compute the length of the list.
574  *
575  * Arguments:
576  *      struct cmd_item *a_firstItem : Ptr to first item in list.
577  *
578  * Returns:
579  *      Length of the above list.
580  *
581  * Environment:
582  *      Nothing interesting.
583  *
584  * Side Effects:
585  *      As advertised.
586  *------------------------------------------------------------------------*/
587
588 static int CountListItems(a_firstItem)
589     struct cmd_item *a_firstItem;
590
591 { /*CountListItems*/
592
593     int list_len;               /*List length*/
594     struct cmd_item *curr_item; /*Ptr to current item*/
595
596     list_len = 0;
597     curr_item = a_firstItem;
598
599     /*
600      * Count 'em up.
601      */
602     while (curr_item) {
603       list_len++;
604       curr_item = curr_item->next;
605     }
606
607     /*
608      * Return our tally.
609      */
610     return(list_len);
611
612 } /*CountListItems*/
613
614
615 /*------------------------------------------------------------------------
616  * RunTheTest
617  *
618  * Description:
619  *      Routine called by the command line interpreter to execute the
620  *      meat of the program.  We count the number of File Servers
621  *      to watch, allocate enough space to remember all the connection
622  *      info for them, then go for it.
623  *      
624  *
625  * Arguments:
626  *      a_s : Ptr to the command line syntax descriptor.
627  *
628  * Returns:
629  *      0, but may exit the whole program on an error!
630  *
631  * Environment:
632  *      Nothing interesting.
633  *
634  * Side Effects:
635  *      As advertised.
636  *------------------------------------------------------------------------*/
637
638 int RunTheTest(a_s)
639     struct cmd_syndesc *a_s;
640
641 { /*RunTheTest*/
642
643     static char rn[] = "RunTheTest";    /*Routine name*/
644     int code;                           /*Return code*/
645     int numFSs;                         /*# File Servers to monitor*/
646     int numCollIDs;                     /*# collections to fetch*/
647     int currFS;                         /*Loop index*/
648     int currCollIDIdx;                  /*Index of current collection ID*/
649     afs_int32 *collIDP;                 /*Ptr to array of collection IDs*/
650     afs_int32 *currCollIDP;                     /*Ptr to current collection ID*/
651     struct cmd_item *curr_item;         /*Current FS cmd line record*/
652     struct sockaddr_in FSSktArray[20];  /*File Server socket array - FIX!*/
653     struct hostent *he;                 /*Host entry*/
654     struct timeval tv;                  /*Time structure*/
655     int sleep_secs;                     /*Number of seconds to sleep*/
656     int initFlags;                      /*Flags passed to the init fcn*/
657     int waitCode;                       /*Result of LWP_WaitProcess()*/
658     int freq;                           /*Frequency of polls*/
659     int period;                         /*Time in minutes of data collection*/
660
661     /*
662      * Are we doing one-shot measurements?
663      */
664     if (a_s->parms[P_ONESHOT].items != 0)
665         one_shot = 1;
666
667     /*
668      * Are we doing debugging output?
669      */
670     if (a_s->parms[P_DEBUG].items != 0)
671         debugging_on = 1;
672     
673     /*
674      * Pull out the number of File Servers to watch and the number of
675      * collections to get.
676      */
677     numFSs     = CountListItems(a_s->parms[P_FS_NAMES].items);
678     numCollIDs = CountListItems(a_s->parms[P_COLL_IDS].items);
679
680      /* Get the polling frequency */
681      if (a_s->parms[P_FREQUENCY].items != 0)
682        freq = atoi(a_s->parms[P_FREQUENCY].items->data);
683      else
684        freq = 30; /* default to 30 seconds */
685
686      /* Get the time duration to run the tests */
687      if (a_s->parms[P_PERIOD].items != 0)
688          period = atoi(a_s->parms[P_PERIOD].items->data);
689      else
690          period = 10; /* default to 10 minutes */
691
692
693     /*
694      * Fill in the socket array for each of the File Servers listed.
695      */
696     curr_item = a_s->parms[P_FS_NAMES].items;
697     for (currFS = 0; currFS < numFSs; currFS++) {
698         FSSktArray[currFS].sin_family = htons(AF_INET); /*Internet family*/
699         FSSktArray[currFS].sin_port   = htons(7000);    /*FileServer port*/
700         he = hostutil_GetHostByName(curr_item->data);
701         if (he == (struct hostent *)0) {
702             fprintf(stderr,
703                     "[%s] Can't get host info for '%s'\n",
704                     rn, curr_item->data);
705             exit(-1);
706         }
707         bcopy(he->h_addr, &(FSSktArray[currFS].sin_addr.s_addr), 4);
708
709         /*
710          * Move to the next File Server name.
711          */
712         curr_item = curr_item->next;
713
714     } /*Get socket info for each File Server*/
715
716     /*
717      * Create and fill up the array of desired collection IDs.
718      */
719     if (debugging_on)
720         printf("Allocating %d long(s) for coll ID\n", numCollIDs);
721     collIDP = (afs_int32 *)(malloc(numCollIDs * sizeof(afs_int32)));
722     currCollIDP = collIDP;
723     curr_item = a_s->parms[P_COLL_IDS].items;
724     for (currCollIDIdx = 0; currCollIDIdx < numCollIDs; currCollIDIdx++) {
725         *currCollIDP = (afs_int32)(atoi(curr_item->data));
726         if (debugging_on)
727             printf("CollID at index %d is %d\n", currCollIDIdx, *currCollIDP);
728         curr_item = curr_item->next;
729         currCollIDP++;
730     };
731
732     /*
733      * Crank up the File Server prober, then sit back and have fun.
734      */
735     printf("\nStarting up the xstat_fs service, ");
736     initFlags = 0;
737     if (debugging_on) {
738         initFlags |= XSTAT_FS_INITFLAG_DEBUGGING;
739         printf("debugging enabled, ");
740     }
741     else
742         printf("no debugging, ");
743     if (one_shot) {
744         initFlags |= XSTAT_FS_INITFLAG_ONE_SHOT;
745         printf("one-shot operation\n");
746     }
747     else
748         printf("continuous operation\n");
749
750     code = xstat_fs_Init(numFSs,        /*Num servers*/
751                          FSSktArray,    /*File Server socket array*/
752                          freq,          /*Probe frequency*/
753                          FS_Handler,    /*Handler routine*/
754                          initFlags,     /*Initialization flags*/
755                          numCollIDs,    /*Number of collection IDs*/
756                          collIDP);      /*Ptr to collection ID array*/
757     if (code) {
758         fprintf(stderr,
759                 "[%s] Error returned by xstat_fs_Init: %d\n",
760                 rn, code);
761         xstat_fs_Cleanup(1); /*Get rid of malloc'ed structures*/
762         exit(-1);
763     }
764
765     if (one_shot) {
766         /*
767          * One-shot operation; just wait for the collection to be done.
768          */
769         if (debugging_on)
770             printf("[%s] Calling LWP_WaitProcess() on event 0x%x\n",
771                     rn, &terminationEvent);
772         waitCode = LWP_WaitProcess(&terminationEvent);
773         if (debugging_on)
774             printf("[%s] Returned from LWP_WaitProcess()\n", rn);
775         if (waitCode) {
776             if (debugging_on)
777                 fprintf(stderr,
778                         "[%s] Error %d encountered by LWP_WaitProcess()\n",
779                         rn, waitCode);
780         }
781     }
782     else {
783         /*
784          * Continuous operation.
785          */
786         sleep_secs = 60*period; /*length of data collection*/
787         printf("xstat_fs service started, main thread sleeping for %d secs.\n",
788                sleep_secs);
789         
790         /*
791          * Let's just fall asleep for a while, then we'll clean up.
792          */
793         tv.tv_sec  = sleep_secs;
794         tv.tv_usec = 0;
795         code = IOMGR_Select(0,    /*Num fds*/
796                             0,    /*Descriptors ready for reading*/
797                             0,    /*Descriptors ready for writing*/
798                             0,    /*Descriptors with exceptional conditions*/
799                             &tv); /*Timeout structure*/
800         if (code) {
801             fprintf(stderr,
802                     "[%s] IOMGR_Select() returned non-zero value: %d\n",
803                     rn, code);
804         }
805     }
806
807     /*
808      * We're all done.  Clean up, put the last nail in Rx, then
809      * exit happily.
810      */
811     if (debugging_on)
812         printf("\nYawn, main thread just woke up.  Cleaning things out...\n");
813
814     code = xstat_fs_Cleanup(1); /*Get rid of malloc'ed data*/
815     rx_Finalize();
816     return(0);
817
818 } /*RunTheTest*/
819
820
821 #include "AFS_component_version_number.c"
822
823 main(argc, argv)
824     int argc;
825     char **argv;
826
827 { /*Main routine*/
828
829     static char rn[] = "xstat_fs_test"; /*Routine name*/
830     register afs_int32 code;                    /*Return code*/
831     struct cmd_syndesc *ts;             /*Ptr to cmd line syntax desc*/
832
833     /*
834      * Set up the commands we understand.
835      */
836     ts = cmd_CreateSyntax("initcmd", RunTheTest, 0,
837                           "initialize the program");
838     cmd_AddParm(ts, "-fsname", CMD_LIST,   CMD_REQUIRED,
839                 "File Server name(s) to monitor");
840     cmd_AddParm(ts, "-collID", CMD_LIST,   CMD_REQUIRED,
841                 "Collection(s) to fetch");
842     cmd_AddParm(ts, "-onceonly",  CMD_FLAG, CMD_OPTIONAL,
843                 "Collect results exactly once, then quit");
844     cmd_AddParm(ts, "-frequency", CMD_SINGLE,   CMD_OPTIONAL,
845               "poll frequency, in seconds");
846     cmd_AddParm(ts, "-period", CMD_SINGLE,   CMD_OPTIONAL,
847               "data collection time, in minutes");
848     cmd_AddParm(ts, "-debug",  CMD_FLAG, CMD_OPTIONAL,
849                 "turn on debugging output");
850
851     /*
852      * Parse command-line switches & execute the test, then get the
853      * heck out of here.
854      */
855     code = cmd_Dispatch(argc, argv);
856     if (code) {
857         fprintf(stderr,
858                 "[%s] Call to cmd_Dispatch() failed; code is %d\n",
859                 rn, code);
860     }
861
862     exit(code);
863
864 } /*Main routine*/
865