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
11 * Afsmonitor: An AFS Performance Monitoring Tool
13 *-------------------------------------------------------------------------*/
16 #include <afsconfig.h>
17 #include <afs/param.h>
28 #include <sys/types.h>
29 #include <netinet/in.h>
31 #include <sys/socket.h>
36 #include <gtxwindows.h> /*Generic window package*/
37 #include <gtxobjects.h> /*Object definitions*/
39 #include <gtxtextobj.h> /*Text object interface*/
41 #include <gtxlightobj.h> /*Light object interface*/
42 #include <gtxcurseswin.h> /*Curses window package*/
43 #include <gtxdumbwin.h> /*Dumb terminal window package*/
44 #include <gtxX11win.h> /*X11 window package*/
45 #include <gtxframe.h> /*Frame package*/
49 #include <afs/xstat_fs.h>
50 #include <afs/xstat_cm.h>
53 #include "afsmonitor.h"
56 /* command line parameter indices */
62 /* #define P_PACKAGE X */
69 int afsmon_debug = 0; /* debug info to file ? */
70 FILE *debugFD; /* debugging file descriptor */
71 static int afsmon_output = 0; /* output to file ? */
72 static int afsmon_detOutput = 0; /* detailed output ? */
73 static int afsmon_onceOnly = 0; /* probe once only ? (not implemented) */
74 int afsmon_probefreq; /* probe frequency */
75 static int wpkg_to_use; /* graphics package to use */
76 static char output_filename[80];/* output filename */
77 char errMsg[256]; /* buffers used to print error messages after*/
78 char errMsg1[256]; /* gtx is initialized (stderr/stdout gone !) */
79 int num_bufSlots = 0; /* number of slots in fs & cm circular buffers*/
81 /* Flags used to process "show" directives in config file */
82 short fs_showFlags[NUM_FS_STAT_ENTRIES];
83 short cm_showFlags[NUM_CM_STAT_ENTRIES];
86 /* afsmonitor misc definitions */
88 #define DEFAULT_FREQUENCY 60 /* default proble frequency in seconds */
89 #define DEFAULT_BUFSLOTS 0 /* default number of buffer slots */
90 #define CFG_STR_LEN 80 /* max length of config file fields */
91 #define FS 1 /* for misc. use */
92 #define CM 2 /* for misc. use */
95 #define NUM_XSTAT_FS_AFS_PERFSTATS_LONGS 66 /* number of fields (longs) in struct afs_PerfStats that we display */
96 #define NUM_AFS_STATS_CMPERF_LONGS 40 /* number of longs in struct afs_stats_CMPerf excluding up/down stats and fields we dont display */
99 /* variables used for exec'ing user provided threshold handlers */
100 char *fsHandler_argv[20]; /* *argv[] for the handler */
101 char fsHandler_args[20][256]; /* buffer space for arguments */
102 int exec_fsThreshHandler = 0; /* execute fs threshold handler ? */
105 /* THRESHOLD STRUCTURE DEFINITIONS */
107 /* flag to indicate that threshold entries apply to all hosts. these will
108 be turned off when the first fs or cm host entry is processed */
109 static int global_ThreshFlag = 1;
110 static int global_fsThreshCount = 0; /* number of global fs thresholds */
111 static int global_cmThreshCount = 0; /* number of global cm thresholds */
115 /* Linked lists of file server and cache manager host names are made from
116 the entries in the config file. Head pointers to FS and CM server name lists. */
117 static struct afsmon_hostEntry *FSnameList;
118 static struct afsmon_hostEntry *CMnameList;
120 /* number of fileservers and cache managers to monitor */
124 /* variables used for processing config file */
125 /* ptr to the hostEntry structure of the last "fs" or "cm" entry processed
126 in the config file */
127 static struct afsmon_hostEntry *last_hostEntry;
128 /* names of the last host processed in the config file */
129 static char last_fsHost[HOST_NAME_LEN];
130 static char last_cmHost[HOST_NAME_LEN];
131 static lastHostType = 0; /* 0 = no host entries processed
132 1 = last host was file server
133 2 = last host was cache manager. */
136 /* FILE SERVER CIRCULAR BUFFER VARIABLES */
138 struct afsmon_fs_Results_list {
139 struct xstat_fs_ProbeResults *fsResults; /* ptr to results struct*/
140 int empty; /* fsResults empty ? */
141 struct afsmon_fs_Results_list *next;
144 struct afsmon_fs_Results_CBuffer {
145 int probeNum; /* probe number of entries in this slot */
146 struct afsmon_fs_Results_list *list; /* ptr to list of results */
149 /* buffer for FS probe results */
150 struct afsmon_fs_Results_CBuffer *afsmon_fs_ResultsCB;
152 int afsmon_fs_curr_CBindex = 0; /* current fs CB slot */
154 /* Probe number variables. The current probe number is incremented
155 when the first probe from a new probe cycle is received. The prev probe
156 number is incremented when the last probe of the current cycle is
157 received. This difference is because of the purpose for which these
160 int afsmon_fs_curr_probeNum = 1; /* current fs probe number */
161 int afsmon_fs_prev_probeNum = 0; /* previous fs probe number */
164 /* CACHE MANAGER CIRCULAR BUFFER VARIABLES */
166 struct afsmon_cm_Results_list {
167 struct xstat_cm_ProbeResults *cmResults; /* ptr to results struct*/
168 int empty; /* cmResults empty ? */
169 struct afsmon_cm_Results_list *next;
172 struct afsmon_cm_Results_CBuffer {
173 int probeNum; /* probe number of entries in this slot */
174 struct afsmon_cm_Results_list *list; /* ptr to list of results */
177 /* buffer for CM probe results */
178 struct afsmon_cm_Results_CBuffer *afsmon_cm_ResultsCB;
180 int afsmon_cm_curr_CBindex = 0; /* current cm CB slot */
183 /* Probe number variables. The current probe number is incremented
184 when the first probe from a new probe cycle is received. The prev probe
185 number is incremented when the last probe of the current cycle is
186 received. This difference is because of the purpose for which these
189 int afsmon_cm_curr_probeNum = 1; /* current cm probe number */
190 int afsmon_cm_prev_probeNum = 0; /* previous cm probe number */
193 /* Structures to hold FS & CM results in string format(suitable for display ) */
195 /* ptr to array holding the results of FS probes in ascii format */
196 /* for current probe cycle */
197 struct fs_Display_Data *curr_fsData = (struct fs_Display_Data *)0;
198 /* for previous probe cycle */
199 struct fs_Display_Data *prev_fsData = (struct fs_Display_Data *)0;
202 /* ptr to array holding the results of CM probes in ascii format */
203 /* for current probe cycle */
204 struct cm_Display_Data *curr_cmData = (struct cm_Display_Data *)0;
205 /* for previous probe cycle */
206 struct cm_Display_Data *prev_cmData = (struct cm_Display_Data *)0;
209 /* EXTERN DEFINITIONS */
211 extern struct hostent *hostutil_GetHostByName();
215 /* routines from afsmon-output.c */
216 extern int afsmon_fsOutput();
217 extern int afsmon_cmOutput();
219 /* file server and cache manager variable names (from afsmon_labels.h) */
220 extern char *fs_varNames[];
221 extern char *cm_varNames[];
223 /* GTX & MISC VARIABLES */
225 /* afsmonitor window */
226 extern struct gwin *afsmon_win;
228 /* current page number in the overview frame */
229 extern int ovw_currPage;
231 /* number of FS alerts and number of hosts on FS alerts */
233 int numHosts_onfs_alerts;
235 /* number of CM alerts and number of hosts on FS alerts */
237 int numHosts_oncm_alerts;
239 /* flag to indicate that atleast one probe cycle has completed and
240 data is available for updating the display */
241 extern fs_Data_Available;
242 extern cm_Data_Available;
244 extern int gtx_initialized; /* gtx initialized ? */
246 /* This array contains the indices of the file server data items that
247 are to be displayed on the File Servers screen. For example, suppose the
248 user wishes to display only the vcache statistics then the following array
249 will contain indices 2 to 14 corresponding to the position of the
250 vcache data items in the fs_varNames[] array. If the config file contains
251 no "show fs .." directives, it will contain the indices of all the
252 items in the fs_varNames[] array */
254 short fs_Display_map[XSTAT_FS_FULLPERF_RESULTS_LEN];
255 int fs_DisplayItems_count = 0; /* number of items to display */
256 int fs_showDefault = 1; /* show all of FS data ? */
259 /* same use as above for Cache Managers */
260 short cm_Display_map[XSTAT_CM_FULLPERF_RESULTS_LEN];
261 int cm_DisplayItems_count = 0; /* number of items to display */
262 int cm_showDefault = 1; /* show all of CM data ? */
264 extern int fs_currPage; /* current page number in the File Servers frame */
265 extern int fs_curr_LCol; /* current leftmost column on display on FS frame */
267 extern int cm_currPage; /* current page number in the Cache Managers frame */
268 extern int cm_curr_LCol; /* current leftmost column on display on CM frame */
270 /* File server and Cache manager data is classified into sections &
271 groups to help the user choose what he wants displayed */
272 extern char *fs_categories[]; /* file server data category names */
273 extern char *cm_categories[]; /* cache manager data category names */
279 strcasestr(): Return first occurence of pattern s2 in s1, case
282 This routine is required since I made pattern matching of the
283 config file to be case insensitive.
286 char *strcasestr(s1,s2)
297 return ((char *)NULL);
301 while( len1 >= len2 && len1 > 0 ) {
302 if ( (strncasecmp(ptr,s2,len2)) == 0)
307 return ((char *)NULL);
311 struct hostent *GetHostByName(name)
319 he = gethostbyname(name);
321 /* On solaris the above does not resolve hostnames to full names */
323 memcpy(ip_addr, he->h_addr, he->h_length);
324 he = gethostbyaddr(ip_addr, he->h_length, he->h_addrtype);
331 /*-----------------------------------------------------------------------
335 * Exit gracefully from the afsmonitor. Frees memory where appropriate,
336 * cleans up after gtx and closes all open file descriptors. If a user
337 * provided threshold handler is to be exec'ed then gtx cleanup is
338 * not performed and an exec() is made instead of an exit().
344 * This function is called to execute a user handler only
345 * by a child process.
347 *----------------------------------------------------------------------*/
350 afsmon_Exit(a_exitVal)
351 int a_exitVal; /* exit code */
353 static char rn[] = "afsmon_Exit";
354 struct afsmon_fs_Results_list *tmp_fslist;
355 struct afsmon_fs_Results_list *next_fslist;
356 struct xstat_fs_ProbeResults *tmp_xstat_fsPR;
357 struct afsmon_cm_Results_list *tmp_cmlist;
358 struct afsmon_cm_Results_list *next_cmlist;
359 struct xstat_cm_ProbeResults *tmp_xstat_cmPR;
360 struct afsmon_hostEntry *curr_hostEntry;
361 struct afsmon_hostEntry *prev_hostEntry;
368 fprintf(debugFD,"[ %s ] Called with exit code %d\n",rn, a_exitVal);
372 /* get out of curses first, but not if we are here to exec a threshold
373 handler. If we do, the screen gets messed up */
374 if (gtx_initialized && ! exec_fsThreshHandler)
375 gator_cursesgwin_cleanup(afsmon_win);
377 /* print the error message buffer */
378 if (errMsg[0] != '\0')
379 fprintf(stderr,"%s",errMsg);
380 if (errMsg1[0] != '\0')
381 fprintf(stderr,"%s",errMsg1);
383 /* deallocate file server circular buffers */
384 if (numFS && num_bufSlots) {
386 fprintf(debugFD,"freeing FS circular buffers ");
390 for (bufslot=0; bufslot<num_bufSlots; bufslot++) {
392 fprintf(debugFD," %d) ",bufslot);
393 if (afsmon_fs_ResultsCB[bufslot].list !=
394 (struct afsmon_fs_Results_list *)0 ) {
395 tmp_fslist = afsmon_fs_ResultsCB[bufslot].list;
397 while ( tmp_fslist ) {
398 /* make sure we do not go astray */
401 fprintf(debugFD,"[ %s ] error in deallocating fs CB\n",
405 next_fslist = tmp_fslist->next;
406 tmp_xstat_fsPR = tmp_fslist->fsResults;
409 fprintf(debugFD,"%d ",numFS-j);
411 /* free xstat_fs_Results data */
412 free(tmp_xstat_fsPR->data.AFS_CollData_val);
413 free(tmp_xstat_fsPR->connP);
414 free(tmp_xstat_fsPR);
416 /* free the fs list item */
418 tmp_fslist = next_fslist;
420 } /* while fs list items in this slot */
421 } /* if entries in this buffer slot */
422 } /* for each fs buffer slot */
424 fprintf(debugFD,"\n");
429 /* deallocate cache manager curcular buffers */
430 if (numCM && num_bufSlots) {
432 fprintf(debugFD,"freeing CM curcular buffers ");
433 for (bufslot=0; bufslot<num_bufSlots; bufslot++) {
435 fprintf(debugFD," %d) ",bufslot);
436 if (afsmon_cm_ResultsCB[bufslot].list !=
437 (struct afsmon_cm_Results_list *)0 ) {
438 tmp_cmlist = afsmon_cm_ResultsCB[bufslot].list;
440 while ( tmp_cmlist ) {
441 /* make sure we do not go astray */
444 fprintf(debugFD,"[ %s ] error in deallocating cm CB\n",
448 next_cmlist = tmp_cmlist->next;
449 tmp_xstat_cmPR = tmp_cmlist->cmResults;
452 fprintf(debugFD,"%d ",numCM-j);
453 /* make sure data is ok */
454 /* Print_cm_FullPerfInfo(tmp_xstat_cmPR); */
456 /* free xstat_cm_Results data */
457 free(tmp_xstat_cmPR->data.AFSCB_CollData_val);
458 free(tmp_xstat_cmPR->connP);
459 free(tmp_xstat_cmPR);
461 /* free the cm list item */
463 tmp_cmlist = next_cmlist;
465 } /* while cm list items in this slot */
466 } /* if entries in this buffer slot */
467 } /* for each cm buffer slot */
469 fprintf(debugFD,"\n");
473 /* deallocate FS & CM Print buffers */
474 if (curr_fsData != (struct fs_Display_Data *)0) {
476 fprintf(debugFD,"Deallocating FS Print Buffers .... curr");
479 if (prev_fsData != (struct fs_Display_Data *)0) {
481 fprintf(debugFD,", prev \n");
484 if (prev_cmData != (struct cm_Display_Data *)0) {
486 fprintf(debugFD,"Deallocating CM Print Buffers .... curr");
489 if (prev_cmData != (struct cm_Display_Data *)0) {
491 fprintf(debugFD,", prev \n");
495 /* deallocate hostEntry lists */
498 fprintf(debugFD,"Deallocating FS hostEntries ..");
499 curr_hostEntry = FSnameList;
500 for(i=0; i<numFS; i++) {
501 prev_hostEntry = curr_hostEntry;
502 if (curr_hostEntry->thresh != NULL)
503 free(curr_hostEntry->thresh);
504 free(curr_hostEntry);
506 fprintf(debugFD," %d",i);
507 curr_hostEntry = prev_hostEntry->next;
510 fprintf(debugFD,"\n");
514 fprintf(debugFD,"Deallocating CM hostEntries ..");
515 curr_hostEntry = CMnameList;
516 for(i=0; i<numCM; i++) {
517 prev_hostEntry = curr_hostEntry;
518 if (curr_hostEntry->thresh != NULL)
519 free(curr_hostEntry->thresh);
520 free(curr_hostEntry);
522 fprintf(debugFD," %d",i);
523 curr_hostEntry = prev_hostEntry->next;
526 fprintf(debugFD,"\n");
529 /* close debug file */
535 if (exec_fsThreshHandler) {
536 code = execvp(fsHandler_argv[0],fsHandler_argv);
538 fprintf(stderr,"execvp() of %s returned %d, errno %d\n",
539 fsHandler_argv[0], code, errno);
547 /*-----------------------------------------------------------------------
551 * Insert a hostname in the file server names list.
556 *----------------------------------------------------------------------*/
559 insert_FS( a_hostName )
560 char *a_hostName; /* name of cache manager to be inserted in list */
562 static char rn[] = "insert_FS"; /* routine name */
563 static struct afsmon_hostEntry *curr_item;
564 static struct afsmon_hostEntry *prev_item;
566 if ( *a_hostName == '\0')
568 curr_item = (struct afsmon_hostEntry *)
569 malloc(sizeof(struct afsmon_hostEntry));
570 if (curr_item == (struct afsmon_hostEntry *)0) {
571 fprintf(stderr,"Failed to allocate space for FS nameList\n");
575 strncpy(curr_item->hostName,a_hostName,CFG_STR_LEN);
576 curr_item->next = (struct afsmon_hostEntry *)0;
577 curr_item->numThresh = 0;
578 curr_item->thresh = NULL;
580 if (FSnameList == (struct afsmon_hostEntry *)0)
581 FSnameList = curr_item;
583 prev_item->next = curr_item;
585 prev_item = curr_item;
586 /* record the address of this entry so that its threshold
587 count can be incremented during the first pass of the config file */
588 last_hostEntry = curr_item;
593 /*-----------------------------------------------------------------------
598 * Prints the file server names linked list.
602 *----------------------------------------------------------------------*/
606 static char rn[] = "print_FS";
607 struct afsmon_hostEntry *tempFS;
608 struct Threshold *threshP;
612 fprintf(debugFD,"[ %s ] Called\n",rn);
618 fprintf(debugFD,"No of File Servers: %d\n",numFS);
621 fprintf(debugFD,"\t %s threshCount = %d\n",
622 tempFS->hostName,tempFS->numThresh);
623 threshP = tempFS->thresh;
624 for(i=0; i<tempFS->numThresh; i++,threshP++)
625 fprintf(debugFD,"\t thresh (%2d) %s %s %s\n",
626 threshP->index, threshP->itemName,
627 threshP->threshVal,threshP->handler);
628 } while ( (tempFS = tempFS->next) != (struct afsmon_hostEntry *)0);
630 fprintf(debugFD,"\t\t-----End of List-----\n");
636 /*-----------------------------------------------------------------------
640 * Insert a hostname in the cache manager names list.
645 *----------------------------------------------------------------------*/
648 insert_CM( a_hostName )
649 char *a_hostName; /* name of cache manager to be inserted in list */
651 static char rn[] = "insert_CM"; /* routine name */
652 static struct afsmon_hostEntry *curr_item;
653 static struct afsmon_hostEntry *prev_item;
655 if ( *a_hostName == '\0')
657 curr_item = (struct afsmon_hostEntry *)
658 malloc(sizeof(struct afsmon_hostEntry));
659 if (curr_item == (struct afsmon_hostEntry *)0) {
660 fprintf(stderr,"Failed to allocate space for CM nameList\n");
664 strncpy(curr_item->hostName,a_hostName,CFG_STR_LEN);
665 curr_item->next = (struct afsmon_hostEntry *)0;
666 curr_item->numThresh = 0;
667 curr_item->thresh = NULL;
669 if (CMnameList == (struct afsmon_hostEntry *)0)
670 CMnameList = curr_item;
672 prev_item->next = curr_item;
674 prev_item = curr_item;
675 /* side effect. note the address of this entry so that its threshold
676 count can be incremented during the first pass of the config file */
677 last_hostEntry = curr_item;
683 /*-----------------------------------------------------------------------
688 * Prints the cache manager names linked list.
692 *----------------------------------------------------------------------*/
696 static char rn[] = "print_CM";
697 struct afsmon_hostEntry *tempCM;
698 struct Threshold *threshP;
702 fprintf(debugFD,"[ %s ] Called\n",rn);
708 fprintf(debugFD,"No of Cache Managers: %d\n",numCM);
711 fprintf(debugFD,"\t %s threshCount = %d\n",
712 tempCM->hostName,tempCM->numThresh);
713 threshP = tempCM->thresh;
714 for(i=0; i<tempCM->numThresh; i++,threshP++)
715 fprintf(debugFD,"\t thresh (%2d) %s %s %s\n",
716 threshP->index, threshP->itemName,
717 threshP->threshVal,threshP->handler);
718 } while ( (tempCM = tempCM->next) != (struct afsmon_hostEntry *)0);
720 fprintf(debugFD,"\t\t-----End of List-----\n");
727 /*-----------------------------------------------------------------------
731 * Parse the host entry line in the config file. Check the syntax,
732 * and inserts the host name in the FS ot CM linked list. Also
733 * remember if this entry was an fs or cm & the ptr to its hostEntry
734 * structure. The threshold entries in the config file are dependent
735 * on their position relative to the hostname entries. Hence it is
736 * required to remember the names of the last file server and cache
737 * manager entries that were processed.
743 *----------------------------------------------------------------------*/
746 parse_hostEntry(a_line)
748 { /* parse_hostEntry */
750 static char rn[] = "parse_hostEntry"; /* routine name */
751 char opcode[CFG_STR_LEN]; /* specifies type of config entry */
752 char arg1[CFG_STR_LEN]; /* hostname or qualifier (fs/cm?) */
753 char arg2[CFG_STR_LEN]; /* threshold variable */
754 char arg3[CFG_STR_LEN]; /* threshold value */
755 char arg4[CFG_STR_LEN]; /* user's handler */
756 struct hostent *he; /* host entry */
759 fprintf(debugFD,"[ %s ] Called, a_line = %s\n",rn, a_line);
764 opcode[0] = 0;arg1[0] = 0;arg2[0] = 0;arg3[0] = 0;arg4[0] = 0;
765 sscanf(a_line,"%s %s %s %s %s",opcode,arg1,arg2,arg3,arg4);
766 /* syntax is "opcode hostname" */
767 if ((strlen(arg2)) != 0) {
768 fprintf(stderr,"[ %s ] Extraneous characters at end of line\n", rn);
773 he = GetHostByName(arg1);
775 fprintf(stderr,"[ %s ] Unable to resolve hostname %s\n",
780 if ((strcasecmp(opcode,"fs")) == 0) {
781 /* use the complete host name to insert in the file server names list */
782 insert_FS(he->h_name);
783 /* note that last host entry in the config file was fs */
786 /* threholds are not global anymore */
787 if (global_ThreshFlag) global_ThreshFlag = 0;
789 else if ((strcasecmp(opcode,"cm")) == 0) {
790 /* use the complete host name to insert in the CM names list */
791 insert_CM(he->h_name);
792 /* last host entry in the config file was cm */
795 /* threholds are not global anymore */
796 if (global_ThreshFlag) global_ThreshFlag = 0;
804 /*-----------------------------------------------------------------------
805 * parse_threshEntry()
808 * Parse the threshold entry line in the config file. This function is
809 * called in the the first pass of the config file. It checks the syntax
810 * of the config lines and verifies their positional validity - eg.,
811 * a cm threshold cannot appear after a fs hostname entry, etc.
812 * It also counts the thresholds applicable to each host.
818 *----------------------------------------------------------------------*/
821 parse_threshEntry(a_line)
823 { /* parse_threshEntry */
824 static char rn[] = "parse_threshEntry"; /* routine name */
825 char opcode[CFG_STR_LEN]; /* specifies type of config entry */
826 char arg1[CFG_STR_LEN]; /* hostname or qualifier (fs/cm?) */
827 char arg2[CFG_STR_LEN]; /* threshold variable */
828 char arg3[CFG_STR_LEN]; /* threshold value */
829 char arg4[CFG_STR_LEN]; /* user's handler */
830 char arg5[CFG_STR_LEN]; /* junk characters */
833 fprintf(debugFD,"[ %s ] Called, a_line = %s\n",rn, a_line);
838 opcode[0] = 0;arg1[0] = 0;arg2[0] = 0;arg3[0] = 0;arg4[0] = 0;arg5[0] = 0;
839 sscanf(a_line,"%s %s %s %s %s %s",opcode,arg1,arg2,arg3,arg4,arg5);
841 /* syntax is "thresh fs/cm variable_name threshold_value [handler] " */
842 if (((strlen(arg1)) == 0)||((strlen(arg2)) == 0)||((strlen(arg3)) == 0)) {
843 fprintf(stderr,"[ %s ] Incomplete line\n", rn);
846 if (strlen(arg3) > THRESH_VAR_LEN-2) {
847 fprintf(stderr,"[%s ] threshold value too long\n", rn);
851 if ((strcasecmp(arg1,"fs")) == 0) {
852 switch (lastHostType) {
853 case 0: /* its a global threshold */
854 global_fsThreshCount++;
856 case 1: /* inc thresh count of last file server */
857 last_hostEntry->numThresh++;
860 fprintf(stderr,"[ %s ] A threshold for a File Server cannot be placed after a Cache Manager host entry in the config file \n",rn);
863 fprintf(stderr,"[ %s ] Programming error 1\n",rn);
866 } else if ((strcasecmp(arg1,"cm")) == 0) {
867 switch (lastHostType) {
868 case 0: /* its a global threshold */
869 global_cmThreshCount++;
871 case 2: /* inc thresh count of last cache manager */
872 last_hostEntry->numThresh++;
875 fprintf(stderr,"[ %s ] A threshold for a Cache Manager cannot be placed after a File Server host entry in the config file \n",rn);
878 fprintf(stderr,"[ %s ] Programming error 2\n",rn);
881 } else if ((strcasecmp(arg1,"cm")) != 0 && (strcasecmp(arg1,"cm")) != 0 ) {
882 fprintf(stderr,"[ %s ] Syntax error. Second argument should be \"fs\" or \"cm\" \n",rn);
887 } /* parse_threshEntry */
890 /*-----------------------------------------------------------------------
894 * The thresholds applicable to each host machine are stored in the
895 * FSnameList and CMnameList. Threshold entries in the config file are
896 * context sensitive. The host to which this threshold is applicable
897 * is pointed to by last_fsHost (for file servers) and last_cmHost
898 * for cache managers. For global thresholds the info is recorded for
899 * all the hosts. This function is called in the second pass of the
900 * config file. In the first pass a count of the number of global
901 * thresholds is determined and this information is used in this
902 * routine. If threshold entries are duplicated the first entry is
904 * Each threshold entry also has an index field. This is a positional
905 * index to the corresponding variable in the prev_[fs/cm]Data arrays.
906 * This makes it easy to check the threshold for overflow.
911 *----------------------------------------------------------------------*/
914 store_threshold(a_type,a_varName,a_value,a_handler)
915 int a_type; /* 1 = fs , 2 = cm */
916 char *a_varName; /* threshold name */
917 char *a_value; /* threshold value */
918 char *a_handler; /* threshold overflow handler */
920 { /* store_thresholds */
922 static char rn[] = "store_thresholds"; /* routine name */
923 struct afsmon_hostEntry *tmp_host; /* tmp ptr to hostEntry */
924 struct afsmon_hostEntry *Header; /* tmp ptr to hostEntry list header*/
925 struct Threshold *threshP; /* tmp ptr to threshold list */
927 int index; /* index to fs_varNames or cm_varNames */
930 int srvCount; /* tmp count of host names */
931 int *global_TC; /* ptr to global_xxThreshCount */
935 fprintf(debugFD,"[ %s ] Called, a_type= %d, a_varName= %s, a_value= %s, a_handler=%s\n",rn, a_type, a_varName, a_value, a_handler);
939 /* resolve the threshold variable name */
941 if (a_type == 1) { /* fs threshold */
942 for(index=0; index < NUM_FS_STAT_ENTRIES ; index++) {
943 if (strcasecmp(a_varName,fs_varNames[index]) == 0) {
949 fprintf(stderr,"[ %s ] Unknown FS threshold variable name %s\n",
955 hostname = last_fsHost;
956 global_TC = &global_fsThreshCount;
957 } else if (a_type == 2) { /* cm threshold */
958 for(index=0; index < NUM_CM_STAT_ENTRIES; index++) {
959 if (strcasecmp(a_varName,cm_varNames[index]) == 0) {
965 fprintf(stderr,"[ %s ] Unknown CM threshold variable name %s\n",
971 hostname = last_cmHost;
972 global_TC = &global_cmThreshCount;
978 /* if the global thresh count is not zero, place this threshold on
979 all the host entries */
983 for(i=0; i<srvCount; i++) {
984 threshP = tmp_host->thresh;
986 for(j=0; j<tmp_host->numThresh; j++) {
987 if ( (threshP->itemName[0] == '\0') ||
988 (strcasecmp(threshP->itemName,a_varName) == 0) ) {
989 strncpy(threshP->itemName,a_varName,THRESH_VAR_NAME_LEN);
990 strncpy(threshP->threshVal,a_value,THRESH_VAR_LEN);
991 strcpy(threshP->handler,a_handler);
992 threshP->index = index;
999 fprintf(stderr,"[ %s ] Could not insert threshold entry",rn);
1000 fprintf(stderr,"for %s in thresh list of host %s \n",
1001 a_varName,tmp_host->hostName);
1004 tmp_host = tmp_host->next;
1010 /* it is not a global threshold, insert it in the thresh list of this
1011 host only. We overwrite the global threshold if it was alread set */
1013 if (*hostname == '\0') {
1014 fprintf(stderr,"[ %s ] Programming error 3\n",rn);
1018 /* get the hostEntry that this threshold belongs to */
1021 for(i=0; i < srvCount; i++) {
1022 if (strcasecmp(tmp_host->hostName,hostname) == 0) {
1026 tmp_host = tmp_host->next;
1029 fprintf(stderr,"[ %s ] Unable to find host %s in %s hostEntry list",
1030 rn,hostname,(a_type-1)?"CM":"FS");
1034 /* put this entry on the thresh list of this host, overwrite global value
1037 threshP = tmp_host->thresh;
1039 for(i=0; i < tmp_host->numThresh; i++) {
1040 if ( (threshP->itemName[0] == '\0') ||
1041 (strcasecmp(threshP->itemName,a_varName) == 0) ) {
1042 strncpy(threshP->itemName,a_varName,THRESH_VAR_NAME_LEN);
1043 strncpy(threshP->threshVal,a_value,THRESH_VAR_LEN);
1044 strcpy(threshP->handler,a_handler);
1045 threshP->index = index;
1053 fprintf(stderr,"[ %s ] Unable to insert threshold %s for %s host %s\n",
1054 rn, a_varName, (a_type -1)?"CM":"FS", tmp_host->hostName);
1060 } /* store_thresholds */
1063 /*-----------------------------------------------------------------------
1067 * This function process a "show" entry in the config file. A "show"
1068 * entry specifies what statistics the user wants to see. File
1069 * server and Cache Manager data is divided into sections. Each section
1070 * is made up of one or more groups. If a group name is specified only
1071 * those statistics under that group are shown. If a section name is
1072 * specified all the groups under this section are shown.
1073 * Data as obtained from the xstat probes is considered to be ordered.
1074 * This data is mapped to the screen thru fs_Display_map[] and
1075 * cm_Display_map[]. This routine parses the "show" entry against the
1076 * section/group names in the [fs/cm]_categories[] array. If there is
1077 * no match it tries to match it against a variable name in
1078 * [fs/cm]_varNames[] array. In each case the corresponding indices to
1079 * the data is the [fs/cm]_displayInfo[] is recorded.
1083 * Failure: -1 (invalid entry)
1084 * > -1 (programming error)
1085 *----------------------------------------------------------------------*/
1088 parse_showEntry(a_line)
1090 { /* parse_showEntry */
1091 static char rn[] = "parse_showEntry";
1092 char opcode[CFG_STR_LEN]; /* specifies type of config entry */
1093 char arg1[CFG_STR_LEN]; /* show fs or cm entry ? */
1094 char arg2[CFG_STR_LEN]; /* what we gotta show */
1095 char arg3[CFG_STR_LEN]; /* junk */
1096 char catName[CFG_STR_LEN]; /* for category names */
1097 int numGroups; /* number of groups in a section */
1101 int idx = 0; /* index to fs_categories[] */
1107 fprintf(debugFD,"[ %s ] Called, a_line= %s\n",rn, a_line);
1110 opcode[0] = 0; arg1[0] = 0; arg2[0] = 0; arg3[0] = 0;
1111 sscanf(a_line,"%s %s %s %s", opcode, arg1, arg2, arg3);
1113 if (arg3[0] != '\0') {
1114 fprintf(stderr,"[ %s ] Extraneous characters at end of line\n",rn);
1118 if ((strcasecmp(arg1,"fs") != 0) && (strcasecmp(arg1,"cm") != 0)) {
1119 fprintf(stderr,"[ %s ] Second argument of \"show\" directive should be \"fs\" or \"cm\" \n",rn);
1123 /* Each entry can either be a variable name or a section/group name. Variable
1124 names are listed in xx_varNames[] and section/group names in xx_categories[].
1125 The section/group names in xx_categiries[] also give the starting/ending
1126 indices of the variables belonging to that section/group. These indices
1127 are stored in order in xx_Display_map[] and displayed to the screen in that
1130 /* To handle duplicate "show" entries we keep track of what what we have
1131 already marked to show in the xx_showFlags[] */
1133 if (strcasecmp(arg1,"fs") == 0) { /* its a File Server entry */
1135 /* mark that we have to show only what the user wants */
1138 /* if it is a section/group name, find it in the fs_categories[] array */
1141 if ( strcasestr(arg2,"_section") != (char *)NULL ||
1142 strcasestr(arg2,"_group") != (char *)NULL ) {
1144 while(idx<FS_NUM_DATA_CATEGORIES) {
1145 sscanf(fs_categories[idx],"%s %d %d",catName, &fromIdx, &toIdx);
1147 if (strcasecmp(arg2, catName) == 0) {
1153 if (! found) { /* typo in section/group name */
1154 fprintf(stderr,"[ %s ] Could not find section/group name %s\n",rn,arg2);
1159 /* if it is a group name, read its start/end indices and fill in the
1160 fs_Display_map[]. */
1162 if (strcasestr(arg2,"_group") != (char *)NULL ) {
1164 if (fromIdx < 0 || toIdx < 0 || fromIdx > NUM_FS_STAT_ENTRIES ||
1165 toIdx > NUM_FS_STAT_ENTRIES)
1167 for(j=fromIdx; j<=toIdx; j++) {
1168 if (! fs_showFlags[j]) {
1169 fs_Display_map[fs_DisplayItems_count] = j;
1170 fs_DisplayItems_count++;
1171 fs_showFlags[j] = 1;
1173 if (fs_DisplayItems_count > NUM_FS_STAT_ENTRIES) {
1174 fprintf(stderr,"[ %s ] fs_DisplayItems_count ovf\n",rn);
1180 /* if it is a section name, get the count of number of groups in it and
1181 for each group fill in the start/end indices in the fs_Display_map[] */
1183 if (strcasestr(arg2,"_section") != (char *)NULL ) {
1184 /* fromIdx is actually the number of groups in thi section */
1185 numGroups = fromIdx;
1186 /* for each group in section */
1187 while(idx < FS_NUM_DATA_CATEGORIES && numGroups) {
1188 sscanf(fs_categories[idx],"%s %d %d",catName, &fromIdx, &toIdx);
1190 if (strcasestr(catName,"_group") != NULL) {
1191 if (fromIdx < 0 || toIdx < 0 || fromIdx > NUM_FS_STAT_ENTRIES ||
1192 toIdx > NUM_FS_STAT_ENTRIES)
1194 for(j=fromIdx; j<=toIdx; j++) {
1195 if (! fs_showFlags[j]) {
1196 fs_Display_map[fs_DisplayItems_count] = j;
1197 fs_DisplayItems_count++;
1198 fs_showFlags[j] = 1;
1200 if (fs_DisplayItems_count > NUM_FS_STAT_ENTRIES) {
1201 fprintf(stderr,"[ %s ] fs_DisplayItems_count ovf\n",rn);
1206 fprintf(stderr,"[ %s ] Error parsing groups for %s\n",rn,arg2);
1211 } /* for each group in section */
1214 } else { /* it is a variable name */
1216 for(i=0; i<NUM_FS_STAT_ENTRIES; i++) {
1217 if (strcasecmp(arg2, fs_varNames[i]) == 0) {
1218 if (! fs_showFlags[i]) {
1219 fs_Display_map[fs_DisplayItems_count] = i;
1220 fs_DisplayItems_count++;
1221 fs_showFlags[i] = 1;
1223 if (fs_DisplayItems_count >= NUM_FS_STAT_ENTRIES) {
1224 fprintf(stderr,"[ %s ] fs_DisplayItems_count ovf\n",rn);
1230 if (! found) { /* typo in section/group name */
1231 fprintf(stderr,"[ %s ] Could not find variable name %s\n",rn,arg2);
1234 } /* its a variable name */
1236 } /* it is an fs entry */
1239 if (strcasecmp(arg1,"cm") == 0) { /* its a Cache Manager entry */
1242 /* mark that we have to show only what the user wants */
1245 /* if it is a section/group name, find it in the cm_categories[] array */
1248 if ( strcasestr(arg2,"_section") != (char *)NULL ||
1249 strcasestr(arg2,"_group") != (char *)NULL ) {
1251 while(idx<CM_NUM_DATA_CATEGORIES) {
1252 sscanf(cm_categories[idx],"%s %d %d",catName, &fromIdx, &toIdx);
1254 if (strcasecmp(arg2, catName) == 0) {
1260 if (! found) { /* typo in section/group name */
1261 fprintf(stderr,"[ %s ] Could not find section/group name %s\n",rn,arg2);
1266 /* if it is a group name, read its start/end indices and fill in the
1267 cm_Display_map[]. */
1269 if (strcasestr(arg2,"_group") != (char *)NULL ) {
1271 if (fromIdx < 0 || toIdx < 0 || fromIdx > NUM_CM_STAT_ENTRIES ||
1272 toIdx > NUM_CM_STAT_ENTRIES)
1274 for(j=fromIdx; j<=toIdx; j++) {
1275 if (! cm_showFlags[j]) {
1276 cm_Display_map[cm_DisplayItems_count] = j;
1277 cm_DisplayItems_count++;
1278 cm_showFlags[j] = 1;
1280 if (cm_DisplayItems_count > NUM_CM_STAT_ENTRIES) {
1281 fprintf(stderr,"[ %s ] cm_DisplayItems_count ovf\n",rn);
1287 /* if it is a section name, get the count of number of groups in it and
1288 for each group fill in the start/end indices in the cm_Display_map[] */
1290 if (strcasestr(arg2,"_section") != (char *)NULL ) {
1291 /* fromIdx is actually the number of groups in thi section */
1292 numGroups = fromIdx;
1293 /* for each group in section */
1294 while(idx < CM_NUM_DATA_CATEGORIES && numGroups) {
1295 sscanf(cm_categories[idx],"%s %d %d",catName, &fromIdx, &toIdx);
1297 if (strcasestr(catName,"_group") != NULL) {
1298 if (fromIdx < 0 || toIdx < 0 || fromIdx > NUM_CM_STAT_ENTRIES ||
1299 toIdx > NUM_CM_STAT_ENTRIES)
1301 for(j=fromIdx; j<=toIdx; j++) {
1302 if (! cm_showFlags[j]) {
1303 cm_Display_map[cm_DisplayItems_count] = j;
1304 cm_DisplayItems_count++;
1305 cm_showFlags[j] = 1;
1307 if (cm_DisplayItems_count > NUM_CM_STAT_ENTRIES) {
1308 fprintf(stderr,"[ %s ] cm_DisplayItems_count ovf\n",rn);
1313 fprintf(stderr,"[ %s ] Error parsing groups for %s\n",rn,arg2);
1318 } /* for each group in section */
1325 } else { /* it is a variable name */
1327 for(i=0; i<NUM_CM_STAT_ENTRIES; i++) {
1328 if (strcasecmp(arg2, cm_varNames[i]) == 0) {
1329 if (! cm_showFlags[i]) {
1330 cm_Display_map[cm_DisplayItems_count] = i;
1331 cm_DisplayItems_count++;
1332 cm_showFlags[i] = 1;
1334 if (cm_DisplayItems_count >= NUM_CM_STAT_ENTRIES) {
1335 fprintf(stderr,"[ %s ] cm_DisplayItems_count ovf\n",rn);
1341 if (! found) { /* typo in section/group name */
1342 fprintf(stderr,"[ %s ] Could not find variable name %s\n",rn,arg2);
1345 } /* its a variable name */
1347 } /* it is an cm entry */
1352 } /* parse_showEntry */
1355 /*-----------------------------------------------------------------------
1356 * process_config_file()
1359 * Parse config file entries in two passes. In the first pass:
1360 * - the syntax of all the entries is checked
1361 * - host names are noted and the FSnamesList and CMnamesList
1363 * - a count of the global thresholds and local thresholds of
1364 * each host are counted.
1365 * - "show" entries are processed.
1366 * In the second pass:
1367 * - thresholds are stored
1371 * Failure: Exits afsmonitor showing error and line.
1372 *----------------------------------------------------------------------*/
1375 process_config_file(a_config_filename)
1376 char *a_config_filename;
1377 { /* process_config_file() */
1378 static char rn[] = "process_config_file"; /* routine name */
1379 FILE *configFD; /* config file descriptor */
1380 char line[4*CFG_STR_LEN]; /* a line of config file */
1381 char opcode[CFG_STR_LEN]; /* specifies type of config entry */
1382 char arg1[CFG_STR_LEN]; /* hostname or qualifier (fs/cm?) */
1383 char arg2[CFG_STR_LEN]; /* threshold variable */
1384 char arg3[CFG_STR_LEN]; /* threshold value */
1385 char arg4[CFG_STR_LEN]; /* user's handler */
1386 struct afsmon_hostEntry *curr_host;
1387 struct hostent *he; /* hostentry to resolve host name*/
1388 char *handlerPtr; /* ptr to pass theresh handler string */
1389 int code = 0; /* error code */
1390 int linenum = 0; /* config file line number */
1391 int threshCount; /* count of thresholds for each server */
1392 int error_in_config; /* syntax errors in config file ?? */
1397 fprintf(debugFD,"[ %s ] Called, a_config_filename= %s\n",
1398 rn, a_config_filename);
1402 /* open config file */
1404 configFD = fopen(a_config_filename,"r");
1405 if (configFD == (FILE *)0) {
1406 fprintf(stderr,"Failed to open config file %s \n",a_config_filename);
1408 fprintf(debugFD,"[ %s ] Failed to open config file %s \n",
1409 rn, a_config_filename);
1415 /* parse config file */
1417 /* We process the config file in two passes. In the first pass we check
1418 for correct syntax and for valid entries and also keep count of the
1419 number of servers and thresholds to monitor. This the data strctures
1420 can be arrays instead of link lists since we would know their sizes.*/
1427 error_in_config = 0; /* flag to note if config file has syntax errors*/
1429 while ( (fgets(line,CFG_STR_LEN,configFD)) != NULL)
1431 opcode[0] = 0; arg1[0] = 0; arg2[0] = 0; arg3[0] = 0; arg4[0] = 0;
1432 sscanf(line,"%s %s %s %s %s", opcode, arg1, arg2, arg3, arg4);
1434 /* skip blank lines and comment lines */
1435 if ( (strlen(opcode) == 0) || line[0] == '#' ) continue;
1437 if ( (strcasecmp(opcode,"fs") == 0) || (strcasecmp(opcode,"cm")) == 0) {
1438 code = parse_hostEntry(line);
1439 } else if ((strcasecmp(opcode,"thresh")) == 0) {
1440 code = parse_threshEntry(line);
1441 } else if ((strcasecmp(opcode,"show")) == 0) {
1442 code = parse_showEntry(line);
1444 fprintf(stderr,"[ %s ] Unknown opcode %s\n",rn,opcode);
1449 fprintf(stderr,"[ %s ] Error in line:\n %d: %s\n",
1451 error_in_config = 1;
1455 if (error_in_config)
1459 fprintf(debugFD,"Global FS thresholds count = %d\n",global_fsThreshCount);
1460 fprintf(debugFD,"Global CM thresholds count = %d\n",global_cmThreshCount);
1464 /* the threshold count of all hosts in increased by 1 for each global
1465 threshold. If one of the hosts has a local threshold for the same
1466 variable it would end up being counted twice. whats a few bytes of memory
1469 if (global_fsThreshCount) {
1470 curr_host = FSnameList;
1471 for(i=0; i<numFS; i++) {
1472 curr_host->numThresh += global_fsThreshCount;
1473 curr_host = curr_host->next;
1476 if (global_cmThreshCount) {
1477 curr_host = CMnameList;
1478 for(i=0; i<numCM; i++) {
1479 curr_host->numThresh += global_cmThreshCount;
1480 curr_host = curr_host->next;
1485 /* make sure we have something to monitor */
1486 if (numFS == 0 && numCM == 0) {
1487 fprintf(stderr,"\nConfig file must specify atleast one File Server or Cache Manager host to monitor.\n");
1494 fseek(configFD,0,0); /* seek to the beginning */
1497 /* allocate memory for threshold lists */
1498 curr_host = FSnameList;
1499 for(i=0; i<numFS; i++) {
1500 if (curr_host->hostName[0] == '\0') {
1501 fprintf(stderr,"[ %s ] Programming error 4\n",rn);
1504 if (curr_host->numThresh) {
1505 numBytes = curr_host->numThresh * sizeof(struct Threshold);
1506 curr_host->thresh = (struct Threshold *) malloc(numBytes);
1507 if (curr_host->thresh == NULL) {
1508 fprintf(stderr,"[ %s ] Memory Allocation error 1",rn);
1511 memset(curr_host->thresh, 0, numBytes);
1513 curr_host = curr_host->next;;
1516 curr_host = CMnameList;
1517 for(i=0; i<numCM; i++) {
1518 if (curr_host->hostName[0] == '\0') {
1519 fprintf(stderr,"[ %s ] Programming error 5\n",rn);
1522 if (curr_host->numThresh) {
1523 numBytes = curr_host->numThresh * sizeof(struct Threshold);
1524 curr_host->thresh = (struct Threshold *) malloc(numBytes);
1525 if (curr_host->thresh == NULL) {
1526 fprintf(stderr,"[ %s ] Memory Allocation error 2",rn);
1529 memset(curr_host->thresh, 0, numBytes);
1531 curr_host = curr_host->next;;
1535 opcode[0] = 0; arg1[0] = 0; arg2[0] = 0; arg3[0] = 0; arg4[0] = 0;
1536 last_fsHost[0] = '\0';
1537 last_cmHost[0] = '\0';
1539 while ( (fgets(line,CFG_STR_LEN,configFD)) != NULL) {
1540 opcode[0] = 0; arg1[0] = 0; arg2[0] = 0; arg3[0] = 0; arg4[0] = 0;
1541 sscanf(line,"%s %s %s %s %s", opcode, arg1, arg2, arg3, arg4);
1544 /* if we have a host entry, remember the host name */
1545 if (strcasecmp(opcode,"fs") == 0) {
1546 he = GetHostByName(arg1);
1547 strncpy(last_fsHost,he->h_name,HOST_NAME_LEN);
1549 else if (strcasecmp(opcode,"cm") == 0) {
1550 he = GetHostByName(arg1);
1551 strncpy(last_cmHost,he->h_name,HOST_NAME_LEN);
1553 else if (strcasecmp(opcode,"thresh") == 0) {
1554 /* if we have a threshold handler it may have arguments
1555 and the sscanf() above would not get them, so do the
1559 /* now skip over 4 words - this is done by first
1560 skipping leading blanks then skipping a word */
1561 for(i=0; i<4; i++) {
1562 while( isspace(*handlerPtr) )
1564 while(! isspace(*handlerPtr) )
1567 while( isspace(*handlerPtr) )
1569 /* we how have a pointer to the start of the handler
1572 handlerPtr = arg4; /* empty string */
1575 if (strcasecmp(arg1,"fs") == 0)
1576 code = store_threshold(1, /* 1 = fs*/
1577 arg2,arg3,handlerPtr);
1579 else if (strcasecmp(arg1,"cm") == 0)
1580 code = store_threshold(2, /* 2 = fs*/
1581 arg2,arg3,handlerPtr);
1584 fprintf(stderr,"[ %s ] Programming error 6\n", rn);
1588 fprintf(stderr,"[ %s ] Failed to store threshold\n",
1590 fprintf(stderr,"[ %s ] Error processing line:\n%d: %s",
1602 /*-----------------------------------------------------------------------
1607 * Print the File Server circular buffer.
1611 *----------------------------------------------------------------------*/
1615 { /* Print_FS_CB() */
1617 struct afsmon_fs_Results_list *fslist;
1621 /* print valid info in the fs CB */
1624 fprintf(debugFD,"==================== FS Buffer ========================\n");
1625 fprintf(debugFD,"afsmon_fs_curr_CBindex = %d\n",afsmon_fs_curr_CBindex);
1626 fprintf(debugFD,"afsmon_fs_curr_probeNum = %d\n\n",afsmon_fs_curr_probeNum);
1628 for(i=0; i<num_bufSlots; i++) {
1629 fprintf(debugFD,"\t--------- slot %d ----------\n",i);
1630 fslist = afsmon_fs_ResultsCB[i].list;
1632 while( j < numFS ) {
1633 if (! fslist->empty) {
1634 fprintf(debugFD,"\t %d) probeNum = %d host = %s",
1635 j,fslist->fsResults->probeNum,
1636 fslist-> fsResults->connP->hostName);
1637 if (fslist->fsResults->probeOK) fprintf(debugFD," NOTOK\n");
1638 else fprintf(debugFD," OK\n");
1640 fprintf(debugFD,"\t %d) -- empty --\n",j);
1641 fslist = fslist->next;
1644 if (fslist != (struct afsmon_fs_Results_list *)0 )
1645 fprintf(debugFD,"dangling last next ptr fs CB\n");
1648 } /* Print_FS_CB() */
1650 /*-----------------------------------------------------------------------
1651 * save_FS_results_inCB()
1654 * Saves the results of the latest FS probe in the fs circular
1655 * buffers. If the current probe cycle is in progress the contents
1656 * of xstat_fs_Results are copied to the end of the list of results
1657 * in the current slot (pointed to by afsmon_fs_curr_CBindex). If
1658 * a new probe cycle has started the next slot in the circular buffer
1659 * is initialized and the results copied. Note that the Rx related
1660 * information available in xstat_fs_Results is not copied.
1664 * Failure: Exits afsmonitor.
1665 *----------------------------------------------------------------------*/
1667 save_FS_results_inCB(a_newProbeCycle)
1668 int a_newProbeCycle; /* start of a new probe cycle ? */
1670 { /* save_FS_results_inCB() */
1671 static char rn[] = "save_FS_results_inCB"; /* routine name */
1672 struct afsmon_fs_Results_list *tmp_fslist_item; /* temp fs list item */
1673 struct xstat_fs_ProbeResults *tmp_fsPR; /* temp ptr */
1677 fprintf(debugFD,"[ %s ] Called, a_newProbeCycle= %d\n",
1678 rn, a_newProbeCycle);
1683 /* If a new probe cycle started, mark the list in the current buffer
1684 slot empty for resuse. Note that afsmon_fs_curr_CBindex was appropriately
1685 incremented in afsmon_FS_Handler() */
1687 if (a_newProbeCycle) {
1688 tmp_fslist_item = afsmon_fs_ResultsCB[afsmon_fs_curr_CBindex].list;
1689 for(i=0; i<numFS; i++) {
1690 tmp_fslist_item->empty = 1;
1691 tmp_fslist_item = tmp_fslist_item->next;
1695 /* locate last unused item in list */
1696 tmp_fslist_item = afsmon_fs_ResultsCB[afsmon_fs_curr_CBindex].list;
1697 for(i=0; i<numFS; i++) {
1698 if (tmp_fslist_item->empty) break;
1699 tmp_fslist_item = tmp_fslist_item->next;
1702 /* if we could not find one we have an inconsistent list */
1703 if ( ! tmp_fslist_item->empty ) {
1704 fprintf(stderr,"[ %s ] list inconsistency 1. unable to find an empty slot to store results of probenum %d of %s\n",rn,
1705 xstat_fs_Results.probeNum,xstat_fs_Results.connP->hostName);
1709 tmp_fsPR = tmp_fslist_item->fsResults;
1711 /* copy hostname and probe number and probe time and probe status.
1712 if the probe failed return now */
1714 memcpy(tmp_fsPR->connP->hostName, xstat_fs_Results.connP->hostName, sizeof(xstat_fs_Results.connP->hostName));
1715 tmp_fsPR->probeNum = xstat_fs_Results.probeNum;
1716 tmp_fsPR->probeTime = xstat_fs_Results.probeTime;
1717 tmp_fsPR->probeOK = xstat_fs_Results.probeOK;
1718 if (xstat_fs_Results.probeOK) { /* probeOK = 1 => notOK */
1719 /* we have a nonempty results structure so mark the list item used */
1720 tmp_fslist_item->empty = 0;
1724 /* copy connection information */
1725 memcpy(&(tmp_fsPR->connP->skt), &(xstat_fs_Results.connP->skt), sizeof(struct sockaddr_in));
1727 memcpy(tmp_fsPR->connP->hostName, xstat_fs_Results.connP->hostName, sizeof(xstat_fs_Results.connP->hostName));
1728 tmp_fsPR->collectionNumber = xstat_fs_Results.collectionNumber;
1730 /* copy the probe data information */
1731 tmp_fsPR->data.AFS_CollData_len = xstat_fs_Results.data.AFS_CollData_len;
1732 memcpy(tmp_fsPR->data.AFS_CollData_val, xstat_fs_Results.data.AFS_CollData_val, xstat_fs_Results.data.AFS_CollData_len * sizeof(afs_int32));
1735 /* we have a valid results structure so mark the list item used */
1736 tmp_fslist_item->empty = 0;
1738 /* Print the fs circular buffer */
1742 } /* save_FS_results_inCB() */
1745 /*-----------------------------------------------------------------------
1749 * The results of xstat probes are stored in a string format in
1750 * the arrays curr_fsData and prev_fsData. The information stored in
1751 * prev_fsData is copied to the screen.
1752 * This function converts xstat FS results from longs to strings and
1753 * place them in the given buffer (a pointer to an item in curr_fsData).
1754 * When a probe cycle completes, curr_fsData is copied to prev_fsData
1755 * in afsmon_FS_Hnadler().
1759 *----------------------------------------------------------------------*/
1762 fs_Results_ltoa(a_fsData,a_fsResults)
1763 struct fs_Display_Data *a_fsData; /* target buffer */
1764 struct xstat_fs_ProbeResults *a_fsResults; /* ptr to xstat fs Results */
1765 { /* fs_Results_ltoa */
1767 static char rn[] = "fs_Results_ltoa"; /* routine name */
1769 struct fs_stats_FullPerfStats *fullPerfP;
1775 fprintf(debugFD,"[ %s ] Called, a_fsData= %d, a_fsResults= %d\n",
1776 rn, a_fsData, a_fsResults);
1780 fullPerfP = (struct fs_stats_FullPerfStats *)
1781 (a_fsResults->data.AFS_CollData_val);
1783 /* there are two parts to the xstat FS statistics
1784 - fullPerfP->overall which give the overall performance statistics, and
1785 - fullPerfP->det which gives detailed info about file server operation
1788 /* copy overall performance statistics */
1789 srcbuf = (afs_int32 *) &(fullPerfP->overall);
1791 for(i=0; i< NUM_XSTAT_FS_AFS_PERFSTATS_LONGS; i++) {
1792 sprintf(a_fsData->data[idx],"%d",*srcbuf);
1798 srcbuf = (afs_int32 *) &(fullPerfP->det.epoch);
1799 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* epoch */
1802 /* copy fs operation timing */
1804 srcbuf = (afs_int32 *) (fullPerfP->det.rpcOpTimes);
1806 for(i=0; i<FS_STATS_NUM_RPC_OPS; i++) {
1807 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* numOps*/
1809 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* numSuccesses */
1811 tmpbuf = srcbuf++; /* sum time */
1812 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1814 tmpbuf = srcbuf++; /* sqr time */
1815 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1817 tmpbuf = srcbuf++; /* min time */
1818 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1820 tmpbuf = srcbuf++; /* max time */
1821 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1825 /* copy fs transfer timings */
1827 srcbuf = (afs_int32 *) (fullPerfP->det.xferOpTimes);
1828 for(i=0; i<FS_STATS_NUM_XFER_OPS; i++) {
1829 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* numOps*/
1831 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* numSuccesses */
1833 tmpbuf = srcbuf++; /* sum time */
1834 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1836 tmpbuf = srcbuf++; /* sqr time */
1837 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1839 tmpbuf = srcbuf++; /* min time */
1840 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1842 tmpbuf = srcbuf++; /* max time */
1843 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1845 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* sum bytes */
1847 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* min bytes */
1849 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* max bytes */
1851 for(j=0; j<FS_STATS_NUM_XFER_BUCKETS; j++) {
1852 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* bucket[j] */
1858 } /* fs_Results_ltoa */
1862 /*-----------------------------------------------------------------------
1863 * execute_thresh_handler()
1866 * Execute a threshold handler. An agrv[] array of pointers is
1867 * constructed from the given data. A child process is forked
1868 * which immediately calls afsmon_Exit() with indication that a
1869 * threshold handler is to be exec'ed insted of exiting.
1873 * Failure: Afsmonitor exits if threshold handler has more than 20 args.
1874 *----------------------------------------------------------------------*/
1877 execute_thresh_handler(a_handler, a_hostName, a_hostType,
1878 a_threshName,a_threshValue, a_actValue)
1879 char *a_handler; /* ptr to handler function + args */
1880 char *a_hostName; /* host name for which threshold crossed */
1881 int a_hostType; /* fs or cm ? */
1882 char *a_threshName; /* threshold variable name */
1883 char *a_threshValue; /* threshold value */
1884 char *a_actValue; /* actual value */
1886 { /* execute_thresh_handler */
1888 static char rn[] = "execute_thresh_handler";
1889 char fileName[256]; /* file name to execute */
1894 int anotherArg; /* boolean used to flag if another arg is available */
1897 fprintf(debugFD,"[ %s ] Called, a_handler= %s, a_hostName= %s, a_hostType= %d, a_threshName= %s, a_threshValue= %s, a_actValue= %s\n",
1898 rn, a_handler, a_hostName, a_hostType, a_threshName, a_threshValue,
1904 /* get the filename to execute - the first argument */
1905 sscanf(a_handler,"%s",fileName);
1907 /* construct the contents of *argv[] */
1909 strncpy(fsHandler_args[0], fileName,256);
1910 strncpy(fsHandler_args[1], a_hostName, HOST_NAME_LEN);
1911 if (a_hostType == FS) strcpy(fsHandler_args[2], "fs");
1912 else strcpy(fsHandler_args[2], "cm");
1913 strncpy(fsHandler_args[3], a_threshName, THRESH_VAR_NAME_LEN);
1914 strncpy(fsHandler_args[4], a_threshValue, THRESH_VAR_LEN);
1915 strncpy(fsHandler_args[5], a_actValue, THRESH_VAR_LEN);
1922 /* we have already extracted the file name so skip to the 1st arg */
1923 while (isspace(*ch)) /* leading blanks */
1925 while (! isspace(*ch) && *ch != '\0') /* handler filename */
1928 while( *ch != '\0' ) {
1931 } else if (anotherArg) {
1933 sscanf(ch,"%s",fsHandler_args[argNum]);
1939 "Threshold handlers cannot have more than 20 arguments\n");
1945 fsHandler_argv[argNum] = NULL;
1946 for(i=0; i<argNum; i++)
1947 fsHandler_argv[i] = fsHandler_args[i];
1950 /* exec the threshold handler */
1953 exec_fsThreshHandler = 1;
1954 code = afsmon_Exit(60);
1958 } /* execute_thresh_handler */
1962 /*-----------------------------------------------------------------------
1963 * check_fs_thresholds()
1966 * Checks the thresholds and sets the overflow flag. Recall that the
1967 * thresholds for each host are stored in the hostEntry lists
1968 * [fs/cm]nameList arrays. The probe results are passed to this
1969 * function in the display-ready format - ie., as strings. Though
1970 * this looks stupid the overhead incurred in converting the strings
1971 * back to floats and comparing them is insignificant and
1972 * programming is easier this way.
1973 * The threshold flags are a part of the display structures
1978 *----------------------------------------------------------------------*/
1981 check_fs_thresholds(a_hostEntry, a_Data)
1982 struct afsmon_hostEntry *a_hostEntry; /* ptr to hostEntry */
1983 struct fs_Display_Data *a_Data; /* ptr to fs data to be displayed */
1985 { /* check_fs_thresholds */
1987 static char rn[] = "check_fs_thresholds";
1988 struct Threshold *threshP;
1989 double tValue; /* threshold value */
1990 double pValue; /* probe value */
1993 int count; /* number of thresholds exceeded */
1996 fprintf(debugFD,"[ %s ] Called, a_hostEntry= %d, a_Data= %d\n",
1997 rn, a_hostEntry, a_Data);
2001 if (a_hostEntry->numThresh == 0) {
2002 /* store in ovf count ?? */
2007 threshP = a_hostEntry->thresh;
2008 for(i=0; i < a_hostEntry->numThresh; i++) {
2009 if (threshP->itemName[0] == '\0') {
2010 threshP++; continue;
2012 idx = threshP->index; /* positional index to the data array */
2013 tValue = atof(threshP->threshVal); /* threshold value */
2014 pValue = atof(a_Data->data[idx]); /* probe value */
2015 if (pValue > tValue) {
2018 fprintf(debugFD,"[ %s ] fs = %s, thresh ovf for %s, threshold= %s, probevalue= %s\n",
2019 rn, a_hostEntry->hostName, threshP->itemName, threshP->threshVal, a_Data->data[idx]);
2022 /* if the threshold is crossed, call the handler function
2023 only if this was a transition -ie, if the threshold was
2024 crossed in the last probe too just count & keep quite! */
2026 if (! a_Data->threshOvf[idx]) {
2027 a_Data->threshOvf[idx] = 1;
2028 /* call the threshold handler if provided */
2029 if (threshP->handler[0] != '\0') {
2031 fprintf(debugFD,"[ %s ] Calling ovf handler %s\n",
2032 rn, threshP->handler);
2035 execute_thresh_handler(threshP->handler,
2036 a_Data->hostName, FS, threshP->itemName,
2037 threshP->threshVal, a_Data->data[idx]);
2043 /* in case threshold was previously crossed, blank it out */
2044 a_Data->threshOvf[idx] = 0;
2047 /* store the overflow count */
2048 a_Data->ovfCount = count;
2051 } /* check_fs_thresholds */
2054 /*-----------------------------------------------------------------------
2055 * save_FS_data_forDisplay()
2058 * Does the following:
2059 * - if the probe number changed (ie, a cycle completed) curr_fsData
2060 * is copied to prev_fsData, curr_fsData zeroed and refresh the
2061 * overview screen and file server screen with the new data.
2062 * - store the results of the current probe from xstat_fs_Results into
2063 * curr_fsData. ie., convert longs to strings.
2064 * - check the thresholds
2068 * Failure: Exits afsmonitor.
2069 *----------------------------------------------------------------------*/
2072 save_FS_data_forDisplay(a_fsResults)
2073 struct xstat_fs_ProbeResults *a_fsResults;
2074 { /* save_FS_data_forDisplay */
2076 static char rn[] = "save_FS_data_forDisplay"; /* routine name */
2077 struct fs_Display_Data *curr_fsDataP; /* tmp ptr to curr_fsData*/
2078 struct fs_Display_Data *prev_fsDataP; /* tmp ptr to prev_fsData*/
2079 struct afsmon_hostEntry *curr_host;
2080 static int probes_Received = 0; /* number of probes reveived in
2081 the current cycle. If this is equal to numFS we got all
2082 the data we want in this cycle and can now display it */
2091 fprintf(debugFD,"[ %s ] Called, a_fsResults= %d\n",rn, a_fsResults);
2097 /* store results in the display array */
2100 curr_fsDataP = curr_fsData;
2101 for (i=0; i<numFS; i++) {
2102 if((strcasecmp(curr_fsDataP->hostName,a_fsResults->connP->hostName)) == 0) {
2110 fprintf(stderr,"[ %s ] Could not insert FS probe results for host %s in fs display array\n",rn, a_fsResults->connP->hostName);
2114 /* Check the status of the probe. If it succeeded, we store its
2115 results in the display data structure. If it failed we only mark
2116 the failed status in the display data structure. */
2118 if (a_fsResults->probeOK) { /* 1 => notOK the xstat results */
2119 curr_fsDataP->probeOK = 0;
2121 /* print the probe status */
2123 fprintf(debugFD,"\n\t\t ----- fs display data ------\n");
2124 fprintf(debugFD,"HostName = %s PROBE FAILED \n",curr_fsDataP->hostName);
2128 } else { /* probe succeeded, update display data structures */
2129 curr_fsDataP->probeOK = 1;
2131 /* covert longs to strings and place them in curr_fsDataP */
2132 fs_Results_ltoa(curr_fsDataP, a_fsResults);
2134 /* compare with thresholds and set the overflow flags.
2135 note that the threshold information is in the hostEntry structure and
2136 each threshold item has a positional index associated with it */
2138 /* locate the hostEntry for this host */
2140 curr_host = FSnameList;
2141 for(i=0; i<numFS; i++) {
2142 if(strcasecmp(curr_host->hostName,a_fsResults->connP->hostName) == 0) {
2146 curr_host = curr_host->next;;
2148 if (!done) afsmon_Exit(70);
2150 code = check_fs_thresholds(curr_host, curr_fsDataP);
2152 fprintf(stderr,"[ %s ] Error in checking thresholds\n",rn);
2159 /* print the info we just saved */
2162 fprintf(debugFD,"\n\t\t ----- fs display data ------\n");
2163 fprintf(debugFD,"HostName = %s\n",curr_fsDataP->hostName);
2164 for(i=0; i<NUM_FS_STAT_ENTRIES; i++)
2165 fprintf(debugFD,"%20s %30s %s\n", curr_fsDataP->data[i],
2166 fs_varNames[i], curr_fsDataP->threshOvf[i] ? "(ovf)":"" );
2168 fprintf(debugFD,"\t\t--------------------------------\n\n");
2172 } /* the probe succeeded, so we store the data in the display structure */
2175 /* if we have received a reply from all the hosts for this probe cycle,
2176 it is time to display the data */
2179 if (probes_Received == numFS) {
2180 probes_Received = 0;
2182 if (afsmon_fs_curr_probeNum != afsmon_fs_prev_probeNum + 1) {
2183 sprintf(errMsg,"[ %s ] Probe number %d missed! \n",
2184 rn, afsmon_fs_prev_probeNum +1);
2187 afsmon_fs_prev_probeNum++;
2189 /* backup the display data of the probe cycle that just completed -
2190 ie., store curr_fsData in prev_fsData */
2192 memcpy((char *)prev_fsData, (char *)curr_fsData, (numFS * sizeof(struct fs_Display_Data)) );
2195 /* initialize curr_fsData but retain the threshold flag information.
2196 The previous state of threshold flags is used in check_fs_thresholds()*/
2198 numBytes = NUM_FS_STAT_ENTRIES * CM_STAT_STRING_LEN;
2199 curr_fsDataP = curr_fsData;
2200 for(i=0; i<numFS; i++) {
2201 curr_fsDataP->probeOK = 0;
2202 curr_fsDataP->ovfCount = 0;
2203 memset((char *)curr_fsDataP->data, 0, numBytes);
2208 /* prev_fsData now contains all the information for the probe cycle
2209 that just completed. Now count the number of threshold overflows for
2210 use in the overview screen */
2212 prev_fsDataP = prev_fsData;
2214 numHosts_onfs_alerts = 0;
2215 for(i=0; i<numFS; i++) {
2216 if (! prev_fsDataP->probeOK ) { /* if probe failed */
2218 numHosts_onfs_alerts++;
2219 } if (prev_fsDataP->ovfCount) { /* overflows ?? */
2220 num_fs_alerts += prev_fsDataP->ovfCount;
2221 numHosts_onfs_alerts++;
2226 fprintf(debugFD,"Number of FS alerts = %d (on %d hosts)\n",
2227 num_fs_alerts, numHosts_onfs_alerts);
2229 /* flag that the data is now ready to be displayed */
2230 fs_Data_Available = 1;
2232 /* call the Overview frame update routine (update only FS info)*/
2233 ovw_refresh(ovw_currPage, OVW_UPDATE_FS);
2235 /* call the File Servers frame update routine */
2236 fs_refresh(fs_currPage, fs_curr_LCol);
2238 } /* display data */
2241 } /* save_FS_data_forDisplay */
2246 /*-----------------------------------------------------------------------
2247 * afsmon_FS_Handler()
2250 * This is the File Server probe Handler. It updates the afsmonitor
2251 * probe counts, fs circular buffer indices and calls the functions
2252 * to process the results of this probe.
2256 * Failure: Exits afsmonitor.
2257 *----------------------------------------------------------------------*/
2261 { /* afsmon_FS_Handler() */
2262 static char rn[] = "afsmon_FS_Handler"; /* routine name */
2263 int newProbeCycle; /* start of new probe cycle ? */
2264 int code; /* return status */
2268 fprintf(debugFD,"[ %s ] Called, hostName= %s, probeNum= %d, status=%s\n",
2270 xstat_fs_Results.connP->hostName,
2271 xstat_fs_Results.probeNum,
2272 xstat_fs_Results.probeOK? "FAILED":"OK");
2277 /* print the probe results to output file */
2278 if (afsmon_output) {
2279 code = afsmon_fsOutput(output_filename, afsmon_detOutput);
2281 fprintf(stderr,"[ %s ] output to file %s returned error code=%d\n",
2282 rn,output_filename,code);
2286 /* Update current probe number and circular buffer index. if current
2287 probenum changed make sure it is only by 1 */
2290 if (xstat_fs_Results.probeNum != afsmon_fs_curr_probeNum) {
2291 if (xstat_fs_Results.probeNum == afsmon_fs_curr_probeNum + 1) {
2292 afsmon_fs_curr_probeNum++;
2295 afsmon_fs_curr_CBindex=
2296 (afsmon_fs_curr_probeNum - 1) % num_bufSlots;
2299 fprintf(stderr,"[ %s ] probe number %d-1 missed\n",
2300 rn,xstat_fs_Results.probeNum);
2305 /* store the results of this probe in the FS circular buffer */
2307 save_FS_results_inCB(newProbeCycle);
2310 /* store the results of the current probe in the fs data display structure.
2311 if the current probe number changed, swap the current and previous display
2312 structures. note that the display screen is updated from these structures
2313 and should start showing the data of the just completed probe cycle */
2315 save_FS_data_forDisplay(&xstat_fs_Results);
2322 /*----------------------------------------------------------------------- *
2327 * Prints the Cache Manager circular buffer
2328 *----------------------------------------------------------------------*/
2332 { /* Print_CM_CB() */
2334 struct afsmon_cm_Results_list *cmlist;
2338 /* print valid info in the cm CB */
2341 fprintf(debugFD,"==================== CM Buffer ========================\n");
2342 fprintf(debugFD,"afsmon_cm_curr_CBindex = %d\n",afsmon_cm_curr_CBindex);
2343 fprintf(debugFD,"afsmon_cm_curr_probeNum = %d\n\n",afsmon_cm_curr_probeNum);
2345 for(i=0; i<num_bufSlots; i++) {
2346 fprintf(debugFD,"\t--------- slot %d ----------\n",i);
2347 cmlist = afsmon_cm_ResultsCB[i].list;
2349 while( j < numCM ) {
2350 if (! cmlist->empty) {
2351 fprintf(debugFD,"\t %d) probeNum = %d host = %s",
2352 j,cmlist->cmResults->probeNum,
2353 cmlist-> cmResults->connP->hostName);
2354 if (cmlist->cmResults->probeOK) fprintf(debugFD," NOTOK\n");
2355 else fprintf(debugFD," OK\n");
2357 fprintf(debugFD,"\t %d) -- empty --\n",j);
2358 cmlist = cmlist->next;
2361 if (cmlist != (struct afsmon_cm_Results_list *)0 )
2362 fprintf(debugFD,"dangling last next ptr cm CB\n");
2368 /*-----------------------------------------------------------------------
2369 * save_CM_results_inCB()
2372 * Saves the results of the latest CM probe in the cm circular
2373 * buffers. If the current probe cycle is in progress the contents
2374 * of xstat_cm_Results are copied to the end of the list of results
2375 * in the current slot (pointed to by afsmon_cm_curr_CBindex). If
2376 * a new probe cycle has started the next slot in the circular buffer
2377 * is initialized and the results copied. Note that the Rx related
2378 * information available in xstat_cm_Results is not copied.
2382 * Failure: Exits afsmonitor.
2383 *----------------------------------------------------------------------*/
2386 save_CM_results_inCB(a_newProbeCycle)
2387 int a_newProbeCycle; /* start of new probe cycle ? */
2389 { /* save_CM_results_inCB() */
2390 static char rn[] = "save_CM_results_inCB"; /* routine name */
2391 struct afsmon_cm_Results_list *tmp_cmlist_item; /* temp cm list item */
2392 struct xstat_cm_ProbeResults *tmp_cmPR; /* temp ptr */
2397 fprintf(debugFD,"[ %s ] Called, a_newProbeCycle= %d\n",rn, a_newProbeCycle);
2401 /* If a new probe cycle started, mark the list in the current buffer
2402 slot empty for resuse. Note that afsmon_cm_curr_CBindex was appropriately
2403 incremented in afsmon_CM_Handler() */
2405 if (a_newProbeCycle) {
2406 tmp_cmlist_item = afsmon_cm_ResultsCB[afsmon_cm_curr_CBindex].list;
2407 for(i=0; i<numCM; i++) {
2408 tmp_cmlist_item->empty = 1;
2409 tmp_cmlist_item = tmp_cmlist_item->next;
2413 /* locate last unused item in list */
2414 tmp_cmlist_item = afsmon_cm_ResultsCB[afsmon_cm_curr_CBindex].list;
2415 for(i=0; i<numCM; i++) {
2416 if (tmp_cmlist_item->empty) break;
2417 tmp_cmlist_item = tmp_cmlist_item->next;
2420 /* if we could not find one we have an inconsistent list */
2421 if ( ! tmp_cmlist_item->empty ) {
2422 fprintf(stderr,"[ %s ] list inconsistency 1. unable to find an empty slot to store results of probenum %d of %s\n",rn,
2423 xstat_cm_Results.probeNum,xstat_cm_Results.connP->hostName);
2427 tmp_cmPR = tmp_cmlist_item->cmResults;
2429 /* copy hostname and probe number and probe time and probe status.
2430 if the probe failed return now */
2432 memcpy(tmp_cmPR->connP->hostName, xstat_cm_Results.connP->hostName, sizeof(xstat_cm_Results.connP->hostName));
2433 tmp_cmPR->probeNum = xstat_cm_Results.probeNum;
2434 tmp_cmPR->probeTime = xstat_cm_Results.probeTime;
2435 tmp_cmPR->probeOK = xstat_cm_Results.probeOK;
2436 if (xstat_cm_Results.probeOK) { /* probeOK = 1 => notOK */
2437 /* we have a nonempty results structure so mark the list item used */
2438 tmp_cmlist_item->empty = 0;
2443 /* copy connection information */
2444 memcpy(&(tmp_cmPR->connP->skt), &(xstat_cm_Results.connP->skt), sizeof(struct sockaddr_in));
2446 /**** NEED TO COPY rx_connection INFORMATION HERE ******/
2448 memcpy(tmp_cmPR->connP->hostName, xstat_cm_Results.connP->hostName, sizeof(xstat_cm_Results.connP->hostName));
2449 tmp_cmPR->collectionNumber = xstat_cm_Results.collectionNumber;
2451 /* copy the probe data information */
2452 tmp_cmPR->data.AFSCB_CollData_len = xstat_cm_Results.data.AFSCB_CollData_len;
2453 memcpy(tmp_cmPR->data.AFSCB_CollData_val, xstat_cm_Results.data.AFSCB_CollData_val, xstat_cm_Results.data.AFSCB_CollData_len * sizeof(afs_int32));
2456 /* we have a valid results structure so mark the list item used */
2457 tmp_cmlist_item->empty = 0;
2459 /* print the stored info - to make sure we copied it right */
2460 /* Print_cm_FullPerfInfo(tmp_cmPR); */
2461 /* Print the cm circular buffer */
2464 } /* save_CM_results_inCB */
2468 /*-----------------------------------------------------------------------
2472 * The results of xstat probes are stored in a string format in
2473 * the arrays curr_cmData and prev_cmData. The information stored in
2474 * prev_cmData is copied to the screen.
2475 * This function converts xstat FS results from longs to strings and
2476 * places them in the given buffer (a pointer to an item in curr_cmData).
2477 * When a probe cycle completes, curr_cmData is copied to prev_cmData
2478 * in afsmon_CM_Handler().
2482 *----------------------------------------------------------------------*/
2485 cm_Results_ltoa(a_cmData,a_cmResults)
2486 struct cm_Display_Data *a_cmData; /* target buffer */
2487 struct xstat_cm_ProbeResults *a_cmResults; /* ptr to xstat cm Results */
2488 { /* cm_Results_ltoa */
2490 static char rn[] = "cm_Results_ltoa"; /* routine name */
2491 struct afs_stats_CMFullPerf *fullP; /* ptr to complete CM stats */
2499 fprintf(debugFD,"[ %s ] Called, a_cmData= %d, a_cmResults= %d\n",
2500 rn, a_cmData, a_cmResults);
2505 fullP = (struct afs_stats_CMFullPerf *)
2506 (xstat_cm_Results.data.AFSCB_CollData_val);
2508 /* There are 4 parts to CM statistics
2509 - Overall performance statistics (including up/down statistics)
2510 - This CMs FS RPC operations info
2511 - This CMs FS RPC errors info
2512 - This CMs FS transfers info
2513 - Authentication info
2514 - [Un]Replicated access info
2517 /* copy overall performance statistics */
2518 srcbuf = (afs_int32 *) &(fullP->perf);
2520 /* we skip the 19 entry, ProtServAddr, so the index must account for this */
2521 for(i=0 ; i<NUM_AFS_STATS_CMPERF_LONGS+1; i++) {
2524 continue; /* skip ProtServerAddr */
2526 sprintf(a_cmData->data[idx], "%d", *srcbuf);
2531 /*printf("Ending index value = %d\n",idx-1);*/
2533 /* server up/down statistics */
2534 /* copy file server up/down stats */
2535 srcbuf = (afs_int32 *) (fullP->perf.fs_UpDown);
2536 numLongs = 2 * (sizeof(struct afs_stats_SrvUpDownInfo) / sizeof(afs_int32));
2537 for(i=0 ; i<numLongs; i++) {
2538 sprintf(a_cmData->data[idx], "%d", *srcbuf);
2543 /*printf("Ending index value = %d\n",idx-1);*/
2545 /* copy volume location server up/down stats */
2546 srcbuf = (afs_int32 *) (fullP->perf.vl_UpDown);
2547 numLongs = 2 * (sizeof(struct afs_stats_SrvUpDownInfo) / sizeof(afs_int32));
2548 for(i=0 ; i<numLongs; i++) {
2549 sprintf(a_cmData->data[idx], "%d", *srcbuf);
2554 /*printf("Ending index value = %d\n",idx-1);*/
2556 /* copy CMs individual FS RPC operations info */
2557 srcbuf = (afs_int32 *) (fullP->rpc.fsRPCTimes);
2558 for(i=0; i<AFS_STATS_NUM_FS_RPC_OPS; i++) {
2559 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* numOps*/
2561 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* numSuccesses */
2563 tmpbuf = srcbuf++; /* sum time */
2564 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2566 tmpbuf = srcbuf++; /* sqr time */
2567 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2569 tmpbuf = srcbuf++; /* min time */
2570 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2572 tmpbuf = srcbuf++; /* max time */
2573 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2577 /*printf("Ending index value = %d\n",idx-1);*/
2579 /* copy CMs individual FS RPC errors info */
2581 srcbuf = (afs_int32 *) (fullP->rpc.fsRPCErrors);
2582 for(i=0; i<AFS_STATS_NUM_FS_RPC_OPS; i++) {
2583 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* server */
2585 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* network */
2587 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* prot */
2589 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* vol */
2591 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* busies */
2593 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* other */
2597 /*printf("Ending index value = %d\n",idx-1);*/
2599 /* copy CMs individual RPC transfers info */
2601 srcbuf = (afs_int32 *) (fullP->rpc.fsXferTimes);
2602 for(i=0; i<AFS_STATS_NUM_FS_XFER_OPS; i++) {
2603 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* numOps*/
2605 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* numSuccesses */
2607 tmpbuf = srcbuf++; /* sum time */
2608 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2610 tmpbuf = srcbuf++; /* sqr time */
2611 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2613 tmpbuf = srcbuf++; /* min time */
2614 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2616 tmpbuf = srcbuf++; /* max time */
2617 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2619 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* sum bytes */
2621 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* min bytes */
2623 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* max bytes */
2625 for(j=0; j<AFS_STATS_NUM_XFER_BUCKETS; j++) {
2626 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* bucket[j] */
2631 /*printf("Ending index value = %d\n",idx-1);*/
2633 /* copy CM operations timings */
2635 srcbuf = (afs_int32 *) (fullP->rpc.cmRPCTimes);
2636 for(i=0; i<AFS_STATS_NUM_CM_RPC_OPS; i++) {
2637 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* numOps*/
2639 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* numSuccesses */
2641 tmpbuf = srcbuf++; /* sum time */
2642 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2644 tmpbuf = srcbuf++; /* sqr time */
2645 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2647 tmpbuf = srcbuf++; /* min time */
2648 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2650 tmpbuf = srcbuf++; /* max time */
2651 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2655 /*printf("Ending index value = %d\n",idx-1);*/
2657 /* copy authentication info */
2659 srcbuf = (afs_int32 *) &(fullP->authent);
2660 numLongs = sizeof(struct afs_stats_AuthentInfo) / sizeof(afs_int32);
2661 for(i=0; i<numLongs; i++) {
2662 sprintf(a_cmData->data[idx], "%d", *srcbuf);
2666 /*printf("Ending index value = %d\n",idx-1);*/
2668 /* copy CM [un]replicated access info */
2670 srcbuf = (afs_int32 *) &(fullP->accessinf);
2671 numLongs = sizeof(struct afs_stats_AccessInfo) / sizeof(afs_int32);
2672 for(i=0; i<numLongs; i++) {
2673 sprintf(a_cmData->data[idx], "%d", *srcbuf);
2677 /*printf("Ending index value = %d\n",idx-1);*/
2680 } /* cm_Results_ltoa */
2683 /*-----------------------------------------------------------------------
2684 * Function: check_cm_thresholds()
2687 * Checks the thresholds and sets the overflow flag. Recall that the
2688 * thresholds for each host are stored in the hostEntry lists
2689 * [fs/cm]nameList arrays. The probe results are passed to this
2690 * function in the display-ready format - ie., as strings. Though
2691 * this looks stupid the overhead incurred in converting the strings
2692 * back to floats and comparing them is insignificant and
2693 * programming is easier this way.
2694 * The threshold flags are a part of the display structures
2699 *----------------------------------------------------------------------*/
2702 check_cm_thresholds(a_hostEntry, a_Data)
2703 struct afsmon_hostEntry *a_hostEntry; /* ptr to hostEntry */
2704 struct cm_Display_Data *a_Data; /* ptr to cm data to be displayed */
2706 { /* check_cm_thresholds */
2708 static char rn[] = "check_cm_thresholds";
2709 struct Threshold *threshP;
2710 double tValue; /* threshold value */
2711 double pValue; /* probe value */
2714 int count; /* number of thresholds exceeded */
2717 fprintf(debugFD,"[ %s ] Called, a_hostEntry= %d, a_Data= %d\n",
2718 rn, a_hostEntry, a_Data);
2722 if (a_hostEntry->numThresh == 0) {
2723 /* store in ovf count ?? */
2728 threshP = a_hostEntry->thresh;
2729 for(i=0; i < a_hostEntry->numThresh; i++) {
2730 if (threshP->itemName[0] == '\0') {
2731 threshP++; continue;
2733 idx = threshP->index; /* positional index to the data array */
2734 tValue = atof(threshP->threshVal); /* threshold value */
2735 pValue = atof(a_Data->data[idx]); /* probe value */
2736 if (pValue > tValue) {
2739 fprintf(debugFD,"[ %s ] cm = %s, thresh ovf for %s, threshold= %s, probevalue= %s\n",
2740 rn, a_hostEntry->hostName, threshP->itemName, threshP->threshVal , a_Data->data[idx]);
2744 /* if the threshold is crossed, call the handler function
2745 only if this was a transition -ie, if the threshold was
2746 crossed in the last probe too just count & keep quite! */
2748 if (! a_Data->threshOvf[idx]) {
2749 a_Data->threshOvf[idx] = 1;
2750 /* call the threshold handler if provided */
2751 if (threshP->handler[0] != '\0') {
2753 fprintf(debugFD,"[ %s ] Calling ovf handler %s\n",
2754 rn, threshP->handler);
2757 execute_thresh_handler(threshP->handler,
2758 a_Data->hostName, CM, threshP->itemName,
2759 threshP->threshVal, a_Data->data[idx]);
2765 /* in case threshold was previously crossed, blank it out */
2766 a_Data->threshOvf[idx] = 0;
2769 /* store the overflow count */
2770 a_Data->ovfCount = count;
2773 } /* check_cm_thresholds */
2776 /*-----------------------------------------------------------------------
2777 * save_CM_data_forDisplay()
2780 * Does the following:
2781 * - if the probe number changed (ie, a cycle completed) curr_cmData
2782 * is copied to prev_cmData, curr_cmData zeroed and refresh the
2783 * overview screen and file server screen with the new data.
2784 * - store the results of the current probe from xstat_cm_Results into
2785 * curr_cmData. ie., convert longs to strings.
2786 * - check the thresholds
2790 * Failure: Exits afsmonitor.
2792 *----------------------------------------------------------------------*/
2795 save_CM_data_forDisplay(a_cmResults)
2796 struct xstat_cm_ProbeResults *a_cmResults;
2797 { /* save_CM_data_forDisplay */
2799 static char rn[] = "save_CM_data_forDisplay"; /* routine name */
2800 struct cm_Display_Data *curr_cmDataP;
2801 struct cm_Display_Data *prev_cmDataP;
2802 struct afsmon_hostEntry *curr_host;
2803 static int probes_Received = 0; /* number of probes reveived in
2804 the current cycle. If this is equal to numFS we got all
2805 the data we want in this cycle and can now display it */
2813 fprintf(debugFD,"[ %s ] Called, a_cmResults= %d\n",rn, a_cmResults);
2817 /* store results in the display array */
2820 curr_cmDataP = curr_cmData;
2821 for (i=0; i<numCM; i++) {
2822 if((strcasecmp(curr_cmDataP->hostName,a_cmResults->connP->hostName)) == 0) {
2830 fprintf(stderr,"[ %s ] Could not insert CM probe results for host %s in cm display array\n",rn, a_cmResults->connP->hostName);
2834 /* Check the status of the probe. If it succeeded, we store its
2835 results in the display data structure. If it failed we only mark
2836 the failed status in the display data structure. */
2839 if (a_cmResults->probeOK) { /* 1 => notOK the xstat results */
2840 curr_cmDataP->probeOK = 0;
2842 /* print the probe status */
2844 fprintf(debugFD,"\n\t\t ----- cm display data ------\n");
2845 fprintf(debugFD,"HostName = %s PROBE FAILED \n",curr_cmDataP->hostName);
2849 } else { /* probe succeeded, update display data structures */
2850 curr_cmDataP->probeOK = 1;
2853 /* covert longs to strings and place them in curr_cmDataP */
2854 cm_Results_ltoa(curr_cmDataP, a_cmResults);
2856 /* compare with thresholds and set the overflow flags.
2857 note that the threshold information is in the hostEntry structure and
2858 each threshold item has a positional index associated with it */
2860 /* locate the hostEntry for this host */
2862 curr_host = CMnameList;
2863 for(i=0; i<numCM; i++) {
2864 if (strcasecmp(curr_host->hostName,a_cmResults->connP->hostName) == 0) {
2868 curr_host = curr_host->next;
2870 if (!done) afsmon_Exit(100);
2872 code = check_cm_thresholds(curr_host, curr_cmDataP);
2874 fprintf(stderr,"[ %s ] Error in checking thresholds\n",rn);
2879 /* print the info we just saved */
2881 fprintf(debugFD,"\n\t\t ----- CM display data ------\n");
2882 fprintf(debugFD,"HostName = %s\n",curr_cmDataP->hostName);
2883 for(i=0; i<NUM_CM_STAT_ENTRIES; i++) {
2885 case 0: fprintf(debugFD,"\t -- Overall Perf Info --\n");
2887 case 39: fprintf(debugFD,"\t -- File Server up/down stats - same cell --\n");
2889 case 64: fprintf(debugFD,"\t -- File Server up/down stats - diff cell --\n");
2891 case 89: fprintf(debugFD,"\t -- VL server up/down stats - same cell --\n");
2893 case 114: fprintf(debugFD,"\t -- VL server up/down stats - diff cell --\n");
2895 case 139: fprintf(debugFD,"\t -- FS Operation Timings --\n");
2897 case 279: fprintf(debugFD,"\t -- FS Error Info --\n");
2899 case 447: fprintf(debugFD,"\t -- FS Transfer Timings --\n");
2901 case 475: fprintf(debugFD,"\t -- CM Operations Timings --\n");
2903 case 510: fprintf(debugFD,"\t -- Authentication Info --\n");
2905 case 522: fprintf(debugFD,"\t -- Access Info --\n");
2910 fprintf(debugFD,"%20s %30s %s\n", curr_cmDataP->data[i],
2911 cm_varNames[i],curr_cmDataP->threshOvf[i] ? "(ovf)":"" );
2913 fprintf(debugFD,"\t\t--------------------------------\n\n");
2916 } /* if the probe succeeded, update the display data structures */
2918 /* if we have received a reply from all the hosts for this probe cycle,
2919 it is time to display the data */
2922 if (probes_Received == numCM) {
2923 probes_Received = 0;
2925 if (afsmon_cm_curr_probeNum != afsmon_cm_prev_probeNum + 1) {
2926 sprintf(errMsg,"[ %s ] Probe number %d missed! \n",
2927 rn, afsmon_cm_prev_probeNum +1);
2930 afsmon_cm_prev_probeNum++;
2933 /* backup the display data of the probe cycle that just completed -
2934 ie., store curr_cmData in prev_cmData */
2936 memcpy((char *)prev_cmData, (char *)curr_cmData, (numCM * sizeof(struct cm_Display_Data)) );
2939 /* initialize curr_cmData but retain the threshold flag information.
2940 The previous state of threshold flags is used in check_cm_thresholds()*/
2942 curr_cmDataP = curr_cmData;
2943 numBytes = NUM_CM_STAT_ENTRIES * CM_STAT_STRING_LEN;
2944 for(i=0; i<numCM; i++) {
2945 curr_cmDataP->probeOK = 0;
2946 curr_cmDataP->ovfCount = 0;
2947 memset((char *)curr_cmDataP->data, 0, numBytes);
2951 /* prev_cmData now contains all the information for the probe cycle
2952 that just completed. Now count the number of threshold overflows for
2953 use in the overview screen */
2955 prev_cmDataP = prev_cmData;
2957 numHosts_oncm_alerts = 0;
2958 for(i=0; i<numCM; i++) {
2959 if (! prev_cmDataP->probeOK) { /* if probe failed */
2961 numHosts_oncm_alerts++;
2962 } else if (prev_cmDataP->ovfCount) { /* overflows ?? */
2963 num_cm_alerts += prev_cmDataP->ovfCount;
2964 numHosts_oncm_alerts++;
2969 fprintf(debugFD,"Number of CM alerts = %d (on %d hosts)\n",
2970 num_cm_alerts, numHosts_oncm_alerts);
2973 /* flag that the data is now ready to be displayed */
2974 cm_Data_Available = 1;
2976 /* update the Overview frame (only CM info)*/
2977 ovw_refresh(ovw_currPage, OVW_UPDATE_CM);
2979 /* update the Cache Managers frame */
2980 cm_refresh(cm_currPage, cm_curr_LCol);
2986 } /* save_CM_data_forDisplay */
2990 /*-----------------------------------------------------------------------
2991 * afsmon_CM_Handler()
2994 * This is the Cache Manager probe Handler. It updates the afsmonitor
2995 * probe counts, cm circular buffer indices and calls the functions
2996 * to process the results of this probe.
3000 * Failure: Exits afsmonitor.
3001 *----------------------------------------------------------------------*/
3005 { /* afsmon_CM_Handler() */
3006 static char rn[] = "afsmon_CM_Handler"; /* routine name */
3007 int code; /* return status */
3008 int newProbeCycle; /* start of new probe cycle ? */
3012 "[ %s ] Called, hostName= %s, probeNum= %d, status= %s\n", rn,
3013 xstat_cm_Results.connP->hostName,
3014 xstat_cm_Results.probeNum,
3015 xstat_cm_Results.probeOK? "FAILED":"OK");
3020 /* print the probe results to output file */
3021 if (afsmon_output) {
3022 code = afsmon_cmOutput(output_filename, afsmon_detOutput);
3024 fprintf(stderr,"[ %s ] output to file %s returned error code=%d\n",
3025 rn,output_filename,code);
3029 /* Update current probe number and circular buffer index. if current
3030 probenum changed make sure it is only by 1 */
3033 if (xstat_cm_Results.probeNum != afsmon_cm_curr_probeNum) {
3034 if (xstat_cm_Results.probeNum == afsmon_cm_curr_probeNum + 1) {
3035 afsmon_cm_curr_probeNum++;
3038 afsmon_cm_curr_CBindex=
3039 (afsmon_cm_curr_probeNum - 1) % num_bufSlots;
3042 fprintf(stderr,"[ %s ] probe number %d-1 missed\n",
3043 rn,xstat_cm_Results.probeNum);
3048 /* save the results of this probe in the CM buffer */
3050 save_CM_results_inCB(newProbeCycle);
3052 /* store the results of the current probe in the cm data display structure.
3053 if the current probe number changed, swap the current and previous display
3054 structures. note that the display screen is updated from these structures
3055 and should start showing the data of the just completed probe cycle */
3057 save_CM_data_forDisplay(&xstat_cm_Results);
3062 /*-----------------------------------------------------------------------
3066 * Allocate and Initialize circular buffers for file servers.
3070 * Failure to allocate memory: exits afsmonitor.
3071 *----------------------------------------------------------------------*/
3075 { /* init_fs_buffers() */
3076 static char rn[] = "init_fs_buffers"; /* routine name */
3077 struct afsmon_fs_Results_list *new_fslist_item; /* ptr for new struct */
3078 struct afsmon_fs_Results_list *tmp_fslist_item; /* temp ptr */
3079 struct xstat_fs_ProbeResults *new_fsPR; /* ptr for new struct */
3086 fprintf(debugFD,"[ %s ] Called\n",rn);
3090 /* allocate memory for the circular buffer of pointers */
3092 afsmon_fs_ResultsCB = (struct afsmon_fs_Results_CBuffer *) malloc(
3093 sizeof(struct afsmon_fs_Results_CBuffer) * num_bufSlots);
3095 /* initialize the fs circular buffer */
3096 for (i=0; i<num_bufSlots; i++) {
3097 afsmon_fs_ResultsCB[i].list = (struct afsmon_fs_Results_list *)0;
3098 afsmon_fs_ResultsCB[i].probeNum = 0;
3101 /* create a list of numFS items to store fs probe results for
3104 if (numFS) { /* if we have file servers to monitor */
3105 for(bufslot=0; bufslot<num_bufSlots; bufslot++) {
3106 numfs = numFS; /* get the number of servers */
3109 /* if any of these mallocs fail we only need to free the memory we
3110 have allocated in this iteration. the rest of it which is in a
3111 proper linked list will be freed in afsmon_Exit */
3113 /* allocate memory for an fs list item */
3114 new_fslist_item = (struct afsmon_fs_Results_list *) malloc (
3115 sizeof(struct afsmon_fs_Results_list));
3116 if (new_fslist_item == (struct afsmon_fs_Results_list *)0)
3119 /* allocate memory to store xstat_fs_Results */
3120 new_fsPR = (struct xstat_fs_ProbeResults *) malloc(
3121 sizeof(struct xstat_fs_ProbeResults));
3122 if (new_fsPR == (struct xstat_fs_ProbeResults *)0) {
3123 free(new_fslist_item);
3126 new_fsPR->connP = (struct xstat_fs_ConnectionInfo *) malloc(
3127 sizeof(struct xstat_fs_ConnectionInfo));
3128 if (new_fsPR->connP == (struct xstat_fs_ConnectionInfo *)0 ) {
3129 free(new_fslist_item);
3134 /* >>> need to allocate rx connection info structure here <<< */
3136 new_fsPR->data.AFS_CollData_val = (afs_int32 *) malloc(
3137 XSTAT_FS_FULLPERF_RESULTS_LEN * sizeof(afs_int32));
3138 if (new_fsPR->data.AFS_CollData_val == NULL) {
3139 free(new_fslist_item);
3140 free(new_fsPR->connP);
3145 /* initialize this list entry */
3146 new_fslist_item->fsResults = new_fsPR;
3147 new_fslist_item->empty = 1;
3148 new_fslist_item->next = (struct afsmon_fs_Results_list *)0;
3150 /* store it at the end of the fs list in the current CB slot */
3151 if (afsmon_fs_ResultsCB[bufslot].list == (struct afsmon_fs_Results_list *)0)
3152 afsmon_fs_ResultsCB[ bufslot ].list = new_fslist_item;
3154 tmp_fslist_item = afsmon_fs_ResultsCB[ bufslot ].list;
3156 while(tmp_fslist_item != (struct afsmon_fs_Results_list *)0)
3158 if (tmp_fslist_item->next == (struct afsmon_fs_Results_list *)0)
3160 tmp_fslist_item = tmp_fslist_item->next;
3163 /* something goofed. exit */
3164 fprintf(stderr,"[ %s ] list creation error\n",rn);
3168 tmp_fslist_item->next = new_fslist_item;
3171 } /* while servers */
3172 } /* for each buffer slot */
3173 } /* if we have file servers to monitor */
3177 /*-----------------------------------------------------------------------
3181 * Allocate and Initialize circular buffers for cache managers.
3185 * Failure to allocate memory: exits afsmonitor.
3186 *----------------------------------------------------------------------*/
3190 { /* init_cm_buffers() */
3191 static char rn[] = "init_cm_buffers"; /* routine name */
3192 struct afsmon_cm_Results_list *new_cmlist_item; /* ptr for new struct */
3193 struct afsmon_cm_Results_list *tmp_cmlist_item; /* temp ptr */
3194 struct xstat_cm_ProbeResults *new_cmPR; /* ptr for new struct */
3200 fprintf(debugFD,"[ %s ] Called\n",rn);
3204 /* allocate memory for the circular buffer of pointers */
3205 afsmon_cm_ResultsCB = (struct afsmon_cm_Results_CBuffer *) malloc(
3206 sizeof(struct afsmon_cm_Results_CBuffer) * num_bufSlots);
3208 /* initialize the fs circular buffer */
3209 for (i=0; i<num_bufSlots; i++) {
3210 afsmon_cm_ResultsCB[i].list = (struct afsmon_cm_Results_list *)0;
3211 afsmon_cm_ResultsCB[i].probeNum = 0;
3214 /* create a list of numCM items to store fs probe results for
3217 if (numCM) { /* if we have file servers to monitor */
3218 for(bufslot=0; bufslot<num_bufSlots; bufslot++) {
3219 numcm = numCM; /* get the number of servers */
3222 /* if any of these mallocs fail we only need to free the memory we
3223 have allocated in this iteration. the rest of it which is in a
3224 proper linked list will be freed in afsmon_Exit */
3226 /* allocate memory for an fs list item */
3227 new_cmlist_item = (struct afsmon_cm_Results_list *) malloc (
3228 sizeof(struct afsmon_cm_Results_list));
3229 if (new_cmlist_item == (struct afsmon_cm_Results_list *)0)
3232 /* allocate memory to store xstat_cm_Results */
3233 new_cmPR = (struct xstat_cm_ProbeResults *) malloc(
3234 sizeof(struct xstat_cm_ProbeResults));
3235 if (new_cmPR == (struct xstat_cm_ProbeResults *)0) {
3236 free(new_cmlist_item);
3239 new_cmPR->connP = (struct xstat_cm_ConnectionInfo *) malloc(
3240 sizeof(struct xstat_cm_ConnectionInfo));
3241 if (new_cmPR->connP == (struct xstat_cm_ConnectionInfo *)0 ) {
3242 free(new_cmlist_item);
3247 /* >>> need to allocate rx connection info structure here <<< */
3249 new_cmPR->data.AFSCB_CollData_val = (afs_int32 *) malloc(
3250 XSTAT_CM_FULLPERF_RESULTS_LEN * sizeof(afs_int32));
3251 if (new_cmPR->data.AFSCB_CollData_val == NULL) {
3252 free(new_cmlist_item);
3253 free(new_cmPR->connP);
3258 /* initialize this list entry */
3259 new_cmlist_item->cmResults = new_cmPR;
3260 new_cmlist_item->empty = 1;
3261 new_cmlist_item->next = (struct afsmon_cm_Results_list *)0;
3263 /* store it at the end of the cm list in the current CB slot */
3264 if (afsmon_cm_ResultsCB[bufslot].list == (struct afsmon_cm_Results_list *)0)
3265 afsmon_cm_ResultsCB[ bufslot ].list = new_cmlist_item;
3267 tmp_cmlist_item = afsmon_cm_ResultsCB[ bufslot ].list;
3269 while(tmp_cmlist_item != (struct afsmon_cm_Results_list *)0)
3271 if (tmp_cmlist_item->next == (struct afsmon_cm_Results_list *)0)
3273 tmp_cmlist_item = tmp_cmlist_item->next;
3276 /* something goofed. exit */
3277 fprintf(stderr,"[ %s ] list creation error\n",rn);
3281 tmp_cmlist_item->next = new_cmlist_item;
3284 } /* while servers */
3285 } /* for each buffer slot */
3286 } /* if we have file servers to monitor */
3287 /* print the CB to make sure it is right */
3291 } /* init_cm_buffers() */
3294 /*-------------------------------------------------------------------------
3295 * init_print_buffers()
3298 * Allocate and initialize the buffers used for printing results
3299 * to the display screen. These buffers store the current and
3300 * previous probe results in ascii format.
3305 *------------------------------------------------------------------------*/
3308 init_print_buffers()
3309 { /* init_print_buffers */
3311 static char rn[] = "init_print_buffers"; /* routine name */
3312 struct fs_Display_Data *tmp_fsData1; /* temp pointers */
3313 struct fs_Display_Data *tmp_fsData2;
3314 struct cm_Display_Data *tmp_cmData1;
3315 struct cm_Display_Data *tmp_cmData2;
3316 struct afsmon_hostEntry *tmp_fsNames;
3317 struct afsmon_hostEntry *tmp_cmNames;
3322 fprintf(debugFD,"[ %s ] Called\n",rn);
3326 /* allocate numFS blocks of the FS print structure. */
3328 /* we need two instances of this structure - one (curr_fsData) for storing
3329 the results of the fs probes currently in progress and another (prev_fsData)
3330 for the last completed probe. The display is updated from the contents of
3331 prev_fsData. The pointers curr_fsData & prev_fsData are switched whenever
3332 the probe number changes */
3335 numBytes = numFS * sizeof(struct fs_Display_Data);
3336 curr_fsData = (struct fs_Display_Data *) malloc(numBytes);
3337 if (curr_fsData == (struct fs_Display_Data *)0) {
3338 fprintf(stderr,"[ %s ] Memory allocation failure\n",rn);
3341 memset(curr_fsData, 0, numBytes);
3343 numBytes = numFS * sizeof(struct fs_Display_Data);
3344 prev_fsData = (struct fs_Display_Data *) malloc(numBytes);
3345 if (prev_fsData == (struct fs_Display_Data *)0) {
3346 fprintf(stderr,"[ %s ] Memory allocation failure\n",rn);
3349 memset(prev_fsData, 0, numBytes);
3351 /* fill in the host names */
3352 tmp_fsData1 = curr_fsData;
3353 tmp_fsData2 = curr_fsData;
3354 tmp_fsNames = FSnameList;
3355 for(i=0; i<numFS; i++) {
3356 strncpy(tmp_fsData1->hostName, tmp_fsNames->hostName, HOST_NAME_LEN);
3357 strncpy(tmp_fsData2->hostName, tmp_fsNames->hostName, HOST_NAME_LEN);
3360 tmp_fsNames = tmp_fsNames->next;;
3363 } /* if file servers to monitor */
3365 /* allocate numCM blocks of the CM print structure */
3366 /* we need two instances of this structure for the same reasons as above*/
3369 numBytes = numCM * sizeof(struct cm_Display_Data);
3371 curr_cmData = (struct cm_Display_Data *) malloc(numBytes);
3372 if (curr_cmData == (struct cm_Display_Data *)0) {
3373 fprintf(stderr,"[ %s ] Memory allocation failure\n",rn);
3376 memset(curr_cmData, 0, numBytes);
3378 numBytes = numCM * sizeof(struct cm_Display_Data);
3379 prev_cmData = (struct cm_Display_Data *) malloc(numBytes);
3380 if (prev_cmData == (struct cm_Display_Data *)0) {
3381 fprintf(stderr,"[ %s ] Memory allocation failure\n",rn);
3384 memset(prev_cmData, 0, numBytes);
3386 /* fill in the host names */
3387 tmp_cmData1 = curr_cmData;
3388 tmp_cmData2 = curr_cmData;
3389 tmp_cmNames = CMnameList;
3390 for(i=0; i<numCM; i++) {
3391 strncpy(tmp_cmData1->hostName, tmp_cmNames->hostName, HOST_NAME_LEN);
3392 strncpy(tmp_cmData2->hostName, tmp_cmNames->hostName, HOST_NAME_LEN);
3395 tmp_cmNames = tmp_cmNames->next;;
3398 } /* if cache managers to monitor */
3402 } /* init_print_buffers */
3404 /*-----------------------------------------------------------------------
3408 * Trap the interrupt signal. This function is useful only until
3409 * gtx is initialized.
3410 *----------------------------------------------------------------------*/
3416 static char *rn = "quit_signal"; /* routine name */
3418 fprintf(stderr,"Received signal %d \n",sig);
3424 /*-----------------------------------------------------------------------
3428 * This is where we start it all. Initialize an array of sockets for
3429 * file servers and cache cache managers and call the xstat_[fs/cm]_Init
3430 * routines. The last step is to call the gtx input server which
3431 * grabs control of the keyboard.
3434 * Does not return. Control is periodically returned to the afsmonitor
3435 * thru afsmon_[FS/CM]_Handler() routines and also through the gtx
3436 * keyboard handler calls.
3438 *----------------------------------------------------------------------*/
3442 { /* afsmon_execute() */
3443 static char rn[] = "afsmon_execute"; /* routine name */
3444 static char fullhostname[128]; /* full host name */
3445 struct sockaddr_in *FSSktArray; /* fs socket array */
3446 int FSsktbytes; /* num bytes in above */
3447 struct sockaddr_in *CMSktArray; /* cm socket array */
3448 int CMsktbytes; /* num bytes in above */
3449 struct sockaddr_in *curr_skt; /* ptr to current socket*/
3450 struct afsmon_hostEntry *curr_FS; /* ptr to FS name list */
3451 struct afsmon_hostEntry *curr_CM; /* ptr to CM name list */
3452 struct hostent *he; /* host entry */
3453 afs_int32 *collIDP; /* ptr to collection ID */
3454 int numCollIDs; /* number of collection IDs */
3455 int FSinitFlags = 0; /* flags for xstat_fs_Init */
3456 int CMinitFlags = 0; /* flags for xstat_cm_Init */
3457 int code; /* function return code */
3458 struct timeval tv; /* time structure */
3461 fprintf(debugFD,"[ %s ] Called\n",rn);
3466 /* process file server entries */
3468 /* Allocate an array of sockets for each fileserver we monitor */
3470 FSsktbytes = numFS * sizeof(struct sockaddr_in);
3471 FSSktArray = (struct sockaddr_in *) malloc(FSsktbytes);
3472 if (FSSktArray == (struct sockaddr_in *)0) {
3473 fprintf(stderr,"[ %s ] cannot malloc %d sockaddr_ins for fileservers\n",
3478 memset(FSSktArray, 0, FSsktbytes);
3480 /* Fill in the socket information for each fileserve */
3482 curr_skt = FSSktArray;
3483 curr_FS = FSnameList; /* FS name list header */
3485 strncpy(fullhostname,curr_FS->hostName,sizeof(fullhostname));
3486 he = GetHostByName(fullhostname);
3488 fprintf(stderr,"[ %s ] Cannot get host info for %s\n",rn, fullhostname);
3491 strncpy(curr_FS->hostName,he->h_name,HOST_NAME_LEN); /* complete name*/
3492 memcpy(&(curr_skt->sin_addr.s_addr), he->h_addr, 4);
3493 curr_skt->sin_family = htons(AF_INET); /*Internet family*/
3494 curr_skt->sin_port = htons(7000); /*FileServer port*/
3495 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
3496 curr_skt->sin_len = sizeof(struct sockaddr_in);
3499 /* get the next dude */
3501 curr_FS = curr_FS->next;
3504 /* initialize collection IDs. We need only one entry since we collect
3505 all the information from xstat */
3508 collIDP = (afs_int32 *) malloc (sizeof (afs_int32));
3509 if (collIDP == NULL) {
3510 fprintf(stderr,"[ %s ] failed to allocate a measely afs_int32 word.Argh!\n", rn);
3513 *collIDP = 2; /* USE A macro for this */
3516 if (afsmon_onceOnly) /* option not provided at this time */
3517 FSinitFlags |= XSTAT_FS_INITFLAG_ONE_SHOT;
3520 fprintf(debugFD,"[ %s ] Calling xstat_fs_Init \n",rn);
3524 code = xstat_fs_Init(numFS, /*Num servers*/
3525 FSSktArray, /*File Server socket array*/
3526 afsmon_probefreq, /*probe frequency*/
3527 afsmon_FS_Handler, /*Handler routine*/
3528 FSinitFlags, /*Initialization flags*/
3529 numCollIDs, /*Number of collection IDs*/
3530 collIDP); /*Ptr to collection ID */
3533 fprintf(stderr,"[ %s ] xstat_fs_init returned error\n",rn);
3537 } /* end of process fileserver entries */
3539 /* process cache manager entries */
3542 /* Allocate an array of sockets for each cache manager we monitor */
3544 CMsktbytes = numCM * sizeof(struct sockaddr_in);
3545 CMSktArray = (struct sockaddr_in *) malloc(CMsktbytes);
3546 if (CMSktArray == (struct sockaddr_in *)0) {
3547 fprintf(stderr,"[ %s ] cannot malloc %d sockaddr_ins for CM entries\n",
3552 memset(CMSktArray, 0, CMsktbytes);
3554 /* Fill in the socket information for each CM */
3556 curr_skt = CMSktArray;
3557 curr_CM = CMnameList; /* CM name list header */
3559 strncpy(fullhostname,curr_CM->hostName,sizeof(fullhostname));
3560 he = GetHostByName(fullhostname);
3562 fprintf(stderr,"[ %s ] Cannot get host info for %s\n",rn, fullhostname);
3565 strncpy(curr_CM->hostName,he->h_name,HOST_NAME_LEN); /* complete name*/
3566 memcpy(&(curr_skt->sin_addr.s_addr), he->h_addr, 4);
3567 curr_skt->sin_family = htons(AF_INET); /*Internet family*/
3568 curr_skt->sin_port = htons(7001); /*Cache Manager port*/
3569 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
3570 curr_skt->sin_len = sizeof(struct sockaddr_in);
3573 /* get the next dude */
3575 curr_CM = curr_CM->next;
3578 /* initialize collection IDs. We need only one entry since we collect
3579 all the information from xstat */
3582 collIDP = (afs_int32 *) malloc (sizeof (afs_int32));
3583 if (collIDP == NULL) {
3584 fprintf(stderr,"[ %s ] failed to allocate a measely long word.Argh!\n", rn);
3587 *collIDP = 2; /* USE A macro for this */
3590 if (afsmon_onceOnly) /* once only ? */
3591 CMinitFlags |= XSTAT_CM_INITFLAG_ONE_SHOT;
3594 fprintf(debugFD,"[ %s ] Calling xstat_cm_Init \n",rn);
3598 code = xstat_cm_Init(numCM, /*Num servers*/
3599 CMSktArray, /*Cache Manager socket array*/
3600 afsmon_probefreq, /*probe frequency*/
3601 afsmon_CM_Handler, /*Handler routine*/
3602 CMinitFlags, /*Initialization flags*/
3603 numCollIDs, /*Number of collection IDs*/
3604 collIDP); /*Ptr to collection ID */
3607 fprintf(stderr,"[ %s ] xstat_cm_init returned error\n",rn);
3610 } /* end of process cache manager entries */
3613 /* if only one probe was required setup a waiting process for the
3614 termination signal */
3616 if (afsmon_onceOnly) {
3617 code = LWP_WaitProcess(&terminationEvent);
3620 fprintf(debugFD,"LWP_WaitProcess() returned error %d\n",code);
3627 /* start the gtx input server */
3628 code = gtx_InputServer(afsmon_win);
3630 fprintf(stderr,"[ %s ] Failed to start input server \n",rn);
3634 /* This part of the code is reached only if the input server is not started
3635 for debugging purposes */
3640 fprintf(stderr,"[ %s ] going to sleep ...\n",rn);
3642 code = IOMGR_Select( 0, /*Num fds*/
3643 0, /*Descriptors ready for reading*/
3644 0, /*Descriptors ready for writing*/
3645 0, /*Descriptors with exceptional conditions*/
3646 &tv); /*Timeout structure*/
3648 fprintf(stderr,"[ %s ] IOMGR_Select() returned non-zero value %d\n",
3656 /*-----------------------------------------------------------------------
3660 * Afsmonitor initialization routine.
3661 * - processes command line parameters
3662 * - call functions to:
3663 * - process config file
3664 * - initialize circular buffers and display buffers
3666 * - execute afsmonitor
3667 * - initialize the display maps [fs/cm]_Display_map[].
3670 * Success: Does not return from the call to afsmon_execute().
3671 * Failure: Exits afsmonitor.
3672 *----------------------------------------------------------------------*/
3676 struct cmd_syndesc *as;
3677 { /* afsmonInit() */
3679 static char rn[] = "afsmonInit"; /* Routine name */
3680 char *debug_filename; /* pointer to debug filename */
3681 FILE *outputFD; /* output file descriptor */
3682 struct cmd_item *hostPtr; /* ptr to parse command line args */
3683 char buf[256]; /* buffer for processing hostnames */
3688 fprintf(debugFD,"[ %s ] Called, as= %d\n",rn, as);
3692 /* Open the debug file if -debug option is specified */
3693 if (as->parms[P_DEBUG].items != 0) {
3695 debug_filename = as->parms[P_DEBUG].items->data;
3696 debugFD = fopen(debug_filename, "w");
3697 if (debugFD == (FILE *)0) {
3698 printf("[ %s ] Failed to open debugging file %s for writing\n",
3706 fprintf(debugFD,"[ %s ] Called\n", rn);
3710 /* use curses always until we support other packages */
3712 wpkg_to_use = atoi(as->parms[P_PACKAGE].items->data);
3714 switch (wpkg_to_use) {
3715 case GATOR_WIN_CURSES:
3716 fprintf(stderr, "curses\n");
3718 case GATOR_WIN_DUMB:
3719 fprintf(stderr, "dumb terminal\n");
3722 fprintf(stderr, "X11\n");
3725 fprintf(stderr, "Illegal graphics package: %d\n", wpkg_to_use);
3727 } /*end switch (wpkg_to_use)*/
3730 wpkg_to_use = GATOR_WIN_CURSES;
3732 /* get probe frequency . We check for meaningful bounds on the frequency
3733 and reset to the default value if needed. The upper bound of 24
3734 hours looks ridiculous though! */
3736 afsmon_probefreq = 0;
3737 if (as->parms[P_FREQUENCY].items != 0)
3738 afsmon_probefreq = atoi(as->parms[P_FREQUENCY].items->data);
3740 afsmon_probefreq = DEFAULT_FREQUENCY;
3742 if (afsmon_probefreq <= 0 || afsmon_probefreq > 24*60*60) {
3743 afsmon_probefreq = DEFAULT_FREQUENCY;
3745 fprintf(debugFD,"[ %s ] Invalid probe frequency %s specified, resetting to default value %d seconds\n",
3746 rn, as->parms[P_FREQUENCY].items->data, afsmon_probefreq);
3749 fprintf(stderr,"Invalid probe frequency %s specified, resetting to default value %d seconds\n",
3750 as->parms[P_FREQUENCY].items->data, afsmon_probefreq);
3755 /* make sure output file is writable, else complain now */
3756 /* we will open and close it as needed after probes */
3758 if (as->parms[P_OUTPUT].items != 0) {
3759 afsmon_output = 1; /* output flag */
3760 strncpy (output_filename, as->parms[P_OUTPUT].items->data,80);
3761 outputFD = fopen(output_filename,"a");
3762 if (outputFD == (FILE *)0) {
3763 fprintf(stderr,"Failed to open output file %s \n",
3766 fprintf(debugFD,"[ %s ] Failed to open output file %s \n",
3767 rn, output_filename);
3772 fprintf(debugFD,"[ %s ] output file is %s\n",rn,output_filename);
3777 /* detailed statistics to storage file */
3778 if (as->parms[P_DETAILED].items !=0) {
3779 if (as->parms[P_OUTPUT].items == 0) {
3780 fprintf(stderr,"-detailed switch can be used only with -output\n");
3783 afsmon_detOutput = 1;
3786 /* Initialize host list headers */
3787 FSnameList = (struct afsmon_hostEntry *)0;
3788 CMnameList = (struct afsmon_hostEntry *)0;
3790 /* The -config option is mutually exclusive with the -fshosts,-cmhosts
3793 if (as->parms[P_CONFIG].items) {
3794 if (as->parms[P_FSHOSTS].items || as->parms[P_CMHOSTS].items) {
3795 fprintf(stderr,"Cannot use -config option with -fshosts or -cmhosts\n");
3799 if (! as->parms[P_FSHOSTS].items && ! as->parms[P_CMHOSTS].items) {
3800 fprintf(stderr,"Must specify either -config or (-fshosts and/or -cmhosts) options \n");
3806 /* If a file server host is specified on the command line we reuse
3807 parse_hostEntry() function . Just the pass the info as if it were
3808 read off the config file */
3810 if (as->parms[P_FSHOSTS].items) {
3811 hostPtr = as->parms[P_FSHOSTS].items;
3812 while( hostPtr != (struct cmd_item *)0) {
3813 sprintf(buf,"fs %s",hostPtr->data);
3814 code = parse_hostEntry(buf);
3816 fprintf(stderr,"Could not parse %s\n",hostPtr->data);
3820 hostPtr = hostPtr->next;
3824 /* same as above for -cmhosts */
3825 if (as->parms[P_CMHOSTS].items) {
3826 hostPtr = as->parms[P_CMHOSTS].items;
3827 while( hostPtr != (struct cmd_item *)0) {
3828 sprintf(buf,"cm %s",hostPtr->data);
3829 code = parse_hostEntry(buf);
3831 fprintf(stderr,"Could not parse %s\n",hostPtr->data);
3835 hostPtr = hostPtr->next;
3839 /* number of slots in circular buffers */
3840 if (as->parms[P_BUFFERS].items)
3841 num_bufSlots = atoi(as->parms[P_BUFFERS].items->data);
3843 num_bufSlots = DEFAULT_BUFSLOTS;
3845 /* Initialize xx_showFlags[]. This array is used solely for processing the
3846 "show" directives in the config file in parse_showEntries() */
3847 for(i=0; i<NUM_FS_STAT_ENTRIES; i++)
3848 fs_showFlags[i] = 0;
3849 for(i=0; i<NUM_CM_STAT_ENTRIES; i++)
3850 cm_showFlags[i] = 0;
3853 /* Process the configuration file if given. This initializes among other
3854 things, the list of FS & CM names in FSnameList and CMnameList */
3856 if (as->parms[P_CONFIG].items)
3857 process_config_file(as->parms[P_CONFIG].items->data);
3859 /* print out the FS and CM lists */
3860 print_FS(); print_CM();
3862 /* Initialize the FS results-to-screen map array if there were no "show fs"
3863 directives in the config file */
3864 if (fs_showDefault) {
3865 for(i=0; i < NUM_FS_STAT_ENTRIES; i++)
3866 fs_Display_map[i] = i;
3867 fs_DisplayItems_count = NUM_FS_STAT_ENTRIES;
3870 /* Initialize the CM results-to-screen map array if there were no "show cm"
3871 directives in the config file */
3872 if (cm_showDefault) {
3873 for(i=0; i < NUM_CM_STAT_ENTRIES; i++)
3874 cm_Display_map[i] = i;
3875 cm_DisplayItems_count = NUM_CM_STAT_ENTRIES;
3880 /* setup an interrupt signal handler; we ain't wanna leak core */
3881 /* this binding is useful only until gtx is initialized after which the
3882 keyboard input server takes over. */
3883 if ( (signal(SIGINT,quit_signal)) == SIG_ERR ) {
3884 perror("signal() failed.");
3889 /* init error message buffers. these will be used to print error messages
3890 once gtx is initialized and there is no access to stderr/stdout */
3891 errMsg[0] = '\0'; errMsg1[0] = '\0';
3895 /* initialize fs and cm circular buffers before initiating probes */
3897 code = init_fs_buffers();
3899 fprintf(stderr,"[ %s ] init_fs_buffers returned %d\n",rn,code);
3905 code = init_cm_buffers();
3907 fprintf(stderr,"[ %s ] init_cm_buffers returned %d\n",rn,code);
3913 /* allocate and initialize buffers for holding fs & cm results in ascii
3914 format suitable for updating the screen */
3915 code = init_print_buffers();
3917 fprintf(stderr,"[ %s ] init_print_buffers returned %d\n",rn,code);
3921 /* perform gtx initializations */
3922 code = gtx_initialize();
3924 fprintf(stderr,"[ %s ] gtx_initialize returned %d\n",rn,code);
3928 /* start xstat probes */
3931 return(0); /* will not return from the call to afsmon_execute() */
3933 } /* afsmonInit() */
3936 /*-----------------------------------------------------------------------
3938 ------------------------------------------------------------------------*/
3940 #include "AFS_component_version_number.c"
3942 int main(argc, argv)
3947 static char rn[] = "main"; /* routine name */
3948 afs_int32 code; /*Return code*/
3949 struct cmd_syndesc *ts; /*Ptr to cmd line syntax descriptor*/
3951 #ifdef AFS_AIX32_ENV
3953 * The following signal action for AIX is necessary so that in case of a
3954 * crash (i.e. core is generated) we can include the user's data section
3955 * in the core dump. Unfortunately, by default, only a partial core is
3956 * generated which, in many cases, isn't too useful.
3958 struct sigaction nsa;
3960 sigemptyset(&nsa.sa_mask);
3961 nsa.sa_handler = SIG_DFL;
3962 nsa.sa_flags = SA_FULLDUMP;
3963 sigaction(SIGSEGV, &nsa, NULL);
3967 * Set up the commands we understand.
3969 ts = cmd_CreateSyntax("initcmd", afsmonInit, 0,
3970 "initialize the program");
3971 cmd_AddParm(ts, "-config", CMD_SINGLE, CMD_OPTIONAL,
3972 "configuration file");
3973 cmd_AddParm(ts, "-frequency", CMD_SINGLE, CMD_OPTIONAL,
3974 "poll frequency, in seconds");
3975 cmd_AddParm(ts, "-output", CMD_SINGLE, CMD_OPTIONAL,
3976 "storage file name");
3977 cmd_AddParm(ts, "-detailed", CMD_FLAG, CMD_OPTIONAL,
3978 "output detailed statistics to storage file");
3980 /* we hope to use this .... eventually! */
3981 cmd_AddParm(ts,"-package", CMD_SINGLE, CMD_REQUIRED,
3982 "Graphics Package to use");
3984 cmd_AddParm(ts, "-debug", CMD_SINGLE, CMD_OPTIONAL,
3985 "turn debugging output on to the named file");
3986 cmd_AddParm(ts, "-fshosts", CMD_LIST, CMD_OPTIONAL,
3987 "list of file servers to monitor");
3988 cmd_AddParm(ts, "-cmhosts", CMD_LIST, CMD_OPTIONAL,
3989 "list of cache managers to monitor");
3990 cmd_AddParm(ts,"-buffers", CMD_SINGLE, CMD_OPTIONAL,
3991 "number of buffer slots");
3994 * Parse command-line switches & execute afsmonitor
3997 code = cmd_Dispatch(argc, argv);
4003 exit(0); /* redundant, but gets rid of warning */