Bug Summary

File:afsmonitor/afsmonitor.c
Location:line 674, column 2
Description:Access to field 'next' results in a dereference of a null pointer (loaded from variable 'prev_item')

Annotated Source Code

1/*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 *
9 * Portions Copyright (c) 2003 Apple Computer, Inc.
10 */
11
12/*
13 * Afsmonitor: An AFS Performance Monitoring Tool
14 *
15 *-------------------------------------------------------------------------*/
16
17
18#include <afsconfig.h>
19#include <afs/param.h>
20
21
22#include <stdio.h>
23#include <math.h>
24#include <string.h>
25#include <errno(* __error()).h>
26#include <afs/cmd.h>
27#include <signal.h>
28#undef IN
29#include <sys/types.h>
30#include <netinet/in.h>
31#include <sys/socket.h>
32#include <netdb.h>
33#include <ctype.h>
34#ifdef HAVE_STDINT_H1
35# include <stdint.h>
36#endif
37
38#include <afs/gtxwindows.h> /*Generic window package */
39#include <afs/gtxobjects.h> /*Object definitions */
40#include <afs/gtxlightobj.h> /*Light object interface */
41#include <afs/gtxcurseswin.h> /*Curses window package */
42#include <afs/gtxdumbwin.h> /*Dumb terminal window package */
43#include <afs/gtxX11win.h> /*X11 window package */
44#include <afs/gtxframe.h> /*Frame package */
45#include <afs/gtxinput.h>
46
47#include <afs/xstat_fs.h>
48#include <afs/xstat_cm.h>
49
50#include "afsmonitor.h"
51
52/* command line parameter indices */
53
54#define P_CONFIG0 0
55#define P_FREQUENCY1 1
56#define P_OUTPUT2 2
57#define P_DETAILED3 3
58/* #define P_PACKAGE X */
59#define P_DEBUG4 4
60#define P_FSHOSTS5 5
61#define P_CMHOSTS6 6
62#define P_BUFFERS7 7
63
64
65int afsmon_debug = 0; /* debug info to file ? */
66FILE *debugFD; /* debugging file descriptor */
67static int afsmon_output = 0; /* output to file ? */
68static int afsmon_detOutput = 0; /* detailed output ? */
69static int afsmon_onceOnly = 0; /* probe once only ? (not implemented) */
70int afsmon_probefreq; /* probe frequency */
71static int wpkg_to_use; /* graphics package to use */
72static char output_filename[80]; /* output filename */
73char errMsg[256]; /* buffers used to print error messages after */
74char errMsg1[256]; /* gtx is initialized (stderr/stdout gone !) */
75int num_bufSlots = 0; /* number of slots in fs & cm circular buffers */
76
77/* Flags used to process "show" directives in config file */
78short fs_showFlags[NUM_FS_STAT_ENTRIES(275 + 16)];
79short cm_showFlags[NUM_CM_STAT_ENTRIES571];
80
81
82/* afsmonitor misc definitions */
83
84#define DEFAULT_FREQUENCY60 60 /* default proble frequency in seconds */
85#define DEFAULT_BUFSLOTS0 0 /* default number of buffer slots */
86#define CFG_STR_LEN80 80 /* max length of config file fields */
87#define FS1 1 /* for misc. use */
88#define CM2 2 /* for misc. use */
89
90
91#define NUM_XSTAT_FS_AFS_PERFSTATS_LONGS70 70 /* number of fields from struct afs_PerfStats that we display */
92#define NUM_AFS_STATS_CMPERF_LONGS40 40 /* number of longs in struct afs_stats_CMPerf excluding up/down stats and fields we dont display */
93
94
95/* variables used for exec'ing user provided threshold handlers */
96char *fsHandler_argv[20]; /* *argv[] for the handler */
97char fsHandler_args[20][256]; /* buffer space for arguments */
98int exec_fsThreshHandler = 0; /* execute fs threshold handler ? */
99
100
101/* THRESHOLD STRUCTURE DEFINITIONS */
102
103/* flag to indicate that threshold entries apply to all hosts. these will
104 be turned off when the first fs or cm host entry is processed */
105static int global_ThreshFlag = 1;
106static int global_fsThreshCount = 0; /* number of global fs thresholds */
107static int global_cmThreshCount = 0; /* number of global cm thresholds */
108
109
110
111/* Linked lists of file server and cache manager host names are made from
112the entries in the config file. Head pointers to FS and CM server name lists. */
113static struct afsmon_hostEntry *FSnameList;
114static struct afsmon_hostEntry *CMnameList;
115
116/* number of fileservers and cache managers to monitor */
117int numFS = 0;
118int numCM = 0;
119
120/* number of xstat collection ids */
121#define MAX_NUM_FS_COLLECTIONS2 2
122#define MAX_NUM_CM_COLLECTIONS1 1
123int num_fs_collections = 0;
124int num_cm_collections = 0;
125
126/* variables used for processing config file */
127/* ptr to the hostEntry structure of the last "fs" or "cm" entry processed
128in the config file */
129static struct afsmon_hostEntry *last_hostEntry;
130/* names of the last host processed in the config file */
131static char last_fsHost[HOST_NAME_LEN80];
132static char last_cmHost[HOST_NAME_LEN80];
133static int lastHostType = 0; /* 0 = no host entries processed
134 * 1 = last host was file server
135 * 2 = last host was cache manager. */
136
137
138/* FILE SERVER CIRCULAR BUFFER VARIABLES */
139
140struct afsmon_fs_Results_list {
141 struct xstat_fs_ProbeResults *fsResults[MAX_NUM_FS_COLLECTIONS2];
142 int empty[MAX_NUM_FS_COLLECTIONS2];
143 struct afsmon_fs_Results_list *next;
144};
145
146struct afsmon_fs_Results_CBuffer {
147 int probeNum; /* probe number of entries in this slot */
148 struct afsmon_fs_Results_list *list; /* ptr to list of results */
149};
150
151int afsmon_fs_results_length[] =
152 { XSTAT_FS_FULLPERF_RESULTS_LEN424, XSTAT_FS_CBSTATS_RESULTS_LEN16 };
153
154/* buffer for FS probe results */
155struct afsmon_fs_Results_CBuffer *afsmon_fs_ResultsCB;
156
157int afsmon_fs_curr_CBindex = 0; /* current fs CB slot */
158
159/* Probe number variables. The current probe number is incremented
160when the first probe from a new probe cycle is received. The prev probe
161number is incremented when the last probe of the current cycle is
162received. This difference is because of the purpose for which these
163counters are used */
164
165int afsmon_fs_curr_probeNum = 1; /* current fs probe number */
166int afsmon_fs_prev_probeNum = 0; /* previous fs probe number */
167
168
169/* CACHE MANAGER CIRCULAR BUFFER VARIABLES */
170
171struct afsmon_cm_Results_list {
172 struct xstat_cm_ProbeResults *cmResults[MAX_NUM_CM_COLLECTIONS1];
173 int empty[MAX_NUM_CM_COLLECTIONS1];
174 struct afsmon_cm_Results_list *next;
175};
176
177struct afsmon_cm_Results_CBuffer {
178 int probeNum; /* probe number of entries in this slot */
179 struct afsmon_cm_Results_list *list; /* ptr to list of results */
180};
181
182int afsmon_cm_results_length[] = { XSTAT_CM_FULLPERF_RESULTS_LEN740 };
183
184/* buffer for CM probe results */
185struct afsmon_cm_Results_CBuffer *afsmon_cm_ResultsCB;
186
187int afsmon_cm_curr_CBindex = 0; /* current cm CB slot */
188
189
190/* Probe number variables. The current probe number is incremented
191when the first probe from a new probe cycle is received. The prev probe
192number is incremented when the last probe of the current cycle is
193received. This difference is because of the purpose for which these
194counters are used */
195
196int afsmon_cm_curr_probeNum = 1; /* current cm probe number */
197int afsmon_cm_prev_probeNum = 0; /* previous cm probe number */
198
199
200/* Structures to hold FS & CM results in string format(suitable for display ) */
201
202/* ptr to array holding the results of FS probes in ascii format */
203 /* for current probe cycle */
204struct fs_Display_Data *curr_fsData = (struct fs_Display_Data *)0;
205 /* for previous probe cycle */
206struct fs_Display_Data *prev_fsData = (struct fs_Display_Data *)0;
207
208
209/* ptr to array holding the results of CM probes in ascii format */
210 /* for current probe cycle */
211struct cm_Display_Data *curr_cmData = (struct cm_Display_Data *)0;
212 /* for previous probe cycle */
213struct cm_Display_Data *prev_cmData = (struct cm_Display_Data *)0;
214
215/* EXTERN DEFINITIONS */
216
217/* file server and cache manager variable names (from afsmon_labels.h) */
218extern char *fs_varNames[];
219extern char *cm_varNames[];
220
221/* GTX & MISC VARIABLES */
222
223/* afsmonitor window */
224extern struct gwin *afsmon_win;
225
226/* current page number in the overview frame */
227extern int ovw_currPage;
228
229/* number of FS alerts and number of hosts on FS alerts */
230int num_fs_alerts;
231int numHosts_onfs_alerts;
232
233/* number of CM alerts and number of hosts on FS alerts */
234int num_cm_alerts;
235int numHosts_oncm_alerts;
236
237/* flag to indicate that atleast one probe cycle has completed and
238data is available for updating the display */
239extern int fs_Data_Available;
240extern int cm_Data_Available;
241
242extern int gtx_initialized; /* gtx initialized ? */
243
244/* This array contains the indices of the file server data items that
245are to be displayed on the File Servers screen. For example, suppose the
246user wishes to display only the vcache statistics then the following array
247will contain indices 2 to 14 corresponding to the position of the
248vcache data items in the fs_varNames[] array. If the config file contains
249no "show fs .." directives, it will contain the indices of all the
250items in the fs_varNames[] array */
251
252short fs_Display_map[NUM_FS_STAT_ENTRIES(275 + 16)];
253int fs_DisplayItems_count = 0; /* number of items to display */
254int fs_showDefault = 1; /* show all of FS data ? */
255
256
257/* same use as above for Cache Managers */
258short cm_Display_map[NUM_CM_STAT_ENTRIES571];
259int cm_DisplayItems_count = 0; /* number of items to display */
260int cm_showDefault = 1; /* show all of CM data ? */
261
262extern int fs_currPage; /* current page number in the File Servers frame */
263extern int fs_curr_LCol; /* current leftmost column on display on FS frame */
264
265extern int cm_currPage; /* current page number in the Cache Managers frame */
266extern int cm_curr_LCol; /* current leftmost column on display on CM frame */
267
268/* File server and Cache manager data is classified into sections &
269groups to help the user choose what he wants displayed */
270extern char *fs_categories[]; /* file server data category names */
271extern char *cm_categories[]; /* cache manager data category names */
272
273
274static int fs_FullPerfs_ltoa(struct fs_Display_Data *a_fsData,
275 struct xstat_fs_ProbeResults *a_fsResults);
276static int fs_CallBackStats_ltoa(struct fs_Display_Data *a_fsData,
277 struct xstat_fs_ProbeResults *a_fsResults);
278
279#ifdef HAVE_STRCASESTR1
280extern char * strcasestr(const char *, const char *);
281#else
282/*
283 strcasestr(): Return first occurence of pattern s2 in s1, case
284 insensitive.
285
286 This routine is required since I made pattern matching of the
287 config file to be case insensitive.
288*/
289
290char *
291strcasestr(s1, s2)
292 char *s1;
293 char *s2;
294{
295 char *ptr;
296 int len1, len2;
297
298 len1 = strlen(s1);
299 len2 = strlen(s2);
300
301 if (len1 < len2)
302 return ((char *)NULL((void *)0));
303
304 ptr = s1;
305
306 while (len1 >= len2 && len1 > 0) {
307 if ((strncasecmp(ptr, s2, len2)) == 0)
308 return (ptr);
309 ptr++;
310 len1--;
311 }
312 return ((char *)NULL((void *)0));
313}
314#endif
315
316struct hostent *
317GetHostByName(char *name)
318{
319 struct hostent *he;
320#ifdef AFS_SUN5_ENV
321 char ip_addr[32];
322#endif
323
324 he = gethostbyname(name);
325#ifdef AFS_SUN5_ENV
326 /* On solaris the above does not resolve hostnames to full names */
327 if (he != NULL((void *)0)) {
328 memcpy(ip_addr, he->h_addrh_addr_list[0], he->h_length);
329 he = gethostbyaddr(ip_addr, he->h_length, he->h_addrtype);
330 }
331#endif
332 return (he);
333}
334
335
336/*-----------------------------------------------------------------------
337 * afsmon_Exit()
338 *
339 * Description
340 * Exit gracefully from the afsmonitor. Frees memory where appropriate,
341 * cleans up after gtx and closes all open file descriptors. If a user
342 * provided threshold handler is to be exec'ed then gtx cleanup is
343 * not performed and an exec() is made instead of an exit().
344 *
345 * Returns
346 * Nothing.
347 *
348 * Comments
349 * This function is called to execute a user handler only
350 * by a child process.
351 *
352 *----------------------------------------------------------------------*/
353
354int
355afsmon_Exit(int a_exitVal) /* exit code */
356{ /* afsmon_Exit */
357 static char rn[] = "afsmon_Exit";
358 struct afsmon_fs_Results_list *tmp_fslist;
359 struct afsmon_fs_Results_list *next_fslist;
360 struct xstat_fs_ProbeResults *tmp_xstat_fsPR;
361 struct afsmon_cm_Results_list *tmp_cmlist;
362 struct afsmon_cm_Results_list *next_cmlist;
363 struct xstat_cm_ProbeResults *tmp_xstat_cmPR;
364 struct afsmon_hostEntry *curr_hostEntry;
365 struct afsmon_hostEntry *next_hostEntry;
366 int i;
367 int j;
368 int bufslot;
369 int code;
370
371 if (afsmon_debug) {
372 fprintf(debugFD, "[ %s ] Called with exit code %d\n", rn, a_exitVal);
373 fflush(debugFD);
374 }
375
376 /* get out of curses first, but not if we are here to exec a threshold
377 * handler. If we do, the screen gets messed up */
378 if (gtx_initialized && !exec_fsThreshHandler)
379 gator_cursesgwin_cleanup(afsmon_win);
380
381 /* print the error message buffer */
382 if (errMsg[0] != '\0')
383 fprintf(stderr__stderrp, "%s", errMsg);
384 if (errMsg1[0] != '\0')
385 fprintf(stderr__stderrp, "%s", errMsg1);
386
387 /* deallocate file server circular buffers */
388 if (numFS && num_bufSlots) {
389 if (afsmon_debug) {
390 fprintf(debugFD, "freeing FS circular buffers ");
391 fflush(debugFD);
392 }
393
394 for (bufslot = 0; bufslot < num_bufSlots; bufslot++) {
395 if (afsmon_debug)
396 fprintf(debugFD, " %d) ", bufslot);
397 if (afsmon_fs_ResultsCB[bufslot].list !=
398 (struct afsmon_fs_Results_list *)0) {
399 tmp_fslist = afsmon_fs_ResultsCB[bufslot].list;
400 j = numFS;
401 while (tmp_fslist) {
402 /* make sure we do not go astray */
403 if (--j < 0) {
404 if (afsmon_debug)
405 fprintf(debugFD,
406 "[ %s ] error in deallocating fs CB\n",
407 rn);
408 break;
409 }
410 next_fslist = tmp_fslist->next;
411 for (i = 0; i < MAX_NUM_FS_COLLECTIONS2; i++) {
412 tmp_xstat_fsPR = tmp_fslist->fsResults[i];
413
414 if (afsmon_debug)
415 fprintf(debugFD, "%d ", numFS - j);
416
417 /* free xstat_fs_Results data */
418 free(tmp_xstat_fsPR->data.AFS_CollData_val);
419 free(tmp_xstat_fsPR->connP);
420 free(tmp_xstat_fsPR);
421 }
422
423 /* free the fs list item */
424 free(tmp_fslist);
425 tmp_fslist = next_fslist;
426
427 } /* while fs list items in this slot */
428 } /* if entries in this buffer slot */
429 } /* for each fs buffer slot */
430 if (afsmon_debug)
431 fprintf(debugFD, "\n");
432 }
433
434 if (afsmon_debug)
435 fflush(debugFD);
436 /* deallocate cache manager curcular buffers */
437 if (numCM && num_bufSlots) {
438 if (afsmon_debug)
439 fprintf(debugFD, "freeing CM curcular buffers ");
440 for (bufslot = 0; bufslot < num_bufSlots; bufslot++) {
441 if (afsmon_debug)
442 fprintf(debugFD, " %d) ", bufslot);
443 if (afsmon_cm_ResultsCB[bufslot].list !=
444 (struct afsmon_cm_Results_list *)0) {
445 tmp_cmlist = afsmon_cm_ResultsCB[bufslot].list;
446 j = numCM;
447 while (tmp_cmlist) {
448 /* make sure we do not go astray */
449 if (--j < 0) {
450 if (afsmon_debug)
451 fprintf(debugFD,
452 "[ %s ] error in deallocating cm CB\n",
453 rn);
454 break;
455 }
456 next_cmlist = tmp_cmlist->next;
457 for (i = 0; i < MAX_NUM_CM_COLLECTIONS1; i++) {
458 tmp_xstat_cmPR = tmp_cmlist->cmResults[i];
459
460 if (afsmon_debug)
461 fprintf(debugFD, "%d ", numCM - j);
462 /* make sure data is ok */
463 /* Print_cm_FullPerfInfo(tmp_xstat_cmPR); */
464
465 /* free xstat_cm_Results data */
466 free(tmp_xstat_cmPR->data.AFSCB_CollData_val);
467 free(tmp_xstat_cmPR->connP);
468 }
469 free(tmp_cmlist->cmResults);
470
471 /* free the cm list item */
472 free(tmp_cmlist);
473 tmp_cmlist = next_cmlist;
474
475 } /* while cm list items in this slot */
476 } /* if entries in this buffer slot */
477 } /* for each cm buffer slot */
478 if (afsmon_debug)
479 fprintf(debugFD, "\n");
480 }
481
482
483 /* deallocate FS & CM Print buffers */
484 if (curr_fsData != (struct fs_Display_Data *)0) {
485 if (afsmon_debug)
486 fprintf(debugFD, "Deallocating FS Print Buffers .... curr");
487 free(curr_fsData);
488 }
489 if (prev_fsData != (struct fs_Display_Data *)0) {
490 if (afsmon_debug)
491 fprintf(debugFD, ", prev \n");
492 free(prev_fsData);
493 }
494 if (prev_cmData != (struct cm_Display_Data *)0) {
495 if (afsmon_debug)
496 fprintf(debugFD, "Deallocating CM Print Buffers .... curr");
497 free(curr_cmData);
498 }
499 if (prev_cmData != (struct cm_Display_Data *)0) {
500 if (afsmon_debug)
501 fprintf(debugFD, ", prev \n");
502 free(prev_cmData);
503 }
504
505 /* deallocate hostEntry lists */
506 if (numFS) {
507 if (afsmon_debug)
508 fprintf(debugFD, "Deallocating FS hostEntries ..");
509 curr_hostEntry = FSnameList;
510 while (curr_hostEntry) {
511 next_hostEntry = curr_hostEntry->next;
512 if (curr_hostEntry->thresh != NULL((void *)0))
513 free(curr_hostEntry->thresh);
514 free(curr_hostEntry);
515 curr_hostEntry = next_hostEntry;
516 }
517 if (afsmon_debug)
518 fprintf(debugFD, "\n");
519 }
520 if (numCM) {
521 if (afsmon_debug)
522 fprintf(debugFD, "Deallocating CM hostEntries ..");
523 curr_hostEntry = CMnameList;
524 while (curr_hostEntry) {
525 next_hostEntry = curr_hostEntry->next;
526 if (curr_hostEntry->thresh != NULL((void *)0))
527 free(curr_hostEntry->thresh);
528 free(curr_hostEntry);
529 curr_hostEntry = next_hostEntry;
530 }
531 if (afsmon_debug)
532 fprintf(debugFD, "\n");
533 }
534
535 /* close debug file */
536 if (afsmon_debug) {
537 fflush(debugFD);
538 fclose(debugFD);
539 }
540
541 if (exec_fsThreshHandler) {
542 code = execvp(fsHandler_argv[0], fsHandler_argv);
543 if (code == -1) {
544 fprintf(stderr__stderrp, "execvp() of %s returned %d, errno %d\n",
545 fsHandler_argv[0], code, errno(* __error()));
546 exit(-1);
547 }
548 }
549
550 exit(a_exitVal);
551} /* afsmon_Exit */
552
553/*-----------------------------------------------------------------------
554 * insert_FS()
555 *
556 * Description:
557 * Insert a hostname in the file server names list.
558 *
559 * Returns:
560 * Success: 0
561 * Failure: -1
562 *----------------------------------------------------------------------*/
563
564int
565insert_FS(char *a_hostName) /* name of cache manager to be inserted in list */
566{ /* insert_FS() */
567 static struct afsmon_hostEntry *curr_item;
568 static struct afsmon_hostEntry *prev_item;
569
570 if (*a_hostName == '\0')
571 return (-1);
572 curr_item = (struct afsmon_hostEntry *)
573 malloc(sizeof(struct afsmon_hostEntry));
574 if (curr_item == (struct afsmon_hostEntry *)0) {
575 fprintf(stderr__stderrp, "Failed to allocate space for FS nameList\n");
576 return (-1);
577 }
578
579 strncpy(curr_item->hostName, a_hostName, CFG_STR_LEN80);
580 curr_item->next = (struct afsmon_hostEntry *)0;
581 curr_item->numThresh = 0;
582 curr_item->thresh = NULL((void *)0);
583
584 if (FSnameList == (struct afsmon_hostEntry *)0)
585 FSnameList = curr_item;
586 else
587 prev_item->next = curr_item;
588
589 prev_item = curr_item;
590 /* record the address of this entry so that its threshold
591 * count can be incremented during the first pass of the config file */
592 last_hostEntry = curr_item;
593
594 return (0);
595}
596
597/*-----------------------------------------------------------------------
598 * print_FS()
599 *
600 * Description:
601 * Debug routine.
602 * Prints the file server names linked list.
603 *
604 * Returns:
605 * Nothing.
606 *----------------------------------------------------------------------*/
607void
608print_FS(void)
609{ /* print_FS() */
610 static char rn[] = "print_FS";
611 struct afsmon_hostEntry *tempFS;
612 struct Threshold *threshP;
613 int i;
614
615 if (afsmon_debug) {
616 fprintf(debugFD, "[ %s ] Called\n", rn);
617 fflush(debugFD);
618 }
619
620 if (afsmon_debug) {
621 tempFS = FSnameList;
622 fprintf(debugFD, "No of File Servers: %d\n", numFS);
623 if (numFS) {
624 do {
625 fprintf(debugFD, "\t %s threshCount = %d\n", tempFS->hostName,
626 tempFS->numThresh);
627 threshP = tempFS->thresh;
628 for (i = 0; i < tempFS->numThresh; i++, threshP++)
629 fprintf(debugFD, "\t thresh (%2d) %s %s %s\n",
630 threshP->index, threshP->itemName,
631 threshP->threshVal, threshP->handler);
632 } while ((tempFS = tempFS->next) != (struct afsmon_hostEntry *)0);
633 }
634 fprintf(debugFD, "\t\t-----End of List-----\n");
635 fflush(debugFD);
636 }
637
638}
639
640/*-----------------------------------------------------------------------
641 * insert_CM()
642 *
643 * Description:
644 * Insert a hostname in the cache manager names list.
645 *
646 * Returns:
647 * Success: 0
648 * Failure: -1
649 *----------------------------------------------------------------------*/
650
651int
652insert_CM(char *a_hostName) /* name of cache manager to be inserted in list */
653{ /* insert_CM */
654 static struct afsmon_hostEntry *curr_item;
655 static struct afsmon_hostEntry *prev_item;
1
Variable 'prev_item' initialized to a null pointer value
656
657 if (*a_hostName == '\0')
2
Taking false branch
658 return (-1);
659 curr_item = (struct afsmon_hostEntry *)
660 malloc(sizeof(struct afsmon_hostEntry));
661 if (curr_item == (struct afsmon_hostEntry *)0) {
3
Taking false branch
662 fprintf(stderr__stderrp, "Failed to allocate space for CM nameList\n");
663 return (-1);
664 }
665
666 strncpy(curr_item->hostName, a_hostName, CFG_STR_LEN80);
667 curr_item->next = (struct afsmon_hostEntry *)0;
668 curr_item->numThresh = 0;
669 curr_item->thresh = NULL((void *)0);
670
671 if (CMnameList == (struct afsmon_hostEntry *)0)
4
Taking false branch
672 CMnameList = curr_item;
673 else
674 prev_item->next = curr_item;
5
Access to field 'next' results in a dereference of a null pointer (loaded from variable 'prev_item')
675
676 prev_item = curr_item;
677 /* side effect. note the address of this entry so that its threshold
678 * count can be incremented during the first pass of the config file */
679 last_hostEntry = curr_item;
680
681 return (0);
682}
683
684
685/*-----------------------------------------------------------------------
686 * print_CM()
687 *
688 * Description:
689 * Debug routine.
690 * Prints the cache manager names linked list.
691 *
692 * Returns:
693 * Nothing.
694 *----------------------------------------------------------------------*/
695int
696print_CM(void)
697{ /* print_CM() */
698 static char rn[] = "print_CM";
699 struct afsmon_hostEntry *tempCM;
700 struct Threshold *threshP;
701 int i;
702
703 if (afsmon_debug) {
704 fprintf(debugFD, "[ %s ] Called\n", rn);
705 fflush(debugFD);
706 }
707
708 if (afsmon_debug) {
709 tempCM = CMnameList;
710 fprintf(debugFD, "No of Cache Managers: %d\n", numCM);
711 if (numCM) {
712 do {
713 fprintf(debugFD, "\t %s threshCount = %d\n", tempCM->hostName,
714 tempCM->numThresh);
715 threshP = tempCM->thresh;
716 for (i = 0; i < tempCM->numThresh; i++, threshP++)
717 fprintf(debugFD, "\t thresh (%2d) %s %s %s\n",
718 threshP->index, threshP->itemName,
719 threshP->threshVal, threshP->handler);
720 } while ((tempCM = tempCM->next) != (struct afsmon_hostEntry *)0);
721 }
722 fprintf(debugFD, "\t\t-----End of List-----\n");
723 }
724 return (0);
725} /* print_CM() */
726
727
728
729/*-----------------------------------------------------------------------
730 * parse_hostEntry()
731 *
732 * Description:
733 * Parse the host entry line in the config file. Check the syntax,
734 * and inserts the host name in the FS ot CM linked list. Also
735 * remember if this entry was an fs or cm & the ptr to its hostEntry
736 * structure. The threshold entries in the config file are dependent
737 * on their position relative to the hostname entries. Hence it is
738 * required to remember the names of the last file server and cache
739 * manager entries that were processed.
740 *
741 * Returns:
742 * Success: 0
743 * Failure: -1
744 *
745 *----------------------------------------------------------------------*/
746
747int
748parse_hostEntry(char *a_line)
749{ /* parse_hostEntry */
750
751 static char rn[] = "parse_hostEntry"; /* routine name */
752 char opcode[CFG_STR_LEN80]; /* specifies type of config entry */
753 char arg1[CFG_STR_LEN80]; /* hostname or qualifier (fs/cm?) */
754 char arg2[CFG_STR_LEN80]; /* threshold variable */
755 char arg3[CFG_STR_LEN80]; /* threshold value */
756 char arg4[CFG_STR_LEN80]; /* user's handler */
757 struct hostent *he; /* host entry */
758
759 if (afsmon_debug) {
760 fprintf(debugFD, "[ %s ] Called, a_line = %s\n", rn, a_line);
761 fflush(debugFD);
762 }
763
764 /* break it up */
765 opcode[0] = 0;
766 arg1[0] = 0;
767 arg2[0] = 0;
768 arg3[0] = 0;
769 arg4[0] = 0;
770 sscanf(a_line, "%s %s %s %s %s", opcode, arg1, arg2, arg3, arg4);
771 /* syntax is "opcode hostname" */
772 if ((strlen(arg2)) != 0) {
773 fprintf(stderr__stderrp, "[ %s ] Extraneous characters at end of line\n", rn);
774 return (-1);
775 }
776
777 /* good host ? */
778 he = GetHostByName(arg1);
779 if (he == NULL((void *)0)) {
780 fprintf(stderr__stderrp, "[ %s ] Unable to resolve hostname %s\n", rn, arg1);
781 return (-1);
782 }
783
784 if ((strcasecmp(opcode, "fs")) == 0) {
785 /* use the complete host name to insert in the file server names list */
786 insert_FS(he->h_name);
787 /* note that last host entry in the config file was fs */
788 lastHostType = 1;
789 numFS++;
790 /* threholds are not global anymore */
791 if (global_ThreshFlag)
792 global_ThreshFlag = 0;
793 } else if ((strcasecmp(opcode, "cm")) == 0) {
794 /* use the complete host name to insert in the CM names list */
795 insert_CM(he->h_name);
796 /* last host entry in the config file was cm */
797 lastHostType = 2;
798 numCM++;
799 /* threholds are not global anymore */
800 if (global_ThreshFlag)
801 global_ThreshFlag = 0;
802 } else
803 return (-1);
804
805 return (0);
806}
807
808/*-----------------------------------------------------------------------
809 * parse_threshEntry()
810 *
811 * Description
812 * Parse the threshold entry line in the config file. This function is
813 * called in the the first pass of the config file. It checks the syntax
814 * of the config lines and verifies their positional validity - eg.,
815 * a cm threshold cannot appear after a fs hostname entry, etc.
816 * It also counts the thresholds applicable to each host.
817 *
818 * Returns
819 * Success: 0
820 * Failure: -1
821 *
822 *----------------------------------------------------------------------*/
823
824int
825parse_threshEntry(char *a_line)
826{ /* parse_threshEntry */
827 static char rn[] = "parse_threshEntry"; /* routine name */
828 char opcode[CFG_STR_LEN80]; /* specifies type of config entry */
829 char arg1[CFG_STR_LEN80]; /* hostname or qualifier (fs/cm?) */
830 char arg2[CFG_STR_LEN80]; /* threshold variable */
831 char arg3[CFG_STR_LEN80]; /* threshold value */
832 char arg4[CFG_STR_LEN80]; /* user's handler */
833 char arg5[CFG_STR_LEN80]; /* junk characters */
834
835 if (afsmon_debug) {
836 fprintf(debugFD, "[ %s ] Called, a_line = %s\n", rn, a_line);
837 fflush(debugFD);
838 }
839
840 /* break it up */
841 opcode[0] = 0;
842 arg1[0] = 0;
843 arg2[0] = 0;
844 arg3[0] = 0;
845 arg4[0] = 0;
846 arg5[0] = 0;
847 sscanf(a_line, "%s %s %s %s %s %s", opcode, arg1, arg2, arg3, arg4, arg5);
848
849 /* syntax is "thresh fs/cm variable_name threshold_value [handler] " */
850 if (((strlen(arg1)) == 0) || ((strlen(arg2)) == 0)
851 || ((strlen(arg3)) == 0)) {
852 fprintf(stderr__stderrp, "[ %s ] Incomplete line\n", rn);
853 return (-1);
854 }
855 if (strlen(arg3) > THRESH_VAR_LEN16 - 2) {
856 fprintf(stderr__stderrp, "[%s ] threshold value too long\n", rn);
857 return (-1);
858 }
859
860 if ((strcasecmp(arg1, "fs")) == 0) {
861 switch (lastHostType) {
862 case 0: /* its a global threshold */
863 global_fsThreshCount++;
864 break;
865 case 1: /* inc thresh count of last file server */
866 last_hostEntry->numThresh++;
867 break;
868 case 2:
869 fprintf(stderr__stderrp,
870 "[ %s ] A threshold for a File Server cannot be placed after a Cache Manager host entry in the config file \n",
871 rn);
872 return (-1);
873 default:
874 fprintf(stderr__stderrp, "[ %s ] Programming error 1\n", rn);
875 return (-1);
876 }
877 } else if ((strcasecmp(arg1, "cm")) == 0) {
878 switch (lastHostType) {
879 case 0: /* its a global threshold */
880 global_cmThreshCount++;
881 break;
882 case 2: /* inc thresh count of last cache manager */
883 last_hostEntry->numThresh++;
884 break;
885 case 1:
886 fprintf(stderr__stderrp,
887 "[ %s ] A threshold for a Cache Manager cannot be placed after a File Server host entry in the config file \n",
888 rn);
889 return (-1);
890 default:
891 fprintf(stderr__stderrp, "[ %s ] Programming error 2\n", rn);
892 return (-1);
893 }
894 } else {
895 fprintf(stderr__stderrp,
896 "[ %s ] Syntax error. Second argument should be \"fs\" or \"cm\" \n",
897 rn);
898 return (-1);
899 }
900
901 return (0);
902} /* parse_threshEntry */
903
904
905/*-----------------------------------------------------------------------
906 * store_threshold()
907 *
908 * Description
909 * The thresholds applicable to each host machine are stored in the
910 * FSnameList and CMnameList. Threshold entries in the config file are
911 * context sensitive. The host to which this threshold is applicable
912 * is pointed to by last_fsHost (for file servers) and last_cmHost
913 * for cache managers. For global thresholds the info is recorded for
914 * all the hosts. This function is called in the second pass of the
915 * config file. In the first pass a count of the number of global
916 * thresholds is determined and this information is used in this
917 * routine. If threshold entries are duplicated the first entry is
918 * overwritten.
919 * Each threshold entry also has an index field. This is a positional
920 * index to the corresponding variable in the prev_[fs/cm]Data arrays.
921 * This makes it easy to check the threshold for overflow.
922 *
923 * Returns:
924 * Success: 0
925 * Failure: -1
926 *----------------------------------------------------------------------*/
927
928int
929store_threshold(int a_type, /* 1 = fs , 2 = cm */
930 char *a_varName, /* threshold name */
931 char *a_value, /* threshold value */
932 char *a_handler) /* threshold overflow handler */
933{ /* store_thresholds */
934
935 static char rn[] = "store_thresholds"; /* routine name */
936 struct afsmon_hostEntry *tmp_host; /* tmp ptr to hostEntry */
937 struct afsmon_hostEntry *Header; /* tmp ptr to hostEntry list header */
938 struct Threshold *threshP; /* tmp ptr to threshold list */
939 char *hostname;
940 int index; /* index to fs_varNames or cm_varNames */
941 int found;
942 int done;
943 int srvCount; /* tmp count of host names */
944 int *global_TC; /* ptr to global_xxThreshCount */
945 int i, j;
946
947 if (afsmon_debug) {
948 fprintf(debugFD,
949 "[ %s ] Called, a_type= %d, a_varName= %s, a_value= %s, a_handler=%s\n",
950 rn, a_type, a_varName, a_value, a_handler);
951 fflush(debugFD);
952 }
953
954 /* resolve the threshold variable name */
955 found = 0;
956 if (a_type == 1) { /* fs threshold */
957 for (index = 0; index < NUM_FS_STAT_ENTRIES(275 + 16); index++) {
958 if (strcasecmp(a_varName, fs_varNames[index]) == 0) {
959 found = 1;
960 break;
961 }
962 }
963 if (!found) {
964 fprintf(stderr__stderrp, "[ %s ] Unknown FS threshold variable name %s\n",
965 rn, a_varName);
966 return (-1);
967 }
968 Header = FSnameList;
969 srvCount = numFS;
970 hostname = last_fsHost;
971 global_TC = &global_fsThreshCount;
972 } else if (a_type == 2) { /* cm threshold */
973 for (index = 0; index < NUM_CM_STAT_ENTRIES571; index++) {
974 if (strcasecmp(a_varName, cm_varNames[index]) == 0) {
975 found = 1;
976 break;
977 }
978 }
979 if (!found) {
980 fprintf(stderr__stderrp, "[ %s ] Unknown CM threshold variable name %s\n",
981 rn, a_varName);
982 return (-1);
983 }
984 Header = CMnameList;
985 srvCount = numCM;
986 hostname = last_cmHost;
987 global_TC = &global_cmThreshCount;
988 } else
989 return (-1);
990
991
992
993 /* if the global thresh count is not zero, place this threshold on
994 * all the host entries */
995
996 if (*global_TC) {
997 tmp_host = Header;
998 for (i = 0; i < srvCount; i++) {
999 threshP = tmp_host->thresh;
1000 done = 0;
1001 for (j = 0; j < tmp_host->numThresh; j++) {
1002 if ((threshP->itemName[0] == '\0')
1003 || (strcasecmp(threshP->itemName, a_varName) == 0)) {
1004 strncpy(threshP->itemName, a_varName,
1005 THRESH_VAR_NAME_LEN80);
1006 strncpy(threshP->threshVal, a_value, THRESH_VAR_LEN16);
1007 strcpy(threshP->handler, a_handler);
1008 threshP->index = index;
1009 done = 1;
1010 break;
1011 }
1012 threshP++;
1013 }
1014 if (!done) {
1015 fprintf(stderr__stderrp, "[ %s ] Could not insert threshold entry",
1016 rn);
1017 fprintf(stderr__stderrp, "for %s in thresh list of host %s \n",
1018 a_varName, tmp_host->hostName);
1019 return (-1);
1020 }
1021 tmp_host = tmp_host->next;
1022 }
1023 (*global_TC)--;
1024 return (0);
1025 }
1026
1027 /* it is not a global threshold, insert it in the thresh list of this
1028 * host only. We overwrite the global threshold if it was alread set */
1029
1030 if (*hostname == '\0') {
1031 fprintf(stderr__stderrp, "[ %s ] Programming error 3\n", rn);
1032 return (-1);
1033 }
1034
1035 /* get the hostEntry that this threshold belongs to */
1036 tmp_host = Header;
1037 found = 0;
1038 for (i = 0; i < srvCount; i++) {
1039 if (strcasecmp(tmp_host->hostName, hostname) == 0) {
1040 found = 1;
1041 break;
1042 }
1043 tmp_host = tmp_host->next;
1044 }
1045 if (!found) {
1046 fprintf(stderr__stderrp, "[ %s ] Unable to find host %s in %s hostEntry list",
1047 rn, hostname, (a_type - 1) ? "CM" : "FS");
1048 return (-1);
1049 }
1050
1051 /* put this entry on the thresh list of this host, overwrite global value
1052 * if needed */
1053
1054 threshP = tmp_host->thresh;
1055 done = 0;
1056 for (i = 0; i < tmp_host->numThresh; i++) {
1057 if ((threshP->itemName[0] == '\0')
1058 || (strcasecmp(threshP->itemName, a_varName) == 0)) {
1059 strncpy(threshP->itemName, a_varName, THRESH_VAR_NAME_LEN80);
1060 strncpy(threshP->threshVal, a_value, THRESH_VAR_LEN16);
1061 strcpy(threshP->handler, a_handler);
1062 threshP->index = index;
1063 done = 1;
1064 break;
1065 }
1066 threshP++;
1067 }
1068
1069 if (!done) {
1070 fprintf(stderr__stderrp,
1071 "[ %s ] Unable to insert threshold %s for %s host %s\n", rn,
1072 a_varName, (a_type - 1) ? "CM" : "FS", tmp_host->hostName);
1073 return (-1);
1074 }
1075
1076 return (0);
1077
1078} /* store_thresholds */
1079
1080
1081/*-----------------------------------------------------------------------
1082 * parse_showEntry()
1083 *
1084 * Description:
1085 * This function process a "show" entry in the config file. A "show"
1086 * entry specifies what statistics the user wants to see. File
1087 * server and Cache Manager data is divided into sections. Each section
1088 * is made up of one or more groups. If a group name is specified only
1089 * those statistics under that group are shown. If a section name is
1090 * specified all the groups under this section are shown.
1091 * Data as obtained from the xstat probes is considered to be ordered.
1092 * This data is mapped to the screen thru fs_Display_map[] and
1093 * cm_Display_map[]. This routine parses the "show" entry against the
1094 * section/group names in the [fs/cm]_categories[] array. If there is
1095 * no match it tries to match it against a variable name in
1096 * [fs/cm]_varNames[] array. In each case the corresponding indices to
1097 * the data is the [fs/cm]_displayInfo[] is recorded.
1098 *
1099 * Returns:
1100 * Success: 0
1101 * Failure: -1 (invalid entry)
1102 * > -1 (programming error)
1103 *----------------------------------------------------------------------*/
1104
1105int
1106parse_showEntry(char *a_line)
1107{ /* parse_showEntry */
1108 static char rn[] = "parse_showEntry";
1109 char opcode[CFG_STR_LEN80]; /* specifies type of config entry */
1110 char arg1[CFG_STR_LEN80]; /* show fs or cm entry ? */
1111 char arg2[CFG_STR_LEN80]; /* what we gotta show */
1112 char arg3[CFG_STR_LEN80]; /* junk */
1113 char catName[CFG_STR_LEN80]; /* for category names */
1114 int numGroups; /* number of groups in a section */
1115 int fromIdx;
1116 int toIdx;
1117 int found;
1118 int idx = 0; /* index to fs_categories[] */
1119 int i;
1120 int j;
1121
1122
1123 if (afsmon_debug) {
1124 fprintf(debugFD, "[ %s ] Called, a_line= %s\n", rn, a_line);
1125 fflush(debugFD);
1126 }
1127 opcode[0] = 0;
1128 arg1[0] = 0;
1129 arg2[0] = 0;
1130 arg3[0] = 0;
1131 sscanf(a_line, "%s %s %s %s", opcode, arg1, arg2, arg3);
1132
1133 if (arg3[0] != '\0') {
1134 fprintf(stderr__stderrp, "[ %s ] Extraneous characters at end of line\n", rn);
1135 return (-1);
1136 }
1137
1138 if ((strcasecmp(arg1, "fs") != 0) && (strcasecmp(arg1, "cm") != 0)) {
1139 fprintf(stderr__stderrp,
1140 "[ %s ] Second argument of \"show\" directive should be \"fs\" or \"cm\" \n",
1141 rn);
1142 return (-1);
1143 }
1144
1145 /* Each entry can either be a variable name or a section/group name. Variable
1146 * names are listed in xx_varNames[] and section/group names in xx_categories[].
1147 * The section/group names in xx_categiries[] also give the starting/ending
1148 * indices of the variables belonging to that section/group. These indices
1149 * are stored in order in xx_Display_map[] and displayed to the screen in that
1150 * order. */
1151
1152 /* To handle duplicate "show" entries we keep track of what what we have
1153 * already marked to show in the xx_showFlags[] */
1154
1155 if (strcasecmp(arg1, "fs") == 0) { /* its a File Server entry */
1156
1157 /* mark that we have to show only what the user wants */
1158 fs_showDefault = 0;
1159
1160 /* if it is a section/group name, find it in the fs_categories[] array */
1161
1162 found = 0;
1163 if (strcasestr(arg2, "_section") != (char *)NULL((void *)0)
1164 || strcasestr(arg2, "_group") != (char *)NULL((void *)0)) {
1165 idx = 0;
1166 while (idx < FS_NUM_DATA_CATEGORIES13) {
1167 sscanf(fs_categories[idx], "%s %d %d", catName, &fromIdx,
1168 &toIdx);
1169 idx++;
1170 if (strcasecmp(arg2, catName) == 0) {
1171 found = 1;
1172 break;
1173 }
1174 }
1175
1176 if (!found) { /* typo in section/group name */
1177 fprintf(stderr__stderrp,
1178 "[ %s ] Could not find section/group name %s\n", rn,
1179 arg2);
1180 return (-1);
1181 }
1182 }
1183
1184 /* if it is a group name, read its start/end indices and fill in the
1185 * fs_Display_map[]. */
1186
1187 if (strcasestr(arg2, "_group") != (char *)NULL((void *)0)) {
1188
1189 if (fromIdx < 0 || toIdx < 0 || fromIdx > NUM_FS_STAT_ENTRIES(275 + 16)
1190 || toIdx > NUM_FS_STAT_ENTRIES(275 + 16))
1191 return (-2);
1192 for (j = fromIdx; j <= toIdx; j++) {
1193 if (!fs_showFlags[j]) {
1194 fs_Display_map[fs_DisplayItems_count] = j;
1195 fs_DisplayItems_count++;
1196 fs_showFlags[j] = 1;
1197 }
1198 if (fs_DisplayItems_count > NUM_FS_STAT_ENTRIES(275 + 16)) {
1199 fprintf(stderr__stderrp, "[ %s ] fs_DisplayItems_count ovf\n", rn);
1200 return (-3);
1201 }
1202 }
1203 } else
1204 /* if it is a section name, get the count of number of groups in it and
1205 * for each group fill in the start/end indices in the fs_Display_map[] */
1206
1207 if (strcasestr(arg2, "_section") != (char *)NULL((void *)0)) {
1208 /* fromIdx is actually the number of groups in thi section */
1209 numGroups = fromIdx;
1210 /* for each group in section */
1211 while (idx < FS_NUM_DATA_CATEGORIES13 && numGroups) {
1212 sscanf(fs_categories[idx], "%s %d %d", catName, &fromIdx,
1213 &toIdx);
1214
1215 if (strcasestr(catName, "_group") != NULL((void *)0)) {
1216 if (fromIdx < 0 || toIdx < 0
1217 || fromIdx > NUM_FS_STAT_ENTRIES(275 + 16)
1218 || toIdx > NUM_FS_STAT_ENTRIES(275 + 16))
1219 return (-4);
1220 for (j = fromIdx; j <= toIdx; j++) {
1221 if (!fs_showFlags[j]) {
1222 fs_Display_map[fs_DisplayItems_count] = j;
1223 fs_DisplayItems_count++;
1224 fs_showFlags[j] = 1;
1225 }
1226 if (fs_DisplayItems_count > NUM_FS_STAT_ENTRIES(275 + 16)) {
1227 fprintf(stderr__stderrp,
1228 "[ %s ] fs_DisplayItems_count ovf\n", rn);
1229 return (-5);
1230 }
1231 }
1232 } else {
1233 fprintf(stderr__stderrp, "[ %s ] Error parsing groups for %s\n",
1234 rn, arg2);
1235 return (-6);
1236 }
1237 idx++;
1238 numGroups--;
1239 } /* for each group in section */
1240
1241
1242 } else { /* it is a variable name */
1243
1244 for (i = 0; i < NUM_FS_STAT_ENTRIES(275 + 16); i++) {
1245 if (strcasecmp(arg2, fs_varNames[i]) == 0) {
1246 if (!fs_showFlags[i]) {
1247 fs_Display_map[fs_DisplayItems_count] = i;
1248 fs_DisplayItems_count++;
1249 fs_showFlags[i] = 1;
1250 }
1251 if (fs_DisplayItems_count >= NUM_FS_STAT_ENTRIES(275 + 16)) {
1252 fprintf(stderr__stderrp, "[ %s ] fs_DisplayItems_count ovf\n",
1253 rn);
1254 return (-25);
1255 }
1256 found = 1;
1257 }
1258 }
1259 if (!found) { /* typo in section/group name */
1260 fprintf(stderr__stderrp, "[ %s ] Could not find variable name %s\n",
1261 rn, arg2);
1262 return (-1);
1263 }
1264 } /* its a variable name */
1265
1266 }
1267
1268 /* it is an fs entry */
1269 if (strcasecmp(arg1, "cm") == 0) { /* its a Cache Manager entry */
1270
1271
1272 /* mark that we have to show only what the user wants */
1273 cm_showDefault = 0;
1274
1275 /* if it is a section/group name, find it in the cm_categories[] array */
1276
1277 found = 0;
1278 if (strcasestr(arg2, "_section") != (char *)NULL((void *)0)
1279 || strcasestr(arg2, "_group") != (char *)NULL((void *)0)) {
1280 idx = 0;
1281 while (idx < CM_NUM_DATA_CATEGORIES16) {
1282 sscanf(cm_categories[idx], "%s %d %d", catName, &fromIdx,
1283 &toIdx);
1284 idx++;
1285 if (strcasecmp(arg2, catName) == 0) {
1286 found = 1;
1287 break;
1288 }
1289 }
1290
1291 if (!found) { /* typo in section/group name */
1292 fprintf(stderr__stderrp,
1293 "[ %s ] Could not find section/group name %s\n", rn,
1294 arg2);
1295 return (-1);
1296 }
1297 }
1298
1299 /* if it is a group name, read its start/end indices and fill in the
1300 * cm_Display_map[]. */
1301
1302 if (strcasestr(arg2, "_group") != (char *)NULL((void *)0)) {
1303
1304 if (fromIdx < 0 || toIdx < 0 || fromIdx > NUM_CM_STAT_ENTRIES571
1305 || toIdx > NUM_CM_STAT_ENTRIES571)
1306 return (-10);
1307 for (j = fromIdx; j <= toIdx; j++) {
1308 if (!cm_showFlags[j]) {
1309 cm_Display_map[cm_DisplayItems_count] = j;
1310 cm_DisplayItems_count++;
1311 cm_showFlags[j] = 1;
1312 }
1313 if (cm_DisplayItems_count > NUM_CM_STAT_ENTRIES571) {
1314 fprintf(stderr__stderrp, "[ %s ] cm_DisplayItems_count ovf\n", rn);
1315 return (-11);
1316 }
1317 }
1318 } else
1319 /* if it is a section name, get the count of number of groups in it and
1320 * for each group fill in the start/end indices in the cm_Display_map[] */
1321
1322 if (strcasestr(arg2, "_section") != (char *)NULL((void *)0)) {
1323 /* fromIdx is actually the number of groups in thi section */
1324 numGroups = fromIdx;
1325 /* for each group in section */
1326 while (idx < CM_NUM_DATA_CATEGORIES16 && numGroups) {
1327 sscanf(cm_categories[idx], "%s %d %d", catName, &fromIdx,
1328 &toIdx);
1329
1330 if (strcasestr(catName, "_group") != NULL((void *)0)) {
1331 if (fromIdx < 0 || toIdx < 0
1332 || fromIdx > NUM_CM_STAT_ENTRIES571
1333 || toIdx > NUM_CM_STAT_ENTRIES571)
1334 return (-12);
1335 for (j = fromIdx; j <= toIdx; j++) {
1336 if (!cm_showFlags[j]) {
1337 cm_Display_map[cm_DisplayItems_count] = j;
1338 cm_DisplayItems_count++;
1339 cm_showFlags[j] = 1;
1340 }
1341 if (cm_DisplayItems_count > NUM_CM_STAT_ENTRIES571) {
1342 fprintf(stderr__stderrp,
1343 "[ %s ] cm_DisplayItems_count ovf\n", rn);
1344 return (-13);
1345 }
1346 }
1347 } else {
1348 fprintf(stderr__stderrp, "[ %s ] Error parsing groups for %s\n",
1349 rn, arg2);
1350 return (-15);
1351 }
1352 idx++;
1353 numGroups--;
1354 } /* for each group in section */
1355 } else { /* it is a variable name */
1356
1357 for (i = 0; i < NUM_CM_STAT_ENTRIES571; i++) {
1358 if (strcasecmp(arg2, cm_varNames[i]) == 0) {
1359 if (!cm_showFlags[i]) {
1360 cm_Display_map[cm_DisplayItems_count] = i;
1361 cm_DisplayItems_count++;
1362 cm_showFlags[i] = 1;
1363 }
1364 if (cm_DisplayItems_count >= NUM_CM_STAT_ENTRIES571) {
1365 fprintf(stderr__stderrp, "[ %s ] cm_DisplayItems_count ovf\n",
1366 rn);
1367 return (-20);
1368 }
1369 found = 1;
1370 }
1371 }
1372 if (!found) { /* typo in section/group name */
1373 fprintf(stderr__stderrp, "[ %s ] Could not find variable name %s\n",
1374 rn, arg2);
1375 return (-1);
1376 }
1377 } /* its a variable name */
1378
1379 }
1380 /* it is an cm entry */
1381 return (0);
1382} /* parse_showEntry */
1383
1384
1385/*-----------------------------------------------------------------------
1386 * process_config_file()
1387 *
1388 * Description:
1389 * Parse config file entries in two passes. In the first pass:
1390 * - the syntax of all the entries is checked
1391 * - host names are noted and the FSnamesList and CMnamesList
1392 * constructed.
1393 * - a count of the global thresholds and local thresholds of
1394 * each host are counted.
1395 * - "show" entries are processed.
1396 * In the second pass:
1397 * - thresholds are stored
1398 *
1399 * Returns:
1400 * Success: 0
1401 * Failure: Exits afsmonitor showing error and line.
1402 *----------------------------------------------------------------------*/
1403
1404int
1405process_config_file(char *a_config_filename)
1406{ /* process_config_file() */
1407 static char rn[] = "process_config_file"; /* routine name */
1408 FILE *configFD; /* config file descriptor */
1409 char line[4 * CFG_STR_LEN80]; /* a line of config file */
1410 char opcode[CFG_STR_LEN80]; /* specifies type of config entry */
1411 char arg1[CFG_STR_LEN80]; /* hostname or qualifier (fs/cm?) */
1412 char arg2[CFG_STR_LEN80]; /* threshold variable */
1413 char arg3[CFG_STR_LEN80]; /* threshold value */
1414 char arg4[CFG_STR_LEN80]; /* user's handler */
1415 struct afsmon_hostEntry *curr_host;
1416 struct hostent *he; /* hostentry to resolve host name */
1417 char *handlerPtr; /* ptr to pass theresh handler string */
1418 int code = 0; /* error code */
1419 int linenum = 0; /* config file line number */
1420 int error_in_config; /* syntax errors in config file ?? */
1421 int i;
1422 int numBytes;
1423
1424 if (afsmon_debug) {
1425 fprintf(debugFD, "[ %s ] Called, a_config_filename= %s\n", rn,
1426 a_config_filename);
1427 fflush(debugFD);
1428 }
1429
1430 /* open config file */
1431
1432 configFD = fopen(a_config_filename, "r");
1433 if (configFD == (FILE *) 0) {
1434 fprintf(stderr__stderrp, "Failed to open config file %s \n",
1435 a_config_filename);
1436 if (afsmon_debug) {
1437 fprintf(debugFD, "[ %s ] Failed to open config file %s \n", rn,
1438 a_config_filename);
1439 }
1440 afsmon_Exit(5);
1441 }
1442
1443
1444 /* parse config file */
1445
1446 /* We process the config file in two passes. In the first pass we check
1447 * for correct syntax and for valid entries and also keep count of the
1448 * number of servers and thresholds to monitor. This the data strctures
1449 * can be arrays instead of link lists since we would know their sizes. */
1450
1451 /* First Pass */
1452
1453 numFS = 0;
1454 numCM = 0;
1455 error_in_config = 0; /* flag to note if config file has syntax errors */
1456
1457 while ((fgets(line, CFG_STR_LEN80, configFD)) != NULL((void *)0)) {
1458 opcode[0] = 0;
1459 arg1[0] = 0;
1460 arg2[0] = 0;
1461 arg3[0] = 0;
1462 arg4[0] = 0;
1463 sscanf(line, "%s %s %s %s %s", opcode, arg1, arg2, arg3, arg4);
1464 linenum++;
1465 /* skip blank lines and comment lines */
1466 if ((strlen(opcode) == 0) || line[0] == '#')
1467 continue;
1468
1469 if ((strcasecmp(opcode, "fs") == 0)
1470 || (strcasecmp(opcode, "cm")) == 0) {
1471 code = parse_hostEntry(line);
1472 } else if ((strcasecmp(opcode, "thresh")) == 0) {
1473 code = parse_threshEntry(line);
1474 } else if ((strcasecmp(opcode, "show")) == 0) {
1475 code = parse_showEntry(line);
1476 } else {
1477 fprintf(stderr__stderrp, "[ %s ] Unknown opcode %s\n", rn, opcode);
1478 code = 1;
1479 }
1480
1481 if (code) {
1482 fprintf(stderr__stderrp, "[ %s ] Error in line:\n %d: %s\n", rn, linenum,
1483 line);
1484 error_in_config = 1;
1485 }
1486 }
1487
1488 if (error_in_config)
1489 afsmon_Exit(10);
1490
1491 if (afsmon_debug) {
1492 fprintf(debugFD, "Global FS thresholds count = %d\n",
1493 global_fsThreshCount);
1494 fprintf(debugFD, "Global CM thresholds count = %d\n",
1495 global_cmThreshCount);
1496 fflush(debugFD);
1497 }
1498
1499 /* the threshold count of all hosts in increased by 1 for each global
1500 * threshold. If one of the hosts has a local threshold for the same
1501 * variable it would end up being counted twice. whats a few bytes of memory
1502 * wasted anyway ? */
1503
1504 if (global_fsThreshCount) {
1505 curr_host = FSnameList;
1506 for (i = 0; i < numFS; i++) {
1507 curr_host->numThresh += global_fsThreshCount;
1508 curr_host = curr_host->next;
1509 }
1510 }
1511 if (global_cmThreshCount) {
1512 curr_host = CMnameList;
1513 for (i = 0; i < numCM; i++) {
1514 curr_host->numThresh += global_cmThreshCount;
1515 curr_host = curr_host->next;
1516 }
1517 }
1518
1519
1520 /* make sure we have something to monitor */
1521 if (numFS == 0 && numCM == 0) {
1522 fprintf(stderr__stderrp,
1523 "\nConfig file must specify atleast one File Server or Cache Manager host to monitor.\n");
1524 fclose(configFD);
1525 afsmon_Exit(15);
1526 }
1527
1528 /* Second Pass */
1529
1530 fseek(configFD, 0, 0); /* seek to the beginning */
1531
1532
1533 /* allocate memory for threshold lists */
1534 curr_host = FSnameList;
1535 for (i = 0; i < numFS; i++) {
1536 if (curr_host->hostName[0] == '\0') {
1537 fprintf(stderr__stderrp, "[ %s ] Programming error 4\n", rn);
1538 afsmon_Exit(20);
1539 }
1540 if (curr_host->numThresh) {
1541 numBytes = curr_host->numThresh * sizeof(struct Threshold);
1542 curr_host->thresh = (struct Threshold *)malloc(numBytes);
1543 if (curr_host->thresh == NULL((void *)0)) {
1544 fprintf(stderr__stderrp, "[ %s ] Memory Allocation error 1", rn);
1545 afsmon_Exit(25);
1546 }
1547 memset(curr_host->thresh, 0, numBytes);
1548 }
1549 curr_host = curr_host->next;;
1550 }
1551
1552 curr_host = CMnameList;
1553 for (i = 0; i < numCM; i++) {
1554 if (curr_host->hostName[0] == '\0') {
1555 fprintf(stderr__stderrp, "[ %s ] Programming error 5\n", rn);
1556 afsmon_Exit(30);
1557 }
1558 if (curr_host->numThresh) {
1559 numBytes = curr_host->numThresh * sizeof(struct Threshold);
1560 curr_host->thresh = (struct Threshold *)malloc(numBytes);
1561 if (curr_host->thresh == NULL((void *)0)) {
1562 fprintf(stderr__stderrp, "[ %s ] Memory Allocation error 2", rn);
1563 afsmon_Exit(35);
1564 }
1565 memset(curr_host->thresh, 0, numBytes);
1566 }
1567 curr_host = curr_host->next;;
1568 }
1569
1570
1571 opcode[0] = 0;
1572 arg1[0] = 0;
1573 arg2[0] = 0;
1574 arg3[0] = 0;
1575 arg4[0] = 0;
1576 last_fsHost[0] = '\0';
1577 last_cmHost[0] = '\0';
1578 linenum = 0;
1579 while ((fgets(line, CFG_STR_LEN80, configFD)) != NULL((void *)0)) {
1580 opcode[0] = 0;
1581 arg1[0] = 0;
1582 arg2[0] = 0;
1583 arg3[0] = 0;
1584 arg4[0] = 0;
1585 sscanf(line, "%s %s %s %s %s", opcode, arg1, arg2, arg3, arg4);
1586 linenum++;
1587
1588 /* if we have a host entry, remember the host name */
1589 if (strcasecmp(opcode, "fs") == 0) {
1590 he = GetHostByName(arg1);
1591 strncpy(last_fsHost, he->h_name, HOST_NAME_LEN80);
1592 } else if (strcasecmp(opcode, "cm") == 0) {
1593 he = GetHostByName(arg1);
1594 strncpy(last_cmHost, he->h_name, HOST_NAME_LEN80);
1595 } else if (strcasecmp(opcode, "thresh") == 0) {
1596 /* if we have a threshold handler it may have arguments
1597 * and the sscanf() above would not get them, so do the
1598 * following */
1599 if (strlen(arg4)) {
1600 handlerPtr = line;
1601 /* now skip over 4 words - this is done by first
1602 * skipping leading blanks then skipping a word */
1603 for (i = 0; i < 4; i++) {
1604 while (isspace(*handlerPtr)__sbistype((*handlerPtr), 0x00004000L))
1605 handlerPtr++;
1606 while (!isspace(*handlerPtr)__sbistype((*handlerPtr), 0x00004000L))
1607 handlerPtr++;
1608 }
1609 while (isspace(*handlerPtr)__sbistype((*handlerPtr), 0x00004000L))
1610 handlerPtr++;
1611 /* we how have a pointer to the start of the handler
1612 * name & args */
1613 } else
1614 handlerPtr = arg4; /* empty string */
1615
1616
1617 if (strcasecmp(arg1, "fs") == 0)
1618 code = store_threshold(1, /* 1 = fs */
1619 arg2, arg3, handlerPtr);
1620
1621 else if (strcasecmp(arg1, "cm") == 0)
1622 code = store_threshold(2, /* 2 = fs */
1623 arg2, arg3, handlerPtr);
1624
1625 else {
1626 fprintf(stderr__stderrp, "[ %s ] Programming error 6\n", rn);
1627 afsmon_Exit(40);
1628 }
1629 if (code) {
1630 fprintf(stderr__stderrp, "[ %s ] Failed to store threshold\n", rn);
1631 fprintf(stderr__stderrp, "[ %s ] Error processing line:\n%d: %s", rn,
1632 linenum, line);
1633 afsmon_Exit(45);
1634 }
1635 }
1636 }
1637
1638
1639 fclose(configFD);
1640 return (0);
1641}
1642
1643/*-----------------------------------------------------------------------
1644 * Print_FS_CB
1645 *
1646 * Description:
1647 * Debug routine.
1648 * Print the File Server circular buffer.
1649 *
1650 * Returns:
1651 * Nothing.
1652 *----------------------------------------------------------------------*/
1653
1654void
1655Print_FS_CB(void)
1656{ /* Print_FS_CB() */
1657
1658 struct afsmon_fs_Results_list *fslist;
1659 int i;
1660 int j;
1661 int k;
1662
1663 /* print valid info in the fs CB */
1664
1665 if (afsmon_debug) {
1666 fprintf(debugFD,
1667 "==================== FS Buffer ========================\n");
1668 fprintf(debugFD, "afsmon_fs_curr_CBindex = %d\n",
1669 afsmon_fs_curr_CBindex);
1670 fprintf(debugFD, "afsmon_fs_curr_probeNum = %d\n\n",
1671 afsmon_fs_curr_probeNum);
1672
1673 for (i = 0; i < num_bufSlots; i++) {
1674 fprintf(debugFD, "\t--------- slot %d ----------\n", i);
1675 fslist = afsmon_fs_ResultsCB[i].list;
1676 j = 0;
1677 while (j < numFS) {
1678 for (k = 0; k < MAX_NUM_FS_COLLECTIONS2; k++) {
1679 if (!(fslist->empty[k])) {
1680 fprintf(debugFD, "\t %d) probeNum = %d host = %s cn = %d",
1681 j,
1682 fslist->fsResults[k]->probeNum,
1683 fslist->fsResults[k]->connP->hostName,
1684 fslist->fsResults[k]->collectionNumber);
1685 if (fslist->fsResults[k]->probeOK)
1686 fprintf(debugFD, " NOTOK\n");
1687 else
1688 fprintf(debugFD, " OK\n");
1689 } else
1690 fprintf(debugFD, "\t %d) -- empty --\n", j);
1691 }
1692 fslist = fslist->next;
1693 j++;
1694 }
1695 if (fslist != (struct afsmon_fs_Results_list *)0)
1696 fprintf(debugFD, "dangling last next ptr fs CB\n");
1697 }
1698 }
1699} /* Print_FS_CB() */
1700
1701/*-----------------------------------------------------------------------
1702 * save_FS_results_inCB()
1703 *
1704 * Description:
1705 * Saves the results of the latest FS probe in the fs circular
1706 * buffers. If the current probe cycle is in progress the contents
1707 * of xstat_fs_Results are copied to the end of the list of results
1708 * in the current slot (pointed to by afsmon_fs_curr_CBindex). If
1709 * a new probe cycle has started the next slot in the circular buffer
1710 * is initialized and the results copied. Note that the Rx related
1711 * information available in xstat_fs_Results is not copied.
1712 *
1713 * Returns:
1714 * Success: 0
1715 * Failure: Exits afsmonitor.
1716 *----------------------------------------------------------------------*/
1717int
1718save_FS_results_inCB(int a_newProbeCycle) /* start of a new probe cycle ? */
1719{ /* save_FS_results_inCB() */
1720 static char rn[] = "save_FS_results_inCB"; /* routine name */
1721 struct afsmon_fs_Results_list *tmp_fslist_item; /* temp fs list item */
1722 struct xstat_fs_ProbeResults *tmp_fsPR; /* temp ptr */
1723 int i;
1724 int index;
1725
1726 if (afsmon_debug) {
1727 fprintf(debugFD, "[ %s ] Called, a_newProbeCycle= %d\n", rn,
1728 a_newProbeCycle);
1729 fflush(debugFD);
1730 }
1731
1732 switch (xstat_fs_Results.collectionNumber) {
1733 case AFS_XSTATSCOLL_FULL_PERF_INFO2:
1734 index = 0;
1735 break;
1736 case AFS_XSTATSCOLL_CBSTATS3:
1737 index = 1;
1738 default:
1739 if (index < 0) {
1740 fprintf(stderr__stderrp, "[ %s ] collection number %d is out of range.\n",
1741 rn, xstat_fs_Results.collectionNumber);
1742 afsmon_Exit(51);
1743 }
1744 }
1745
1746 /* If a new probe cycle started, mark the list in the current buffer
1747 * slot empty for resuse. Note that afsmon_fs_curr_CBindex was appropriately
1748 * incremented in afsmon_FS_Handler() */
1749
1750 if (a_newProbeCycle) {
1751 tmp_fslist_item = afsmon_fs_ResultsCB[afsmon_fs_curr_CBindex].list;
1752 for (i = 0; i < numFS; i++) {
1753 tmp_fslist_item->empty[index] = 1;
1754 tmp_fslist_item = tmp_fslist_item->next;
1755 }
1756 }
1757
1758 /* locate last unused item in list */
1759 tmp_fslist_item = afsmon_fs_ResultsCB[afsmon_fs_curr_CBindex].list;
1760 for (i = 0; i < numFS; i++) {
1761 if (tmp_fslist_item->empty[index])
1762 break;
1763 tmp_fslist_item = tmp_fslist_item->next;
1764 }
1765
1766 /* if we could not find one we have an inconsistent list */
1767 if (!tmp_fslist_item->empty[index]) {
1768 fprintf(stderr__stderrp,
1769 "[ %s ] list inconsistency 1. unable to find an empty slot to store results of probenum %d of %s\n",
1770 rn, xstat_fs_Results.probeNum,
1771 xstat_fs_Results.connP->hostName);
1772 afsmon_Exit(50);
1773 }
1774
1775 tmp_fsPR = tmp_fslist_item->fsResults[index];
1776
1777 /* copy hostname and probe number and probe time and probe status.
1778 * if the probe failed return now */
1779
1780 memcpy(tmp_fsPR->connP->hostName, xstat_fs_Results.connP->hostName,
1781 sizeof(xstat_fs_Results.connP->hostName));
1782 tmp_fsPR->probeNum = xstat_fs_Results.probeNum;
1783 tmp_fsPR->probeTime = xstat_fs_Results.probeTime;
1784 tmp_fsPR->probeOK = xstat_fs_Results.probeOK;
1785 if (xstat_fs_Results.probeOK) { /* probeOK = 1 => notOK */
1786 /* we have a nonempty results structure so mark the list item used */
1787 tmp_fslist_item->empty[index] = 0;
1788 return (0);
1789 }
1790
1791 /* copy connection information */
1792 memcpy(&(tmp_fsPR->connP->skt), &(xstat_fs_Results.connP->skt),
1793 sizeof(struct sockaddr_in));
1794
1795 memcpy(tmp_fsPR->connP->hostName, xstat_fs_Results.connP->hostName,
1796 sizeof(xstat_fs_Results.connP->hostName));
1797 tmp_fsPR->collectionNumber = xstat_fs_Results.collectionNumber;
1798
1799 /* copy the probe data information */
1800 tmp_fsPR->data.AFS_CollData_len =
1801 min(xstat_fs_Results.data.AFS_CollData_len,((xstat_fs_Results.data.AFS_CollData_len) > (afsmon_fs_results_length
[index]) ? (afsmon_fs_results_length[index]) : (xstat_fs_Results
.data.AFS_CollData_len))
1802 afsmon_fs_results_length[index])((xstat_fs_Results.data.AFS_CollData_len) > (afsmon_fs_results_length
[index]) ? (afsmon_fs_results_length[index]) : (xstat_fs_Results
.data.AFS_CollData_len))
;
1803 memcpy(tmp_fsPR->data.AFS_CollData_val,
1804 xstat_fs_Results.data.AFS_CollData_val,
1805 tmp_fsPR->data.AFS_CollData_len * sizeof(afs_int32));
1806
1807
1808 /* we have a valid results structure so mark the list item used */
1809 tmp_fslist_item->empty[index] = 0;
1810
1811 /* Print the fs circular buffer */
1812 Print_FS_CB();
1813
1814 return (0);
1815} /* save_FS_results_inCB() */
1816
1817
1818/*-----------------------------------------------------------------------
1819 * fs_Results_ltoa()
1820 *
1821 * Description:
1822 * The results of xstat probes are stored in a string format in
1823 * the arrays curr_fsData and prev_fsData. The information stored in
1824 * prev_fsData is copied to the screen.
1825 * This function converts xstat FS results from longs to strings and
1826 * place them in the given buffer (a pointer to an item in curr_fsData).
1827 * When a probe cycle completes, curr_fsData is copied to prev_fsData
1828 * in afsmon_FS_Hnadler().
1829 *
1830 * Returns:
1831 * Always returns 0.
1832 *----------------------------------------------------------------------*/
1833
1834int
1835fs_Results_ltoa(struct fs_Display_Data *a_fsData, /* target buffer */
1836 struct xstat_fs_ProbeResults *a_fsResults) /* ptr to xstat fs Results */
1837{ /* fs_Results_ltoa */
1838
1839 static char rn[] = "fs_Results_ltoa"; /* routine name */
1840
1841 if (afsmon_debug) {
1842 fprintf(debugFD, "[ %s ] Called, a_fsData= %p, a_fsResults= %p\n", rn,
1843 a_fsData, a_fsResults);
1844 fflush(debugFD);
1845 }
1846
1847 switch (a_fsResults->collectionNumber) {
1848 case AFS_XSTATSCOLL_FULL_PERF_INFO2:
1849 fs_FullPerfs_ltoa(a_fsData, a_fsResults);
1850 break;
1851 case AFS_XSTATSCOLL_CBSTATS3:
1852 fs_CallBackStats_ltoa(a_fsData, a_fsResults);
1853 break;
1854 default:
1855 if (afsmon_debug) {
1856 fprintf(debugFD, "[ %s ] Unexpected collection id %d\n",
1857 rn, a_fsResults->collectionNumber);
1858 }
1859 }
1860
1861 return (0);
1862} /* fs_Results_ltoa */
1863
1864/*-----------------------------------------------------------------------
1865 * fs_FullPerfs_ltoa()
1866 *
1867 * Description:
1868 * Convert the full perf xstat collection from int32s to strings.
1869 *
1870 * Returns:
1871 * Always returns 0.
1872 *----------------------------------------------------------------------*/
1873static int
1874fs_FullPerfs_ltoa(struct fs_Display_Data *a_fsData,
1875 struct xstat_fs_ProbeResults *a_fsResults)
1876{
1877 afs_int32 *srcbuf;
1878 struct fs_stats_FullPerfStats *fullPerfP;
1879 struct fs_stats_FullPerfStats buffer;
1880 int idx;
1881 int i, j;
1882 afs_int32 *tmpbuf;
1883 int code;
1884
1885 /* there are two parts to the xstat FS statistics
1886 * - fullPerfP->overall which give the overall performance statistics, and
1887 * - fullPerfP->det which gives detailed info about file server operation
1888 * execution times */
1889
1890 code = xstat_fs_DecodeFullPerfStats(&fullPerfP,
1891 a_fsResults->data.AFS_CollData_val,
1892 a_fsResults->data.AFS_CollData_len,
1893 &buffer);
1894 if (code) {
1895 /* Not able to decode the full perf stats. Avoid displaying garbage. */
1896 for (i = 0; i < NUM_FS_STAT_ENTRIES(275 + 16); i++) {
1897 sprintf(a_fsData->data[i], "%s", "--");
1898 }
1899 return 0;
1900 }
1901
1902 /* copy overall performance statistics */
1903 srcbuf = (afs_int32 *) & (fullPerfP->overall);
1904 idx = 0;
1905 for (i = 0; i < NUM_XSTAT_FS_AFS_PERFSTATS_LONGS70; i++) {
1906 sprintf(a_fsData->data[idx], "%d", *srcbuf);
1907 idx++;
1908 srcbuf++;
1909 }
1910
1911 /* copy epoch */
1912 srcbuf = (afs_int32 *) & (fullPerfP->det.epoch);
1913 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* epoch */
1914 idx++;
1915
1916 /* copy fs operation timing */
1917
1918 srcbuf = (afs_int32 *) (fullPerfP->det.rpcOpTimes);
1919
1920 for (i = 0; i < FS_STATS_NUM_RPC_OPS28; i++) {
1921 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* numOps */
1922 idx++;
1923 srcbuf++;
1924 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* numSuccesses */
1925 idx++;
1926 srcbuf++;
1927 tmpbuf = srcbuf++; /* sum time */
1928 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1929 idx++;
1930 srcbuf++;
1931 tmpbuf = srcbuf++; /* sqr time */
1932 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1933 idx++;
1934 srcbuf++;
1935 tmpbuf = srcbuf++; /* min time */
1936 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1937 idx++;
1938 srcbuf++;
1939 tmpbuf = srcbuf++; /* max time */
1940 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1941 idx++;
1942 srcbuf++;
1943 }
1944
1945 /* copy fs transfer timings */
1946
1947 srcbuf = (afs_int32 *) (fullPerfP->det.xferOpTimes);
1948 for (i = 0; i < FS_STATS_NUM_XFER_OPS2; i++) {
1949 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* numOps */
1950 idx++;
1951 srcbuf++;
1952 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* numSuccesses */
1953 idx++;
1954 srcbuf++;
1955 tmpbuf = srcbuf++; /* sum time */
1956 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1957 idx++;
1958 srcbuf++;
1959 tmpbuf = srcbuf++; /* sqr time */
1960 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1961 idx++;
1962 srcbuf++;
1963 tmpbuf = srcbuf++; /* min time */
1964 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1965 idx++;
1966 srcbuf++;
1967 tmpbuf = srcbuf++; /* max time */
1968 sprintf(a_fsData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
1969 idx++;
1970 srcbuf++;
1971 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* sum bytes */
1972 idx++;
1973 srcbuf++;
1974 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* min bytes */
1975 idx++;
1976 srcbuf++;
1977 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* max bytes */
1978 idx++;
1979 srcbuf++;
1980 for (j = 0; j < FS_STATS_NUM_XFER_BUCKETS9; j++) {
1981 sprintf(a_fsData->data[idx], "%d", *srcbuf); /* bucket[j] */
1982 idx++;
1983 srcbuf++;
1984 }
1985 }
1986
1987 return (0);
1988}
1989
1990/*-----------------------------------------------------------------------
1991 * fs_CallBackStats_ltoa()
1992 *
1993 * Description:
1994 * Convert the callback counter xstat collection from
1995 * int32s to strings.
1996 *
1997 * Returns:
1998 * Always returns 0.
1999 *----------------------------------------------------------------------*/
2000
2001static int
2002fs_CallBackStats_ltoa(struct fs_Display_Data *a_fsData,
2003 struct xstat_fs_ProbeResults *a_fsResults)
2004{
2005 int idx;
2006 int i;
2007 int len = a_fsResults->data.AFS_CollData_len;
2008 afs_int32 *val = a_fsResults->data.AFS_CollData_val;
2009
2010 /* place callback stats after the full perf stats */
2011 idx = NUM_FS_FULLPERF_ENTRIES275;
2012 for (i=0; i < len && i < NUM_FS_CB_ENTRIES16; i++) {
2013 sprintf(a_fsData->data[idx++], "%u", val[i]);
2014 }
2015 return 0;
2016}
2017
2018/*-----------------------------------------------------------------------
2019 * execute_thresh_handler()
2020 *
2021 * Description:
2022 * Execute a threshold handler. An agrv[] array of pointers is
2023 * constructed from the given data. A child process is forked
2024 * which immediately calls afsmon_Exit() with indication that a
2025 * threshold handler is to be exec'ed insted of exiting.
2026 *
2027 * Returns:
2028 * Success: 0
2029 * Failure: Afsmonitor exits if threshold handler has more than 20 args.
2030 *----------------------------------------------------------------------*/
2031
2032int
2033execute_thresh_handler(char *a_handler, /* ptr to handler function + args */
2034 char *a_hostName, /* host name for which threshold crossed */
2035 int a_hostType, /* fs or cm ? */
2036 char *a_threshName, /* threshold variable name */
2037 char *a_threshValue, /* threshold value */
2038 char *a_actValue) /* actual value */
2039{ /* execute_thresh_handler */
2040
2041 static char rn[] = "execute_thresh_handler";
2042 char fileName[256]; /* file name to execute */
2043 int i;
2044 char *ch;
2045 int argNum;
2046 int anotherArg; /* boolean used to flag if another arg is available */
2047
2048 if (afsmon_debug) {
2049 fprintf(debugFD,
2050 "[ %s ] Called, a_handler= %s, a_hostName= %s, a_hostType= %d, a_threshName= %s, a_threshValue= %s, a_actValue= %s\n",
2051 rn, a_handler, a_hostName, a_hostType, a_threshName,
2052 a_threshValue, a_actValue);
2053 fflush(debugFD);
2054 }
2055
2056
2057 /* get the filename to execute - the first argument */
2058 sscanf(a_handler, "%s", fileName);
2059
2060 /* construct the contents of *argv[] */
2061
2062 strncpy(fsHandler_args[0], fileName, 256);
2063 strncpy(fsHandler_args[1], a_hostName, HOST_NAME_LEN80);
2064 if (a_hostType == FS1)
2065 strcpy(fsHandler_args[2], "fs");
2066 else
2067 strcpy(fsHandler_args[2], "cm");
2068 strncpy(fsHandler_args[3], a_threshName, THRESH_VAR_NAME_LEN80);
2069 strncpy(fsHandler_args[4], a_threshValue, THRESH_VAR_LEN16);
2070 strncpy(fsHandler_args[5], a_actValue, THRESH_VAR_LEN16);
2071
2072
2073 argNum = 6;
2074 anotherArg = 1;
2075 ch = a_handler;
2076
2077 /* we have already extracted the file name so skip to the 1st arg */
2078 while (isspace(*ch)__sbistype((*ch), 0x00004000L)) /* leading blanks */
2079 ch++;
2080 while (!isspace(*ch)__sbistype((*ch), 0x00004000L) && *ch != '\0') /* handler filename */
2081 ch++;
2082
2083 while (*ch != '\0') {
2084 if (isspace(*ch)__sbistype((*ch), 0x00004000L)) {
2085 anotherArg = 1;
2086 } else if (anotherArg) {
2087 anotherArg = 0;
2088 sscanf(ch, "%s", fsHandler_args[argNum]);
2089 argNum++;
2090 }
2091 ch++;
2092 if (argNum >= 20) {
2093 sprintf(errMsg,
2094 "Threshold handlers cannot have more than 20 arguments\n");
2095 afsmon_Exit(55);
2096 }
2097
2098 }
2099
2100 fsHandler_argv[argNum] = NULL((void *)0);
2101 for (i = 0; i < argNum; i++)
2102 fsHandler_argv[i] = fsHandler_args[i];
2103
2104
2105 /* exec the threshold handler */
2106
2107 if (fork() == 0) {
2108 exec_fsThreshHandler = 1;
2109 afsmon_Exit(60);
2110 }
2111
2112 return (0);
2113} /* execute_thresh_handler */
2114
2115
2116
2117/*-----------------------------------------------------------------------
2118 * check_fs_thresholds()
2119 *
2120 * Description:
2121 * Checks the thresholds and sets the overflow flag. Recall that the
2122 * thresholds for each host are stored in the hostEntry lists
2123 * [fs/cm]nameList arrays. The probe results are passed to this
2124 * function in the display-ready format - ie., as strings. Though
2125 * this looks stupid the overhead incurred in converting the strings
2126 * back to floats and comparing them is insignificant and
2127 * programming is easier this way.
2128 * The threshold flags are a part of the display structures
2129 * curr_[fs/cm]Data.
2130 *
2131 * Returns:
2132 * 0
2133 *----------------------------------------------------------------------*/
2134
2135int
2136check_fs_thresholds(struct afsmon_hostEntry *a_hostEntry, /* ptr to hostEntry */
2137 struct fs_Display_Data *a_Data) /* ptr to fs data to be displayed */
2138{ /* check_fs_thresholds */
2139
2140 static char rn[] = "check_fs_thresholds";
2141 struct Threshold *threshP;
2142 double tValue; /* threshold value */
2143 double pValue; /* probe value */
2144 int i;
2145 int idx;
2146 int count; /* number of thresholds exceeded */
2147
2148 if (afsmon_debug) {
2149 fprintf(debugFD, "[ %s ] Called, a_hostEntry= %p, a_Data= %p\n", rn,
2150 a_hostEntry, a_Data);
2151 fflush(debugFD);
2152 }
2153
2154 if (a_hostEntry->numThresh == 0) {
2155 /* store in ovf count ?? */
2156 return (0);
2157 }
2158
2159 count = 0;
2160 threshP = a_hostEntry->thresh;
2161 for (i = 0; i < a_hostEntry->numThresh; i++) {
2162 if (threshP->itemName[0] == '\0') {
2163 threshP++;
2164 continue;
2165 }
2166 idx = threshP->index; /* positional index to the data array */
2167 tValue = atof(threshP->threshVal); /* threshold value */
2168 pValue = atof(a_Data->data[idx]); /* probe value */
2169 if (pValue > tValue) {
2170
2171 if (afsmon_debug) {
2172 fprintf(debugFD,
2173 "[ %s ] fs = %s, thresh ovf for %s, threshold= %s, probevalue= %s\n",
2174 rn, a_hostEntry->hostName, threshP->itemName,
2175 threshP->threshVal, a_Data->data[idx]);
2176 fflush(debugFD);
2177 }
2178 /* if the threshold is crossed, call the handler function
2179 * only if this was a transition -ie, if the threshold was
2180 * crossed in the last probe too just count & keep quite! */
2181
2182 if (!a_Data->threshOvf[idx]) {
2183 a_Data->threshOvf[idx] = 1;
2184 /* call the threshold handler if provided */
2185 if (threshP->handler[0] != '\0') {
2186 if (afsmon_debug) {
2187 fprintf(debugFD, "[ %s ] Calling ovf handler %s\n",
2188 rn, threshP->handler);
2189 fflush(debugFD);
2190 }
2191 execute_thresh_handler(threshP->handler, a_Data->hostName,
2192 FS1, threshP->itemName,
2193 threshP->threshVal,
2194 a_Data->data[idx]);
2195 }
2196 }
2197
2198 count++;
2199 } else
2200 /* in case threshold was previously crossed, blank it out */
2201 a_Data->threshOvf[idx] = 0;
2202 threshP++;
2203 }
2204 /* store the overflow count */
2205 a_Data->ovfCount = count;
2206
2207 return (0);
2208} /* check_fs_thresholds */
2209
2210
2211/*-----------------------------------------------------------------------
2212 * save_FS_data_forDisplay()
2213 *
2214 * Description:
2215 * Does the following:
2216 * - if the probe number changed (ie, a cycle completed) curr_fsData
2217 * is copied to prev_fsData, curr_fsData zeroed and refresh the
2218 * overview screen and file server screen with the new data.
2219 * - store the results of the current probe from xstat_fs_Results into
2220 * curr_fsData. ie., convert longs to strings.
2221 * - check the thresholds
2222 *
2223 * Returns:
2224 * Success: 0
2225 * Failure: Exits afsmonitor.
2226 *----------------------------------------------------------------------*/
2227
2228int
2229save_FS_data_forDisplay(struct xstat_fs_ProbeResults *a_fsResults)
2230{ /* save_FS_data_forDisplay */
2231
2232 static char rn[] = "save_FS_data_forDisplay"; /* routine name */
2233 struct fs_Display_Data *curr_fsDataP; /* tmp ptr to curr_fsData */
2234 struct fs_Display_Data *prev_fsDataP; /* tmp ptr to prev_fsData */
2235 struct afsmon_hostEntry *curr_host;
2236 static int results_Received = 0; /* number of probes reveived in
2237 * the current cycle. If this is equal to numFS we got all
2238 * the data we want in this cycle and can now display it */
2239 int numBytes;
2240 int okay;
2241 int i;
2242 int code;
2243 int done;
2244
2245
2246 if (afsmon_debug) {
2247 fprintf(debugFD, "[ %s ] Called, a_fsResults= %p\n", rn, a_fsResults);
2248 fflush(debugFD);
2249 }
2250
2251 /* store results in the display array */
2252
2253 okay = 0;
2254 curr_fsDataP = curr_fsData;
2255 for (i = 0; i < numFS; i++) {
2256 if ((strcasecmp(curr_fsDataP->hostName, a_fsResults->connP->hostName))
2257 == 0) {
2258 okay = 1;
2259 break;
2260 }
2261 curr_fsDataP++;
2262 }
2263
2264 if (!okay) {
2265 fprintf(stderr__stderrp,
2266 "[ %s ] Could not insert FS probe results for host %s in fs display array\n",
2267 rn, a_fsResults->connP->hostName);
2268 afsmon_Exit(65);
2269 }
2270
2271 /* Check the status of the probe. If it succeeded, we store its
2272 * results in the display data structure. If it failed we only mark
2273 * the failed status in the display data structure. */
2274
2275 if (a_fsResults->probeOK) { /* 1 => notOK the xstat results */
2276 curr_fsDataP->probeOK = 0;
2277
2278 /* print the probe status */
2279 if (afsmon_debug) {
2280 fprintf(debugFD, "\n\t\t ----- fs display data ------\n");
2281 fprintf(debugFD, "HostName = %s PROBE FAILED \n",
2282 curr_fsDataP->hostName);
2283 fflush(debugFD);
2284 }
2285
2286 } else { /* probe succeeded, update display data structures */
2287 curr_fsDataP->probeOK = 1;
2288
2289 /* convert longs to strings and place them in curr_fsDataP */
2290 fs_Results_ltoa(curr_fsDataP, a_fsResults);
2291
2292 /* compare with thresholds and set the overflow flags.
2293 * note that the threshold information is in the hostEntry structure and
2294 * each threshold item has a positional index associated with it */
2295
2296 /* locate the hostEntry for this host */
2297 done = 0;
2298 curr_host = FSnameList;
2299 for (i = 0; i < numFS; i++) {
2300 if (strcasecmp(curr_host->hostName, a_fsResults->connP->hostName)
2301 == 0) {
2302 done = 1;
2303 break;
2304 }
2305 curr_host = curr_host->next;;
2306 }
2307 if (!done)
2308 afsmon_Exit(70);
2309
2310 code = check_fs_thresholds(curr_host, curr_fsDataP);
2311 if (code) {
2312 fprintf(stderr__stderrp, "[ %s ] Error in checking thresholds\n", rn);
2313 afsmon_Exit(75);
2314 }
2315
2316 /* print the info we just saved */
2317
2318 if (afsmon_debug) {
2319 fprintf(debugFD, "\n\t\t ----- fs display data ------\n");
2320 fprintf(debugFD, "HostName = %s\n", curr_fsDataP->hostName);
2321 for (i = 0; i < NUM_FS_STAT_ENTRIES(275 + 16); i++)
2322 fprintf(debugFD, "%20s %30s %s\n", curr_fsDataP->data[i],
2323 fs_varNames[i],
2324 curr_fsDataP->threshOvf[i] ? "(ovf)" : "");
2325
2326 fprintf(debugFD, "\t\t--------------------------------\n\n");
2327 fflush(debugFD);
2328 }
2329
2330 } /* the probe succeeded, so we store the data in the display structure */
2331
2332
2333 /* if we have received a reply from all the hosts for this probe cycle,
2334 * it is time to display the data */
2335
2336 results_Received++;
2337 if (results_Received == numFS * num_fs_collections) {
2338 results_Received = 0;
2339
2340 if (afsmon_fs_curr_probeNum != afsmon_fs_prev_probeNum + 1) {
2341 sprintf(errMsg, "[ %s ] Probe number %d missed! \n", rn,
2342 afsmon_fs_prev_probeNum + 1);
2343 afsmon_Exit(80);
2344 } else
2345 afsmon_fs_prev_probeNum++;
2346
2347 /* backup the display data of the probe cycle that just completed -
2348 * ie., store curr_fsData in prev_fsData */
2349
2350 memcpy((char *)prev_fsData, (char *)curr_fsData,
2351 (numFS * sizeof(struct fs_Display_Data)));
2352
2353
2354 /* initialize curr_fsData but retain the threshold flag information.
2355 * The previous state of threshold flags is used in check_fs_thresholds() */
2356
2357 numBytes = NUM_FS_STAT_ENTRIES(275 + 16) * FS_STAT_STRING_LEN14;
2358 curr_fsDataP = curr_fsData;
2359 for (i = 0; i < numFS; i++) {
2360 curr_fsDataP->probeOK = 0;
2361 curr_fsDataP->ovfCount = 0;
2362 memset(curr_fsDataP->data, 0, numBytes);
2363 curr_fsDataP++;
2364 }
2365
2366
2367 /* prev_fsData now contains all the information for the probe cycle
2368 * that just completed. Now count the number of threshold overflows for
2369 * use in the overview screen */
2370
2371 prev_fsDataP = prev_fsData;
2372 num_fs_alerts = 0;
2373 numHosts_onfs_alerts = 0;
2374 for (i = 0; i < numFS; i++) {
2375 if (!prev_fsDataP->probeOK) { /* if probe failed */
2376 num_fs_alerts++;
2377 numHosts_onfs_alerts++;
2378 }
2379 if (prev_fsDataP->ovfCount) { /* overflows ?? */
2380 num_fs_alerts += prev_fsDataP->ovfCount;
2381 numHosts_onfs_alerts++;
2382 }
2383 prev_fsDataP++;
2384 }
2385 if (afsmon_debug)
2386 fprintf(debugFD, "Number of FS alerts = %d (on %d hosts)\n",
2387 num_fs_alerts, numHosts_onfs_alerts);
2388
2389 /* flag that the data is now ready to be displayed */
2390 fs_Data_Available = 1;
2391
2392 /* call the Overview frame update routine (update only FS info) */
2393 ovw_refresh(ovw_currPage, OVW_UPDATE_FS1);
2394
2395 /* call the File Servers frame update routine */
2396 fs_refresh(fs_currPage, fs_curr_LCol);
2397
2398 }
2399 /* display data */
2400 return (0);
2401} /* save_FS_data_forDisplay */
2402
2403
2404
2405
2406/*-----------------------------------------------------------------------
2407 * afsmon_FS_Handler()
2408 *
2409 * Description:
2410 * This is the File Server probe Handler. It updates the afsmonitor
2411 * probe counts, fs circular buffer indices and calls the functions
2412 * to process the results of this probe.
2413 *
2414 * Returns:
2415 * Success: 0
2416 * Failure: Exits afsmonitor.
2417 *----------------------------------------------------------------------*/
2418
2419int
2420afsmon_FS_Handler(void)
2421{ /* afsmon_FS_Handler() */
2422 static char rn[] = "afsmon_FS_Handler"; /* routine name */
2423 int newProbeCycle; /* start of new probe cycle ? */
2424 int code; /* return status */
2425
2426
2427 if (afsmon_debug) {
2428 fprintf(debugFD,
2429 "[ %s ] Called, hostName= %s, probeNum= %d, status=%s, collection=%d\n", rn,
2430 xstat_fs_Results.connP->hostName, xstat_fs_Results.probeNum,
2431 xstat_fs_Results.probeOK ? "FAILED" : "OK",
2432 xstat_fs_Results.collectionNumber);
2433 fflush(debugFD);
2434 }
2435
2436
2437 /* print the probe results to output file */
2438 if (afsmon_output) {
2439 code = afsmon_fsOutput(output_filename, afsmon_detOutput);
2440 if (code) {
2441 fprintf(stderr__stderrp,
2442 "[ %s ] output to file %s returned error code=%d\n", rn,
2443 output_filename, code);
2444 }
2445 }
2446
2447 /* Update current probe number and circular buffer index. if current
2448 * probenum changed make sure it is only by 1 */
2449
2450 newProbeCycle = 0;
2451 if (xstat_fs_Results.probeNum != afsmon_fs_curr_probeNum) {
2452 if (xstat_fs_Results.probeNum == afsmon_fs_curr_probeNum + 1) {
2453 afsmon_fs_curr_probeNum++;
2454 newProbeCycle = 1;
2455 if (num_bufSlots)
2456 afsmon_fs_curr_CBindex =
2457 (afsmon_fs_curr_probeNum - 1) % num_bufSlots;
2458 } else {
2459 fprintf(stderr__stderrp, "[ %s ] probe number %d-1 missed\n", rn,
2460 xstat_fs_Results.probeNum);
2461 afsmon_Exit(85);
2462 }
2463 }
2464
2465
2466 /* store the results of this probe in the FS circular buffer */
2467 if (num_bufSlots)
2468 save_FS_results_inCB(newProbeCycle);
2469
2470
2471 /* store the results of the current probe in the fs data display structure.
2472 * if the current probe number changed, swap the current and previous display
2473 * structures. note that the display screen is updated from these structures
2474 * and should start showing the data of the just completed probe cycle */
2475
2476 save_FS_data_forDisplay(&xstat_fs_Results);
2477
2478 return (0);
2479}
2480
2481
2482
2483/*----------------------------------------------------------------------- *
2484 * Print_CM_CB()
2485 *
2486 * Description:
2487 * Debug routine.
2488 * Prints the Cache Manager circular buffer
2489 *----------------------------------------------------------------------*/
2490
2491void
2492Print_CM_CB(void)
2493{ /* Print_CM_CB() */
2494
2495 struct afsmon_cm_Results_list *cmlist;
2496 int i;
2497 int j;
2498 int k;
2499
2500 /* print valid info in the cm CB */
2501
2502 if (afsmon_debug) {
2503 fprintf(debugFD,
2504 "==================== CM Buffer ========================\n");
2505 fprintf(debugFD, "afsmon_cm_curr_CBindex = %d\n",
2506 afsmon_cm_curr_CBindex);
2507 fprintf(debugFD, "afsmon_cm_curr_probeNum = %d\n\n",
2508 afsmon_cm_curr_probeNum);
2509
2510 for (i = 0; i < num_bufSlots; i++) {
2511 fprintf(debugFD, "\t--------- slot %d ----------\n", i);
2512 cmlist = afsmon_cm_ResultsCB[i].list;
2513 j = 0;
2514 while (j < numCM) {
2515 for (k = 0; k < MAX_NUM_CM_COLLECTIONS1; k++) {
2516 if (!cmlist->empty[k]) {
2517 fprintf(debugFD,
2518 "\t %d) probeNum = %d host = %s cn = %d",
2519 j,
2520 cmlist->cmResults[k]->probeNum,
2521 cmlist->cmResults[k]->connP->hostName,
2522 cmlist->cmResults[k]->collectionNumber);
2523 if (cmlist->cmResults[k]->probeOK)
2524 fprintf(debugFD, " NOTOK\n");
2525 else
2526 fprintf(debugFD, " OK\n");
2527 } else
2528 fprintf(debugFD, "\t %d) -- empty --\n", j);
2529 }
2530 cmlist = cmlist->next;
2531 j++;
2532 }
2533 if (cmlist != (struct afsmon_cm_Results_list *)0)
2534 fprintf(debugFD, "dangling last next ptr cm CB\n");
2535 }
2536 }
2537}
2538
2539
2540/*-----------------------------------------------------------------------
2541 * save_CM_results_inCB()
2542 *
2543 * Description:
2544 * Saves the results of the latest CM probe in the cm circular
2545 * buffers. If the current probe cycle is in progress the contents
2546 * of xstat_cm_Results are copied to the end of the list of results
2547 * in the current slot (pointed to by afsmon_cm_curr_CBindex). If
2548 * a new probe cycle has started the next slot in the circular buffer
2549 * is initialized and the results copied. Note that the Rx related
2550 * information available in xstat_cm_Results is not copied.
2551 *
2552 * Returns:
2553 * Success: 0
2554 * Failure: Exits afsmonitor.
2555 *----------------------------------------------------------------------*/
2556
2557int
2558save_CM_results_inCB(int a_newProbeCycle) /* start of new probe cycle ? */
2559{ /* save_CM_results_inCB() */
2560 static char rn[] = "save_CM_results_inCB"; /* routine name */
2561 struct afsmon_cm_Results_list *tmp_cmlist_item; /* temp cm list item */
2562 struct xstat_cm_ProbeResults *tmp_cmPR; /* temp ptr */
2563 int i;
2564 int index;
2565
2566
2567 if (afsmon_debug) {
2568 fprintf(debugFD, "[ %s ] Called, a_newProbeCycle= %d\n", rn,
2569 a_newProbeCycle);
2570 fflush(debugFD);
2571 }
2572
2573 if (xstat_cm_Results.collectionNumber == AFSCB_XSTATSCOLL_FULL_PERF_INFO2) {
2574 index = 0;
2575 } else {
2576 fprintf(stderr__stderrp, "[ %s ] collection number %d is out of range.\n",
2577 rn, xstat_cm_Results.collectionNumber);
2578 afsmon_Exit(91);
2579 }
2580
2581 /* If a new probe cycle started, mark the list in the current buffer
2582 * slot empty for resuse. Note that afsmon_cm_curr_CBindex was appropriately
2583 * incremented in afsmon_CM_Handler() */
2584
2585 if (a_newProbeCycle) {
2586 tmp_cmlist_item = afsmon_cm_ResultsCB[afsmon_cm_curr_CBindex].list;
2587 for (i = 0; i < numCM; i++) {
2588 tmp_cmlist_item->empty[index] = 1;
2589 tmp_cmlist_item = tmp_cmlist_item->next;
2590 }
2591 }
2592
2593 /* locate last unused item in list */
2594 tmp_cmlist_item = afsmon_cm_ResultsCB[afsmon_cm_curr_CBindex].list;
2595 for (i = 0; i < numCM; i++) {
2596 if (tmp_cmlist_item->empty[index])
2597 break;
2598 tmp_cmlist_item = tmp_cmlist_item->next;
2599 }
2600
2601 /* if we could not find one we have an inconsistent list */
2602 if (!tmp_cmlist_item->empty[index]) {
2603 fprintf(stderr__stderrp,
2604 "[ %s ] list inconsistency 1. unable to find an empty slot to store results of probenum %d of %s\n",
2605 rn, xstat_cm_Results.probeNum,
2606 xstat_cm_Results.connP->hostName);
2607 afsmon_Exit(90);
2608 }
2609
2610 tmp_cmPR = tmp_cmlist_item->cmResults[index];
2611
2612 /* copy hostname and probe number and probe time and probe status.
2613 * if the probe failed return now */
2614
2615 memcpy(tmp_cmPR->connP->hostName, xstat_cm_Results.connP->hostName,
2616 sizeof(xstat_cm_Results.connP->hostName));
2617 tmp_cmPR->probeNum = xstat_cm_Results.probeNum;
2618 tmp_cmPR->probeTime = xstat_cm_Results.probeTime;
2619 tmp_cmPR->probeOK = xstat_cm_Results.probeOK;
2620 if (xstat_cm_Results.probeOK) { /* probeOK = 1 => notOK */
2621 /* we have a nonempty results structure so mark the list item used */
2622 tmp_cmlist_item->empty[index] = 0;
2623 return (0);
2624 }
2625
2626
2627 /* copy connection information */
2628 memcpy(&(tmp_cmPR->connP->skt), &(xstat_cm_Results.connP->skt),
2629 sizeof(struct sockaddr_in));
2630
2631 /**** NEED TO COPY rx_connection INFORMATION HERE ******/
2632
2633 memcpy(tmp_cmPR->connP->hostName, xstat_cm_Results.connP->hostName,
2634 sizeof(xstat_cm_Results.connP->hostName));
2635 tmp_cmPR->collectionNumber = xstat_cm_Results.collectionNumber;
2636
2637 /* copy the probe data information */
2638 tmp_cmPR->data.AFSCB_CollData_len =
2639 min(xstat_cm_Results.data.AFSCB_CollData_len,((xstat_cm_Results.data.AFSCB_CollData_len) > (afsmon_cm_results_length
[index]) ? (afsmon_cm_results_length[index]) : (xstat_cm_Results
.data.AFSCB_CollData_len))
2640 afsmon_cm_results_length[index])((xstat_cm_Results.data.AFSCB_CollData_len) > (afsmon_cm_results_length
[index]) ? (afsmon_cm_results_length[index]) : (xstat_cm_Results
.data.AFSCB_CollData_len))
;
2641 memcpy(tmp_cmPR->data.AFSCB_CollData_val,
2642 xstat_cm_Results.data.AFSCB_CollData_val,
2643 tmp_cmPR->data.AFSCB_CollData_len * sizeof(afs_int32));
2644
2645
2646 /* we have a valid results structure so mark the list item used */
2647 tmp_cmlist_item->empty[index] = 0;
2648
2649 /* print the stored info - to make sure we copied it right */
2650 /* Print_cm_FullPerfInfo(tmp_cmPR); */
2651 /* Print the cm circular buffer */
2652 Print_CM_CB();
2653 return (0);
2654} /* save_CM_results_inCB */
2655
2656
2657
2658/*-----------------------------------------------------------------------
2659 * cm_Results_ltoa()
2660 *
2661 * Description:
2662 * The results of xstat probes are stored in a string format in
2663 * the arrays curr_cmData and prev_cmData. The information stored in
2664 * prev_cmData is copied to the screen.
2665 * This function converts xstat FS results from longs to strings and
2666 * places them in the given buffer (a pointer to an item in curr_cmData).
2667 * When a probe cycle completes, curr_cmData is copied to prev_cmData
2668 * in afsmon_CM_Handler().
2669 *
2670 * Returns:
2671 * Always returns 0.
2672 *----------------------------------------------------------------------*/
2673
2674int
2675cm_Results_ltoa(struct cm_Display_Data *a_cmData, /* target buffer */
2676 struct xstat_cm_ProbeResults *a_cmResults) /* ptr to xstat cm Results */
2677{ /* cm_Results_ltoa */
2678
2679 static char rn[] = "cm_Results_ltoa"; /* routine name */
2680 struct afs_stats_CMFullPerf *fullP; /* ptr to complete CM stats */
2681 afs_int32 *srcbuf;
2682 afs_int32 *tmpbuf;
2683 int i, j;
2684 int idx;
2685 afs_int32 numLongs;
2686
2687 if (afsmon_debug) {
2688 fprintf(debugFD, "[ %s ] Called, a_cmData= %p, a_cmResults= %p\n", rn,
2689 a_cmData, a_cmResults);
2690 fflush(debugFD);
2691 }
2692
2693
2694 fullP = (struct afs_stats_CMFullPerf *)
2695 (a_cmResults->data.AFSCB_CollData_val);
2696
2697 /* There are 4 parts to CM statistics
2698 * - Overall performance statistics (including up/down statistics)
2699 * - This CMs FS RPC operations info
2700 * - This CMs FS RPC errors info
2701 * - This CMs FS transfers info
2702 * - Authentication info
2703 * - [Un]Replicated access info
2704 */
2705
2706 /* copy overall performance statistics */
2707 srcbuf = (afs_int32 *) & (fullP->perf);
2708 idx = 0;
2709 /* we skip the 19 entry, ProtServAddr, so the index must account for this */
2710 for (i = 0; i < NUM_AFS_STATS_CMPERF_LONGS40 + 1; i++) {
2711 if (i == 19) {
2712 srcbuf++;
2713 continue; /* skip ProtServerAddr */
2714 }
2715 sprintf(a_cmData->data[idx], "%d", *srcbuf);
2716 idx++;
2717 srcbuf++;
2718 }
2719
2720 /*printf("Ending index value = %d\n",idx-1); */
2721
2722 /* server up/down statistics */
2723 /* copy file server up/down stats */
2724 srcbuf = (afs_int32 *) (fullP->perf.fs_UpDown);
2725 numLongs =
2726 2 * (sizeof(struct afs_stats_SrvUpDownInfo) / sizeof(afs_int32));
2727 for (i = 0; i < numLongs; i++) {
2728 sprintf(a_cmData->data[idx], "%d", *srcbuf);
2729 idx++;
2730 srcbuf++;
2731 }
2732
2733 /*printf("Ending index value = %d\n",idx-1); */
2734
2735 /* copy volume location server up/down stats */
2736 srcbuf = (afs_int32 *) (fullP->perf.vl_UpDown);
2737 numLongs =
2738 2 * (sizeof(struct afs_stats_SrvUpDownInfo) / sizeof(afs_int32));
2739 for (i = 0; i < numLongs; i++) {
2740 sprintf(a_cmData->data[idx], "%d", *srcbuf);
2741 idx++;
2742 srcbuf++;
2743 }
2744
2745 /*printf("Ending index value = %d\n",idx-1); */
2746
2747 /* copy CMs individual FS RPC operations info */
2748 srcbuf = (afs_int32 *) (fullP->rpc.fsRPCTimes);
2749 for (i = 0; i < AFS_STATS_NUM_FS_RPC_OPS29; i++) {
2750 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* numOps */
2751 idx++;
2752 srcbuf++;
2753 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* numSuccesses */
2754 idx++;
2755 srcbuf++;
2756 tmpbuf = srcbuf++; /* sum time */
2757 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2758 idx++;
2759 srcbuf++;
2760 tmpbuf = srcbuf++; /* sqr time */
2761 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2762 idx++;
2763 srcbuf++;
2764 tmpbuf = srcbuf++; /* min time */
2765 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2766 idx++;
2767 srcbuf++;
2768 tmpbuf = srcbuf++; /* max time */
2769 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2770 idx++;
2771 srcbuf++;
2772 }
2773
2774 /*printf("Ending index value = %d\n",idx-1); */
2775
2776 /* copy CMs individual FS RPC errors info */
2777
2778 srcbuf = (afs_int32 *) (fullP->rpc.fsRPCErrors);
2779 for (i = 0; i < AFS_STATS_NUM_FS_RPC_OPS29; i++) {
2780 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* server */
2781 idx++;
2782 srcbuf++;
2783 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* network */
2784 idx++;
2785 srcbuf++;
2786 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* prot */
2787 idx++;
2788 srcbuf++;
2789 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* vol */
2790 idx++;
2791 srcbuf++;
2792 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* busies */
2793 idx++;
2794 srcbuf++;
2795 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* other */
2796 idx++;
2797 srcbuf++;
2798 }
2799
2800 /*printf("Ending index value = %d\n",idx-1); */
2801
2802 /* copy CMs individual RPC transfers info */
2803
2804 srcbuf = (afs_int32 *) (fullP->rpc.fsXferTimes);
2805 for (i = 0; i < AFS_STATS_NUM_FS_XFER_OPS2; i++) {
2806 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* numOps */
2807 idx++;
2808 srcbuf++;
2809 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* numSuccesses */
2810 idx++;
2811 srcbuf++;
2812 tmpbuf = srcbuf++; /* sum time */
2813 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2814 idx++;
2815 srcbuf++;
2816 tmpbuf = srcbuf++; /* sqr time */
2817 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2818 idx++;
2819 srcbuf++;
2820 tmpbuf = srcbuf++; /* min time */
2821 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2822 idx++;
2823 srcbuf++;
2824 tmpbuf = srcbuf++; /* max time */
2825 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2826 idx++;
2827 srcbuf++;
2828 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* sum bytes */
2829 idx++;
2830 srcbuf++;
2831 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* min bytes */
2832 idx++;
2833 srcbuf++;
2834 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* max bytes */
2835 idx++;
2836 srcbuf++;
2837 for (j = 0; j < AFS_STATS_NUM_XFER_BUCKETS9; j++) {
2838 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* bucket[j] */
2839 idx++;
2840 srcbuf++;
2841 }
2842 }
2843
2844 /*printf("Ending index value = %d\n",idx-1); */
2845
2846 /* copy CM operations timings */
2847
2848 srcbuf = (afs_int32 *) (fullP->rpc.cmRPCTimes);
2849 for (i = 0; i < AFS_STATS_NUM_CM_RPC_OPS7; i++) {
2850 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* numOps */
2851 idx++;
2852 srcbuf++;
2853 sprintf(a_cmData->data[idx], "%d", *srcbuf); /* numSuccesses */
2854 idx++;
2855 srcbuf++;
2856 tmpbuf = srcbuf++; /* sum time */
2857 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2858 idx++;
2859 srcbuf++;
2860 tmpbuf = srcbuf++; /* sqr time */
2861 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2862 idx++;
2863 srcbuf++;
2864 tmpbuf = srcbuf++; /* min time */
2865 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2866 idx++;
2867 srcbuf++;
2868 tmpbuf = srcbuf++; /* max time */
2869 sprintf(a_cmData->data[idx], "%d.%06d", *tmpbuf, *srcbuf);
2870 idx++;
2871 srcbuf++;
2872 }
2873
2874 /*printf("Ending index value = %d\n",idx-1); */
2875
2876 /* copy authentication info */
2877
2878 srcbuf = (afs_int32 *) & (fullP->authent);
2879 numLongs = sizeof(struct afs_stats_AuthentInfo) / sizeof(afs_int32);
2880 for (i = 0; i < numLongs; i++) {
2881 sprintf(a_cmData->data[idx], "%d", *srcbuf);
2882 idx++;
2883 srcbuf++;
2884 }
2885
2886 /*printf("Ending index value = %d\n",idx-1); */
2887
2888 /* copy CM [un]replicated access info */
2889
2890 srcbuf = (afs_int32 *) & (fullP->accessinf);
2891 numLongs = sizeof(struct afs_stats_AccessInfo) / sizeof(afs_int32);
2892 for (i = 0; i < numLongs; i++) {
2893 sprintf(a_cmData->data[idx], "%d", *srcbuf);
2894 idx++;
2895 srcbuf++;
2896 }
2897
2898 /*printf("Ending index value = %d\n",idx-1); */
2899 return (0);
2900
2901} /* cm_Results_ltoa */
2902
2903
2904/*-----------------------------------------------------------------------
2905 * Function: check_cm_thresholds()
2906 *
2907 * Description:
2908 * Checks the thresholds and sets the overflow flag. Recall that the
2909 * thresholds for each host are stored in the hostEntry lists
2910 * [fs/cm]nameList arrays. The probe results are passed to this
2911 * function in the display-ready format - ie., as strings. Though
2912 * this looks stupid the overhead incurred in converting the strings
2913 * back to floats and comparing them is insignificant and
2914 * programming is easier this way.
2915 * The threshold flags are a part of the display structures
2916 * curr_[fs/cm]Data.
2917 *
2918 * Returns:
2919 * 0
2920 *----------------------------------------------------------------------*/
2921
2922int
2923check_cm_thresholds(struct afsmon_hostEntry *a_hostEntry, /* ptr to hostEntry */
2924 struct cm_Display_Data *a_Data) /* ptr to cm data to be displayed */
2925{ /* check_cm_thresholds */
2926
2927 static char rn[] = "check_cm_thresholds";
2928 struct Threshold *threshP;
2929 double tValue; /* threshold value */
2930 double pValue; /* probe value */
2931 int i;
2932 int idx;
2933 int count; /* number of thresholds exceeded */
2934
2935 if (afsmon_debug) {
2936 fprintf(debugFD, "[ %s ] Called, a_hostEntry= %p, a_Data= %p\n", rn,
2937 a_hostEntry, a_Data);
2938 fflush(debugFD);
2939 }
2940
2941 if (a_hostEntry->numThresh == 0) {
2942 /* store in ovf count ?? */
2943 return (0);
2944 }
2945
2946 count = 0;
2947 threshP = a_hostEntry->thresh;
2948 for (i = 0; i < a_hostEntry->numThresh; i++) {
2949 if (threshP->itemName[0] == '\0') {
2950 threshP++;
2951 continue;
2952 }
2953 idx = threshP->index; /* positional index to the data array */
2954 tValue = atof(threshP->threshVal); /* threshold value */
2955 pValue = atof(a_Data->data[idx]); /* probe value */
2956 if (pValue > tValue) {
2957
2958 if (afsmon_debug) {
2959 fprintf(debugFD,
2960 "[ %s ] cm = %s, thresh ovf for %s, threshold= %s, probevalue= %s\n",
2961 rn, a_hostEntry->hostName, threshP->itemName,
2962 threshP->threshVal, a_Data->data[idx]);
2963 fflush(debugFD);
2964 }
2965
2966 /* if the threshold is crossed, call the handler function
2967 * only if this was a transition -ie, if the threshold was
2968 * crossed in the last probe too just count & keep quite! */
2969
2970 if (!a_Data->threshOvf[idx]) {
2971 a_Data->threshOvf[idx] = 1;
2972 /* call the threshold handler if provided */
2973 if (threshP->handler[0] != '\0') {
2974 if (afsmon_debug) {
2975 fprintf(debugFD, "[ %s ] Calling ovf handler %s\n",
2976 rn, threshP->handler);
2977 fflush(debugFD);
2978 }
2979 execute_thresh_handler(threshP->handler, a_Data->hostName,
2980 CM2, threshP->itemName,
2981 threshP->threshVal,
2982 a_Data->data[idx]);
2983 }
2984 }
2985
2986 count++;
2987 } else
2988 /* in case threshold was previously crossed, blank it out */
2989 a_Data->threshOvf[idx] = 0;
2990 threshP++;
2991 }
2992 /* store the overflow count */
2993 a_Data->ovfCount = count;
2994
2995 return (0);
2996} /* check_cm_thresholds */
2997
2998
2999/*-----------------------------------------------------------------------
3000 * save_CM_data_forDisplay()
3001 *
3002 * Description:
3003 * Does the following:
3004 * - if the probe number changed (ie, a cycle completed) curr_cmData
3005 * is copied to prev_cmData, curr_cmData zeroed and refresh the
3006 * overview screen and file server screen with the new data.
3007 * - store the results of the current probe from xstat_cm_Results into
3008 * curr_cmData. ie., convert longs to strings.
3009 * - check the thresholds
3010 *
3011 * Returns:
3012 * Success: 0
3013 * Failure: Exits afsmonitor.
3014 *
3015 *----------------------------------------------------------------------*/
3016
3017int
3018save_CM_data_forDisplay(struct xstat_cm_ProbeResults *a_cmResults)
3019{ /* save_CM_data_forDisplay */
3020
3021 static char rn[] = "save_CM_data_forDisplay"; /* routine name */
3022 struct cm_Display_Data *curr_cmDataP;
3023 struct cm_Display_Data *prev_cmDataP;
3024 struct afsmon_hostEntry *curr_host;
3025 static int results_Received = 0; /* number of probes reveived in
3026 * the current cycle. If this is equal to numFS we got all
3027 * the data we want in this cycle and can now display it */
3028 int numBytes;
3029 int done;
3030 int code;
3031 int okay;
3032 int i;
3033
3034 if (afsmon_debug) {
3035 fprintf(debugFD, "[ %s ] Called, a_cmResults= %p\n", rn, a_cmResults);
3036 fflush(debugFD);
3037 }
3038
3039 /* store results in the display array */
3040
3041 okay = 0;
3042 curr_cmDataP = curr_cmData;
3043 for (i = 0; i < numCM; i++) {
3044 if ((strcasecmp(curr_cmDataP->hostName, a_cmResults->connP->hostName))
3045 == 0) {
3046 okay = 1;
3047 break;
3048 }
3049 curr_cmDataP++;
3050 }
3051
3052 if (!okay) {
3053 fprintf(stderr__stderrp,
3054 "[ %s ] Could not insert CM probe results for host %s in cm display array\n",
3055 rn, a_cmResults->connP->hostName);
3056 afsmon_Exit(95);
3057 }
3058
3059 /* Check the status of the probe. If it succeeded, we store its
3060 * results in the display data structure. If it failed we only mark
3061 * the failed status in the display data structure. */
3062
3063
3064 if (a_cmResults->probeOK) { /* 1 => notOK the xstat results */
3065 curr_cmDataP->probeOK = 0;
3066
3067 /* print the probe status */
3068 if (afsmon_debug) {
3069 fprintf(debugFD, "\n\t\t ----- cm display data ------\n");
3070 fprintf(debugFD, "HostName = %s PROBE FAILED \n",
3071 curr_cmDataP->hostName);
3072 fflush(debugFD);
3073 }
3074
3075 } else { /* probe succeeded, update display data structures */
3076 curr_cmDataP->probeOK = 1;
3077
3078
3079 /* covert longs to strings and place them in curr_cmDataP */
3080 cm_Results_ltoa(curr_cmDataP, a_cmResults);
3081
3082 /* compare with thresholds and set the overflow flags.
3083 * note that the threshold information is in the hostEntry structure and
3084 * each threshold item has a positional index associated with it */
3085
3086 /* locate the hostEntry for this host */
3087 done = 0;
3088 curr_host = CMnameList;
3089 for (i = 0; i < numCM; i++) {
3090 if (strcasecmp(curr_host->hostName, a_cmResults->connP->hostName)
3091 == 0) {
3092 done = 1;
3093 break;
3094 }
3095 curr_host = curr_host->next;
3096 }
3097 if (!done)
3098 afsmon_Exit(100);
3099
3100 code = check_cm_thresholds(curr_host, curr_cmDataP);
3101 if (code) {
3102 fprintf(stderr__stderrp, "[ %s ] Error in checking thresholds\n", rn);
3103 afsmon_Exit(105);
3104 }
3105
3106 /* print the info we just saved */
3107 if (afsmon_debug) {
3108 fprintf(debugFD, "\n\t\t ----- CM display data ------\n");
3109 fprintf(debugFD, "HostName = %s\n", curr_cmDataP->hostName);
3110 for (i = 0; i < NUM_CM_STAT_ENTRIES571; i++) {
3111 switch (i) {
3112 case 0:
3113 fprintf(debugFD, "\t -- Overall Perf Info --\n");
3114 break;
3115 case 39:
3116 fprintf(debugFD,
3117 "\t -- File Server up/down stats - same cell --\n");
3118 break;
3119 case 64:
3120 fprintf(debugFD,
3121 "\t -- File Server up/down stats - diff cell --\n");
3122 break;
3123 case 89:
3124 fprintf(debugFD,
3125 "\t -- VL server up/down stats - same cell --\n");
3126 break;
3127 case 114:
3128 fprintf(debugFD,
3129 "\t -- VL server up/down stats - diff cell --\n");
3130 break;
3131 case 139:
3132 fprintf(debugFD, "\t -- FS Operation Timings --\n");
3133 break;
3134 case 279:
3135 fprintf(debugFD, "\t -- FS Error Info --\n");
3136 break;
3137 case 447:
3138 fprintf(debugFD, "\t -- FS Transfer Timings --\n");
3139 break;
3140 case 475:
3141 fprintf(debugFD, "\t -- CM Operations Timings --\n");
3142 break;
3143 case 510:
3144 fprintf(debugFD, "\t -- Authentication Info --\n");
3145 break;
3146 case 522:
3147 fprintf(debugFD, "\t -- Access Info --\n");
3148 break;
3149 default:
3150 break;
3151 }
3152
3153 fprintf(debugFD, "%20s %30s %s\n", curr_cmDataP->data[i],
3154 cm_varNames[i],
3155 curr_cmDataP->threshOvf[i] ? "(ovf)" : "");
3156 }
3157 fprintf(debugFD, "\t\t--------------------------------\n\n");
3158 }
3159
3160 } /* if the probe succeeded, update the display data structures */
3161
3162 /* if we have received a reply from all the hosts for this probe cycle,
3163 * it is time to display the data */
3164
3165 results_Received++;
3166 if (results_Received == numCM * num_cm_collections) {
3167 results_Received = 0;
3168
3169 if (afsmon_cm_curr_probeNum != afsmon_cm_prev_probeNum + 1) {
3170 sprintf(errMsg, "[ %s ] Probe number %d missed! \n", rn,
3171 afsmon_cm_prev_probeNum + 1);
3172 afsmon_Exit(110);
3173 } else
3174 afsmon_cm_prev_probeNum++;
3175
3176
3177 /* backup the display data of the probe cycle that just completed -
3178 * ie., store curr_cmData in prev_cmData */
3179
3180 memcpy((char *)prev_cmData, (char *)curr_cmData,
3181 (numCM * sizeof(struct cm_Display_Data)));
3182
3183
3184 /* initialize curr_cmData but retain the threshold flag information.
3185 * The previous state of threshold flags is used in check_cm_thresholds() */
3186
3187 curr_cmDataP = curr_cmData;
3188 numBytes = NUM_CM_STAT_ENTRIES571 * CM_STAT_STRING_LEN14;
3189 for (i = 0; i < numCM; i++) {
3190 curr_cmDataP->probeOK = 0;
3191 curr_cmDataP->ovfCount = 0;
3192 memset(curr_cmDataP->data, 0, numBytes);
3193 curr_cmDataP++;
3194 }
3195
3196 /* prev_cmData now contains all the information for the probe cycle
3197 * that just completed. Now count the number of threshold overflows for
3198 * use in the overview screen */
3199
3200 prev_cmDataP = prev_cmData;
3201 num_cm_alerts = 0;
3202 numHosts_oncm_alerts = 0;
3203 for (i = 0; i < numCM; i++) {
3204 if (!prev_cmDataP->probeOK) { /* if probe failed */
3205 num_cm_alerts++;
3206 numHosts_oncm_alerts++;
3207 } else if (prev_cmDataP->ovfCount) { /* overflows ?? */
3208 num_cm_alerts += prev_cmDataP->ovfCount;
3209 numHosts_oncm_alerts++;
3210 }
3211 prev_cmDataP++;
3212 }
3213 if (afsmon_debug)
3214 fprintf(debugFD, "Number of CM alerts = %d (on %d hosts)\n",
3215 num_cm_alerts, numHosts_oncm_alerts);
3216
3217
3218 /* flag that the data is now ready to be displayed */
3219 cm_Data_Available = 1;
3220
3221 /* update the Overview frame (only CM info) */
3222 ovw_refresh(ovw_currPage, OVW_UPDATE_CM2);
3223
3224 /* update the Cache Managers frame */
3225 cm_refresh(cm_currPage, cm_curr_LCol);
3226
3227 }
3228
3229
3230 return (0);
3231} /* save_CM_data_forDisplay */
3232
3233
3234
3235/*-----------------------------------------------------------------------
3236 * afsmon_CM_Handler()
3237 *
3238 * Description:
3239 * This is the Cache Manager probe Handler. It updates the afsmonitor
3240 * probe counts, cm circular buffer indices and calls the functions
3241 * to process the results of this probe.
3242 *
3243 * Returns:
3244 * Success: 0
3245 * Failure: Exits afsmonitor.
3246 *----------------------------------------------------------------------*/
3247
3248int
3249afsmon_CM_Handler(void)
3250{ /* afsmon_CM_Handler() */
3251 static char rn[] = "afsmon_CM_Handler"; /* routine name */
3252 int code; /* return status */
3253 int newProbeCycle; /* start of new probe cycle ? */
3254
3255 if (afsmon_debug) {
3256 fprintf(debugFD,
3257 "[ %s ] Called, hostName= %s, probeNum= %d, status= %s\n", rn,
3258 xstat_cm_Results.connP->hostName, xstat_cm_Results.probeNum,
3259 xstat_cm_Results.probeOK ? "FAILED" : "OK");
3260 fflush(debugFD);
3261 }
3262
3263
3264 /* print the probe results to output file */
3265 if (afsmon_output) {
3266 code = afsmon_cmOutput(output_filename, afsmon_detOutput);
3267 if (code) {
3268 fprintf(stderr__stderrp,
3269 "[ %s ] output to file %s returned error code=%d\n", rn,
3270 output_filename, code);
3271 }
3272 }
3273
3274 /* Update current probe number and circular buffer index. if current
3275 * probenum changed make sure it is only by 1 */
3276
3277 newProbeCycle = 0;
3278 if (xstat_cm_Results.probeNum != afsmon_cm_curr_probeNum) {
3279 if (xstat_cm_Results.probeNum == afsmon_cm_curr_probeNum + 1) {
3280 afsmon_cm_curr_probeNum++;
3281 newProbeCycle = 1;
3282 if (num_bufSlots)
3283 afsmon_cm_curr_CBindex =
3284 (afsmon_cm_curr_probeNum - 1) % num_bufSlots;
3285 } else {
3286 fprintf(stderr__stderrp, "[ %s ] probe number %d-1 missed\n", rn,
3287 xstat_cm_Results.probeNum);
3288 afsmon_Exit(115);
3289 }
3290 }
3291
3292 /* save the results of this probe in the CM buffer */
3293 if (num_bufSlots)
3294 save_CM_results_inCB(newProbeCycle);
3295
3296 /* store the results of the current probe in the cm data display structure.
3297 * if the current probe number changed, swap the current and previous display
3298 * structures. note that the display screen is updated from these structures
3299 * and should start showing the data of the just completed probe cycle */
3300
3301 save_CM_data_forDisplay(&xstat_cm_Results);
3302
3303 return (0);
3304}
3305
3306/*-----------------------------------------------------------------------
3307 * init_fs_buffers()
3308 *
3309 * Description:
3310 * Allocate and Initialize circular buffers for file servers.
3311 *
3312 * Returns:
3313 * Success: 0
3314 * Failure to allocate memory: exits afsmonitor.
3315 *----------------------------------------------------------------------*/
3316
3317int
3318init_fs_buffers(void)
3319{ /* init_fs_buffers() */
3320 static char rn[] = "init_fs_buffers"; /* routine name */
3321 struct afsmon_fs_Results_list *new_fslist_item; /* ptr for new struct */
3322 struct afsmon_fs_Results_list *tmp_fslist_item; /* temp ptr */
3323 struct xstat_fs_ProbeResults *new_fsPR; /* ptr for new struct */
3324 int i, j;
3325 int bufslot;
3326 int numfs;
3327
3328
3329 if (afsmon_debug) {
3330 fprintf(debugFD, "[ %s ] Called\n", rn);
3331 fflush(debugFD);
3332 }
3333
3334 /* allocate memory for the circular buffer of pointers */
3335
3336 afsmon_fs_ResultsCB = (struct afsmon_fs_Results_CBuffer *)
3337 malloc(sizeof(struct afsmon_fs_Results_CBuffer) * num_bufSlots);
3338
3339 /* initialize the fs circular buffer */
3340 for (i = 0; i < num_bufSlots; i++) {
3341 afsmon_fs_ResultsCB[i].list = (struct afsmon_fs_Results_list *)0;
3342 afsmon_fs_ResultsCB[i].probeNum = 0;
3343 }
3344
3345 /* create a list of numFS items to store fs probe results for
3346 * each slot in CB */
3347
3348 if (numFS) { /* if we have file servers to monitor */
3349 for (bufslot = 0; bufslot < num_bufSlots; bufslot++) {
3350 numfs = numFS; /* get the number of servers */
3351 while (numfs--) {
3352
3353 /* if any of these mallocs fail we only need to free the memory we
3354 * have allocated in this iteration. the rest of it which is in a
3355 * proper linked list will be freed in afsmon_Exit */
3356
3357 /* allocate memory for an fs list item */
3358 new_fslist_item = (struct afsmon_fs_Results_list *)
3359 malloc(sizeof(struct afsmon_fs_Results_list));
3360 if (new_fslist_item == (struct afsmon_fs_Results_list *)0)
3361 return (-1);
3362
3363 for (i = 0; i < MAX_NUM_FS_COLLECTIONS2; i++) {
3364 /* allocate memory to store xstat_fs_Results */
3365 new_fsPR = (struct xstat_fs_ProbeResults *)
3366 malloc(sizeof(struct xstat_fs_ProbeResults));
3367 if (!new_fsPR) {
3368 free(new_fslist_item);
3369 return (-1);
3370 }
3371
3372 new_fsPR->connP = (struct xstat_fs_ConnectionInfo *)
3373 malloc(sizeof(struct xstat_fs_ConnectionInfo));
3374 if (new_fsPR->connP == (struct xstat_fs_ConnectionInfo *)0) {
3375 free(new_fslist_item);
3376 free(new_fsPR);
3377 return (-1);
3378 }
3379
3380 /* >>> need to allocate rx connection info structure here <<< */
3381 new_fsPR->data.AFS_CollData_val = (afs_int32 *)
3382 malloc(afsmon_fs_results_length[i] * sizeof(afs_int32));
3383 if (new_fsPR->data.AFS_CollData_val == NULL((void *)0)) {
3384 free(new_fslist_item);
3385 free(new_fsPR->connP);
3386 free(new_fsPR);
3387 return (-1);
3388 }
3389 new_fslist_item->fsResults[i] = new_fsPR;
3390 new_fslist_item->empty[i] = 1;
3391 }
3392
3393 /* initialize this list entry */
3394 new_fslist_item->next = (struct afsmon_fs_Results_list *)0;
3395
3396 /* store it at the end of the fs list in the current CB slot */
3397 if (afsmon_fs_ResultsCB[bufslot].list ==
3398 (struct afsmon_fs_Results_list *)0)
3399 afsmon_fs_ResultsCB[bufslot].list = new_fslist_item;
3400 else {
3401 tmp_fslist_item = afsmon_fs_ResultsCB[bufslot].list;
3402 j = 0;
3403 while (tmp_fslist_item !=
3404 (struct afsmon_fs_Results_list *)0) {
3405 if (tmp_fslist_item->next ==
3406 (struct afsmon_fs_Results_list *)0)
3407 break;
3408 tmp_fslist_item = tmp_fslist_item->next;
3409 if (++j > numFS) {
3410 /* something goofed. exit */
3411 fprintf(stderr__stderrp, "[ %s ] list creation error\n",
3412 rn);
3413 return (-1);
3414 }
3415 }
3416 tmp_fslist_item->next = new_fslist_item;
3417 }
3418
3419 } /* while servers */
3420 } /* for each buffer slot */
3421 } /* if we have file servers to monitor */
3422 return (0);
3423}
3424
3425/*-----------------------------------------------------------------------
3426 * init_cm_buffers()
3427 *
3428 * Description:
3429 * Allocate and Initialize circular buffers for cache managers.
3430 *
3431 * Returns:
3432 * Success: 0
3433 * Failure to allocate memory: exits afsmonitor.
3434 *----------------------------------------------------------------------*/
3435
3436int
3437init_cm_buffers(void)
3438{ /* init_cm_buffers() */
3439 static char rn[] = "init_cm_buffers"; /* routine name */
3440 struct afsmon_cm_Results_list *new_cmlist_item; /* ptr for new struct */
3441 struct afsmon_cm_Results_list *tmp_cmlist_item; /* temp ptr */
3442 struct xstat_cm_ProbeResults *new_cmPR; /* ptr for new struct */
3443 int i, j;
3444 int bufslot;
3445 int numcm;
3446
3447 if (afsmon_debug) {
3448 fprintf(debugFD, "[ %s ] Called\n", rn);
3449 fflush(debugFD);
3450 }
3451
3452 /* allocate memory for the circular buffer of pointers */
3453 afsmon_cm_ResultsCB = (struct afsmon_cm_Results_CBuffer *)
3454 malloc(sizeof(struct afsmon_cm_Results_CBuffer) * num_bufSlots);
3455
3456 /* initialize the fs circular buffer */
3457 for (i = 0; i < num_bufSlots; i++) {
3458 afsmon_cm_ResultsCB[i].list = (struct afsmon_cm_Results_list *)0;
3459 afsmon_cm_ResultsCB[i].probeNum = 0;
3460 }
3461
3462 /* create a list of numCM items to store fs probe results for
3463 * each slot in CB */
3464
3465 if (numCM) { /* if we have file servers to monitor */
3466 for (bufslot = 0; bufslot < num_bufSlots; bufslot++) {
3467 numcm = numCM; /* get the number of servers */
3468 while (numcm--) {
3469
3470 /* if any of these mallocs fail we only need to free the memory we
3471 * have allocated in this iteration. the rest of it which is in a
3472 * proper linked list will be freed in afsmon_Exit */
3473
3474 /* allocate memory for an fs list item */
3475 new_cmlist_item = (struct afsmon_cm_Results_list *)
3476 malloc(sizeof(struct afsmon_cm_Results_list));
3477 if (new_cmlist_item == (struct afsmon_cm_Results_list *)0)
3478 return (-1);
3479
3480 for (i = 0; i < MAX_NUM_CM_COLLECTIONS1; i++) {
3481 /* allocate memory to store xstat_cm_Results */
3482 new_cmPR = (struct xstat_cm_ProbeResults *)
3483 malloc(sizeof(struct xstat_cm_ProbeResults));
3484 if (!new_cmPR) {
3485 free(new_cmlist_item);
3486 return (-1);
3487 }
3488 new_cmPR->connP = (struct xstat_cm_ConnectionInfo *)
3489 malloc(sizeof(struct xstat_cm_ConnectionInfo));
3490 if (!new_cmPR->connP) {
3491 free(new_cmlist_item);
3492 free(new_cmPR);
3493 return (-1);
3494 }
3495
3496 /* >>> need to allocate rx connection info structure here <<< */
3497
3498 new_cmPR->data.AFSCB_CollData_val =
3499 (afs_int32 *) malloc(XSTAT_CM_FULLPERF_RESULTS_LEN740
3500 * sizeof(afs_int32));
3501 if (new_cmPR->data.AFSCB_CollData_val == NULL((void *)0)) {
3502 free(new_cmlist_item);
3503 free(new_cmPR->connP);
3504 free(new_cmPR);
3505 return (-1);
3506 }
3507
3508 new_cmlist_item->cmResults[i] = new_cmPR;
3509 new_cmlist_item->empty[i] = 1;
3510 }
3511
3512 /* initialize this list entry */
3513 new_cmlist_item->next = (struct afsmon_cm_Results_list *)0;
3514
3515 /* store it at the end of the cm list in the current CB slot */
3516 if (afsmon_cm_ResultsCB[bufslot].list ==
3517 (struct afsmon_cm_Results_list *)0)
3518 afsmon_cm_ResultsCB[bufslot].list = new_cmlist_item;
3519 else {
3520 tmp_cmlist_item = afsmon_cm_ResultsCB[bufslot].list;
3521 j = 0;
3522 while (tmp_cmlist_item !=
3523 (struct afsmon_cm_Results_list *)0) {
3524 if (tmp_cmlist_item->next ==
3525 (struct afsmon_cm_Results_list *)0)
3526 break;
3527 tmp_cmlist_item = tmp_cmlist_item->next;
3528 if (++j > numCM) {
3529 /* something goofed. exit */
3530 fprintf(stderr__stderrp, "[ %s ] list creation error\n",
3531 rn);
3532 return (-1);
3533 }
3534 }
3535 tmp_cmlist_item->next = new_cmlist_item;
3536 }
3537
3538 } /* while servers */
3539 } /* for each buffer slot */
3540 }
3541 /* if we have file servers to monitor */
3542 /* print the CB to make sure it is right */
3543 Print_CM_CB();
3544
3545 return (0);
3546} /* init_cm_buffers() */
3547
3548
3549/*-------------------------------------------------------------------------
3550 * init_print_buffers()
3551 *
3552 * Description:
3553 * Allocate and initialize the buffers used for printing results
3554 * to the display screen. These buffers store the current and
3555 * previous probe results in ascii format.
3556 *
3557 * Returns:
3558 * Success: 0
3559 * Failure: < 0
3560 *------------------------------------------------------------------------*/
3561
3562int
3563init_print_buffers(void)
3564{ /* init_print_buffers */
3565
3566 static char rn[] = "init_print_buffers"; /* routine name */
3567 struct fs_Display_Data *tmp_fsData1; /* temp pointers */
3568 struct fs_Display_Data *tmp_fsData2;
3569 struct cm_Display_Data *tmp_cmData1;
3570 struct cm_Display_Data *tmp_cmData2;
3571 struct afsmon_hostEntry *tmp_fsNames;
3572 struct afsmon_hostEntry *tmp_cmNames;
3573 int i;
3574 int numBytes;
3575
3576 if (afsmon_debug) {
3577 fprintf(debugFD, "[ %s ] Called\n", rn);
3578 fflush(debugFD);
3579 }
3580
3581 /* allocate numFS blocks of the FS print structure. */
3582
3583 /* we need two instances of this structure - one (curr_fsData) for storing
3584 * the results of the fs probes currently in progress and another (prev_fsData)
3585 * for the last completed probe. The display is updated from the contents of
3586 * prev_fsData. The pointers curr_fsData & prev_fsData are switched whenever
3587 * the probe number changes */
3588
3589 if (numFS) {
3590 numBytes = numFS * sizeof(struct fs_Display_Data);
3591 curr_fsData = (struct fs_Display_Data *)malloc(numBytes);
3592 if (curr_fsData == (struct fs_Display_Data *)0) {
3593 fprintf(stderr__stderrp, "[ %s ] Memory allocation failure\n", rn);
3594 return (-1);
3595 }
3596 memset(curr_fsData, 0, numBytes);
3597
3598 numBytes = numFS * sizeof(struct fs_Display_Data);
3599 prev_fsData = (struct fs_Display_Data *)malloc(numBytes);
3600 if (prev_fsData == (struct fs_Display_Data *)0) {
3601 fprintf(stderr__stderrp, "[ %s ] Memory allocation failure\n", rn);
3602 return (-5);
3603 }
3604 memset(prev_fsData, 0, numBytes);
3605
3606 /* fill in the host names */
3607 tmp_fsData1 = curr_fsData;
3608 tmp_fsData2 = curr_fsData;
3609 tmp_fsNames = FSnameList;
3610 for (i = 0; i < numFS; i++) {
3611 strncpy(tmp_fsData1->hostName, tmp_fsNames->hostName,
3612 HOST_NAME_LEN80);
3613 strncpy(tmp_fsData2->hostName, tmp_fsNames->hostName,
3614 HOST_NAME_LEN80);
3615 tmp_fsData1++;
3616 tmp_fsData2++;
3617 tmp_fsNames = tmp_fsNames->next;;
3618 }
3619
3620 }
3621
3622 /* if file servers to monitor */
3623 /* allocate numCM blocks of the CM print structure */
3624 /* we need two instances of this structure for the same reasons as above */
3625 if (numCM) {
3626 numBytes = numCM * sizeof(struct cm_Display_Data);
3627
3628 curr_cmData = (struct cm_Display_Data *)malloc(numBytes);
3629 if (curr_cmData == (struct cm_Display_Data *)0) {
3630 fprintf(stderr__stderrp, "[ %s ] Memory allocation failure\n", rn);
3631 return (-10);
3632 }
3633 memset(curr_cmData, 0, numBytes);
3634
3635 numBytes = numCM * sizeof(struct cm_Display_Data);
3636 prev_cmData = (struct cm_Display_Data *)malloc(numBytes);
3637 if (prev_cmData == (struct cm_Display_Data *)0) {
3638 fprintf(stderr__stderrp, "[ %s ] Memory allocation failure\n", rn);
3639 return (-15);
3640 }
3641 memset(prev_cmData, 0, numBytes);
3642
3643 /* fill in the host names */
3644 tmp_cmData1 = curr_cmData;
3645 tmp_cmData2 = curr_cmData;
3646 tmp_cmNames = CMnameList;
3647 for (i = 0; i < numCM; i++) {
3648 strncpy(tmp_cmData1->hostName, tmp_cmNames->hostName,
3649 HOST_NAME_LEN80);
3650 strncpy(tmp_cmData2->hostName, tmp_cmNames->hostName,
3651 HOST_NAME_LEN80);
3652 tmp_cmData1++;
3653 tmp_cmData2++;
3654 tmp_cmNames = tmp_cmNames->next;;
3655 }
3656
3657 }
3658 /* if cache managers to monitor */
3659 return (0);
3660
3661} /* init_print_buffers */
3662
3663/*-----------------------------------------------------------------------
3664 * quit_signal()
3665 *
3666 * Description:
3667 * Trap the interrupt signal. This function is useful only until
3668 * gtx is initialized.
3669 *----------------------------------------------------------------------*/
3670
3671void
3672quit_signal(int sig)
3673{ /* quit_signal */
3674 fprintf(stderr__stderrp, "Received signal %d \n", sig);
3675 afsmon_Exit(120);
3676} /* quit_signal */
3677
3678
3679
3680/*-----------------------------------------------------------------------
3681 * afsmon_execute()
3682 *
3683 * Description:
3684 * This is where we start it all. Initialize an array of sockets for
3685 * file servers and cache cache managers and call the xstat_[fs/cm]_Init
3686 * routines. The last step is to call the gtx input server which
3687 * grabs control of the keyboard.
3688 *
3689 * Returns:
3690 * Does not return. Control is periodically returned to the afsmonitor
3691 * thru afsmon_[FS/CM]_Handler() routines and also through the gtx
3692 * keyboard handler calls.
3693 *
3694 *----------------------------------------------------------------------*/
3695
3696int
3697afsmon_execute(void)
3698{ /* afsmon_execute() */
3699 static char rn[] = "afsmon_execute"; /* routine name */
3700 static char fullhostname[128]; /* full host name */
3701 struct sockaddr_in *FSSktArray; /* fs socket array */
3702 int FSsktbytes; /* num bytes in above */
3703 struct sockaddr_in *CMSktArray; /* cm socket array */
3704 int CMsktbytes; /* num bytes in above */
3705 struct sockaddr_in *curr_skt; /* ptr to current socket */
3706 struct afsmon_hostEntry *curr_FS; /* ptr to FS name list */
3707 struct afsmon_hostEntry *curr_CM; /* ptr to CM name list */
3708 struct hostent *he; /* host entry */
3709 int FSinitFlags = 0; /* flags for xstat_fs_Init */
3710 int CMinitFlags = 0; /* flags for xstat_cm_Init */
3711 int code; /* function return code */
3712 struct timeval tv; /* time structure */
3713 int i;
3714 short index;
3715
3716 if (afsmon_debug) {
3717 fprintf(debugFD, "[ %s ] Called\n", rn);
3718 fflush(debugFD);
3719 }
3720
3721
3722 /* process file server entries */
3723 if (numFS) {
3724 afs_int32 collIDs[MAX_NUM_FS_COLLECTIONS2];
3725
3726 /* Allocate an array of sockets for each fileserver we monitor */
3727
3728 FSsktbytes = numFS * sizeof(struct sockaddr_in);
3729 FSSktArray = (struct sockaddr_in *)malloc(FSsktbytes);
3730 if (FSSktArray == (struct sockaddr_in *)0) {
3731 fprintf(stderr__stderrp,
3732 "[ %s ] cannot malloc %d sockaddr_ins for fileservers\n",
3733 rn, numFS);
3734 return (-1);
3735 }
3736
3737 memset(FSSktArray, 0, FSsktbytes);
3738
3739 /* Fill in the socket information for each fileserve */
3740
3741 curr_skt = FSSktArray;
3742 curr_FS = FSnameList; /* FS name list header */
3743 while (curr_FS) {
3744 strncpy(fullhostname, curr_FS->hostName, sizeof(fullhostname));
3745 he = GetHostByName(fullhostname);
3746 if (he == NULL((void *)0)) {
3747 fprintf(stderr__stderrp, "[ %s ] Cannot get host info for %s\n", rn,
3748 fullhostname);
3749 return (-1);
3750 }
3751 strncpy(curr_FS->hostName, he->h_name, HOST_NAME_LEN80); /* complete name */
3752 memcpy(&(curr_skt->sin_addr.s_addr), he->h_addrh_addr_list[0], 4);
3753 curr_skt->sin_family = AF_INET2; /*Internet family */
3754 curr_skt->sin_port = htons(7000)(__builtin_constant_p(7000) ? (__uint16_t)(((__uint16_t)(7000
)) << 8 | ((__uint16_t)(7000)) >> 8) : __bswap16_var
(7000))
; /*FileServer port */
3755#ifdef STRUCT_SOCKADDR_HAS_SA_LEN1
3756 curr_skt->sin_len = sizeof(struct sockaddr_in);
3757#endif
3758
3759 /* get the next dude */
3760 curr_skt++;
3761 curr_FS = curr_FS->next;
3762 }
3763
3764 /* Initialize collection IDs, depending on the data requested. */
3765 num_fs_collections = 0;
3766 for (i = 0; i < fs_DisplayItems_count; i++) {
3767 index = fs_Display_map[i];
3768 if (FS_FULLPERF_ENTRY_START0 <= index && index <= FS_FULLPERF_ENTRY_END(275 - 1)) {
3769 collIDs[num_fs_collections++] = AFS_XSTATSCOLL_FULL_PERF_INFO2;
3770 break;
3771 }
3772 }
3773 for (i = 0; i < fs_DisplayItems_count; i++) {
3774 index = fs_Display_map[i];
3775 if (FS_CB_ENTRY_START((275 - 1) + 1) <= index && index <= FS_CB_ENTRY_END(((275 - 1) + 1) + 16 - 1)) {
3776 collIDs[num_fs_collections++] = AFS_XSTATSCOLL_CBSTATS3;
3777 break;
3778 }
3779 }
3780
3781 FSinitFlags = 0;
3782 if (afsmon_onceOnly) /* option not provided at this time */
3783 FSinitFlags |= XSTAT_FS_INITFLAG_ONE_SHOT0x2;
3784
3785 if (afsmon_debug) {
3786 fprintf(debugFD, "[ %s ] Calling xstat_fs_Init \n", rn);
3787 fflush(debugFD);
3788 }
3789
3790 code = xstat_fs_Init(numFS, /*Num servers */
3791 FSSktArray, /*File Server socket array */
3792 afsmon_probefreq, /*probe frequency */
3793 afsmon_FS_Handler, /*Handler routine */
3794 FSinitFlags, /*Initialization flags */
3795 num_fs_collections, /*Number of collection IDs */
3796 collIDs); /*Ptr to collection ID */
3797
3798 if (code) {
3799 fprintf(stderr__stderrp, "[ %s ] xstat_fs_init returned error\n", rn);
3800 afsmon_Exit(125);
3801 }
3802
3803 }
3804
3805
3806 /* end of process fileserver entries */
3807 /* process cache manager entries */
3808 if (numCM) {
3809 afs_int32 collIDs[MAX_NUM_CM_COLLECTIONS1];
3810
3811 /* Allocate an array of sockets for each cache manager we monitor */
3812
3813 CMsktbytes = numCM * sizeof(struct sockaddr_in);
3814 CMSktArray = (struct sockaddr_in *)malloc(CMsktbytes);
3815 if (CMSktArray == (struct sockaddr_in *)0) {
3816 fprintf(stderr__stderrp,
3817 "[ %s ] cannot malloc %d sockaddr_ins for CM entries\n",
3818 rn, numCM);
3819 return (-1);
3820 }
3821
3822 memset(CMSktArray, 0, CMsktbytes);
3823
3824 /* Fill in the socket information for each CM */
3825
3826 curr_skt = CMSktArray;
3827 curr_CM = CMnameList; /* CM name list header */
3828 while (curr_CM) {
3829 strncpy(fullhostname, curr_CM->hostName, sizeof(fullhostname));
3830 he = GetHostByName(fullhostname);
3831 if (he == NULL((void *)0)) {
3832 fprintf(stderr__stderrp, "[ %s ] Cannot get host info for %s\n", rn,
3833 fullhostname);
3834 return (-1);
3835 }
3836 strncpy(curr_CM->hostName, he->h_name, HOST_NAME_LEN80); /* complete name */
3837 memcpy(&(curr_skt->sin_addr.s_addr), he->h_addrh_addr_list[0], 4);
3838 curr_skt->sin_family = AF_INET2;
3839 curr_skt->sin_port = htons(7001)(__builtin_constant_p(7001) ? (__uint16_t)(((__uint16_t)(7001
)) << 8 | ((__uint16_t)(7001)) >> 8) : __bswap16_var
(7001))
; /* Cache Manager port */
3840#ifdef STRUCT_SOCKADDR_HAS_SA_LEN1
3841 curr_skt->sin_len = sizeof(struct sockaddr_in);
3842#endif
3843
3844 /* get the next dude */
3845 curr_skt++;
3846 curr_CM = curr_CM->next;
3847 }
3848
3849 /* initialize collection IDs. We need only one entry since we collect
3850 * all the information from xstat */
3851 num_cm_collections = 0;
3852 collIDs[num_cm_collections++] = AFSCB_XSTATSCOLL_FULL_PERF_INFO2;
3853
3854 CMinitFlags = 0;
3855 if (afsmon_onceOnly) /* once only ? */
3856 CMinitFlags |= XSTAT_CM_INITFLAG_ONE_SHOT0x2;
3857
3858 if (afsmon_debug) {
3859 fprintf(debugFD, "[ %s ] Calling xstat_cm_Init \n", rn);
3860 fflush(debugFD);
3861 }
3862
3863 code = xstat_cm_Init(numCM, /*Num servers */
3864 CMSktArray, /*Cache Manager socket array */
3865 afsmon_probefreq, /*probe frequency */
3866 afsmon_CM_Handler, /*Handler routine */
3867 CMinitFlags, /*Initialization flags */
3868 num_cm_collections, /*Number of collection IDs */
3869 collIDs); /*Ptr to collection ID */
3870
3871 if (code) {
3872 fprintf(stderr__stderrp, "[ %s ] xstat_cm_init returned error\n", rn);
3873 afsmon_Exit(130);
3874 }
3875 }
3876
3877
3878
3879 /* end of process cache manager entries */
3880 /* if only one probe was required setup a waiting process for the
3881 * termination signal */
3882 if (afsmon_onceOnly) {
3883 code = LWP_WaitProcess(&terminationEvent);
3884 if (code) {
3885 if (afsmon_debug) {
3886 fprintf(debugFD, "LWP_WaitProcess() returned error %d\n",
3887 code);
3888 fflush(debugFD);
3889 }
3890 afsmon_Exit(135);
3891 }
3892 }
3893
3894 /* start the gtx input server */
3895 code = (intptr_t)gtx_InputServer(afsmon_win);
3896 if (code) {
3897 fprintf(stderr__stderrp, "[ %s ] Failed to start input server \n", rn);
3898 afsmon_Exit(140);
3899 }
3900
3901 /* This part of the code is reached only if the input server is not started
3902 * for debugging purposes */
3903
3904 /* sleep forever */
3905 tv.tv_sec = 24 * 60;
3906 tv.tv_usec = 0;
3907 fprintf(stderr__stderrp, "[ %s ] going to sleep ...\n", rn);
3908 while (1) {
3909 code = IOMGR_Select(0, /*Num fds */
3910 0, /*Descriptors ready for reading */
3911 0, /*Descriptors ready for writing */
3912 0, /*Descriptors with exceptional conditions */
3913 &tv); /*Timeout structure */
3914 if (code) {
3915 fprintf(stderr__stderrp,
3916 "[ %s ] IOMGR_Select() returned non-zero value %d\n", rn,
3917 code);
3918 afsmon_Exit(145);
3919 }
3920 } /* while sleep */
3921}
3922
3923
3924/*-----------------------------------------------------------------------
3925 * afsmonInit()
3926 *
3927 * Description:
3928 * Afsmonitor initialization routine.
3929 * - processes command line parameters
3930 * - call functions to:
3931 * - process config file
3932 * - initialize circular buffers and display buffers
3933 * - initialize gtx
3934 * - execute afsmonitor
3935 * - initialize the display maps [fs/cm]_Display_map[].
3936 *
3937 * Returns:
3938 * Success: Does not return from the call to afsmon_execute().
3939 * Failure: Exits afsmonitor.
3940 *----------------------------------------------------------------------*/
3941
3942int
3943afsmonInit(struct cmd_syndesc *as, void *arock)
3944{ /* afsmonInit() */
3945
3946 static char rn[] = "afsmonInit"; /* Routine name */
3947 char *debug_filename; /* pointer to debug filename */
3948 FILE *outputFD; /* output file descriptor */
3949 struct cmd_item *hostPtr; /* ptr to parse command line args */
3950 char buf[256]; /* buffer for processing hostnames */
3951 int code;
3952 int i;
3953
3954 if (afsmon_debug) {
3955 fprintf(debugFD, "[ %s ] Called, as= %p\n", rn, as);
3956 fflush(debugFD);
3957 }
3958
3959 /* Open the debug file if -debug option is specified */
3960 if (as->parms[P_DEBUG4].items != 0) {
3961 afsmon_debug = 1;
3962 debug_filename = as->parms[P_DEBUG4].items->data;
3963 debugFD = fopen(debug_filename, "w");
3964 if (debugFD == (FILE *) 0) {
3965 printf("[ %s ] Failed to open debugging file %s for writing\n",
3966 rn, "log");
3967 afsmon_debug = 0;
3968 afsmon_Exit(150);
3969 }
3970 }
3971
3972 if (afsmon_debug) {
3973 fprintf(debugFD, "[ %s ] Called\n", rn);
3974 }
3975
3976
3977 /* use curses always until we support other packages */
3978#ifdef notdef
3979 wpkg_to_use = atoi(as->parms[P_PACKAGE].items->data);
3980
3981 switch (wpkg_to_use) {
3982 case GATOR_WIN_CURSES2:
3983 fprintf(stderr__stderrp, "curses\n");
3984 break;
3985 case GATOR_WIN_DUMB1:
3986 fprintf(stderr__stderrp, "dumb terminal\n");
3987 break;
3988 case GATOR_WIN_X113:
3989 fprintf(stderr__stderrp, "X11\n");
3990 break;
3991 default:
3992 fprintf(stderr__stderrp, "Illegal graphics package: %d\n", wpkg_to_use);
3993 afsmon_Exit(155);
3994 } /*end switch (wpkg_to_use) */
3995#endif
3996
3997 wpkg_to_use = GATOR_WIN_CURSES2;
3998
3999 /* get probe frequency . We check for meaningful bounds on the frequency
4000 * and reset to the default value if needed. The upper bound of 24
4001 * hours looks ridiculous though! */
4002
4003 afsmon_probefreq = 0;
4004 if (as->parms[P_FREQUENCY1].items != 0)
4005 afsmon_probefreq = atoi(as->parms[P_FREQUENCY1].items->data);
4006 else
4007 afsmon_probefreq = DEFAULT_FREQUENCY60;
4008
4009 if (afsmon_probefreq <= 0 || afsmon_probefreq > 24 * 60 * 60) {
4010 afsmon_probefreq = DEFAULT_FREQUENCY60;
4011 if (afsmon_debug) {
4012 fprintf(debugFD,
4013 "[ %s ] Invalid probe frequency %s specified, resetting to default value %d seconds\n",
4014 rn, as->parms[P_FREQUENCY1].items->data, afsmon_probefreq);
4015 fflush(debugFD);
4016 }
4017 fprintf(stderr__stderrp,
4018 "Invalid probe frequency %s specified, resetting to default value %d seconds\n",
4019 as->parms[P_FREQUENCY1].items->data, afsmon_probefreq);
4020 sleep(3);
4021 }
4022
4023
4024 /* make sure output file is writable, else complain now */
4025 /* we will open and close it as needed after probes */
4026
4027 if (as->parms[P_OUTPUT2].items != 0) {
4028 afsmon_output = 1; /* output flag */
4029 strncpy(output_filename, as->parms[P_OUTPUT2].items->data, 80);
4030 outputFD = fopen(output_filename, "a");
4031 if (outputFD == (FILE *) 0) {
4032 fprintf(stderr__stderrp, "Failed to open output file %s \n",
4033 output_filename);
4034 if (afsmon_debug) {
4035 fprintf(debugFD, "[ %s ] Failed to open output file %s \n",
4036 rn, output_filename);
4037 afsmon_Exit(160);
4038 }
4039 }
4040 if (afsmon_debug) {
4041 fprintf(debugFD, "[ %s ] output file is %s\n", rn,
4042 output_filename);
4043 }
4044 fclose(outputFD);
4045 }
4046
4047 /* detailed statistics to storage file */
4048 if (as->parms[P_DETAILED3].items != 0) {
4049 if (as->parms[P_OUTPUT2].items == 0) {
4050 fprintf(stderr__stderrp,
4051 "-detailed switch can be used only with -output\n");
4052 afsmon_Exit(165);
4053 }
4054 afsmon_detOutput = 1;
4055 }
4056
4057 /* Initialize host list headers */
4058 FSnameList = (struct afsmon_hostEntry *)0;
4059 CMnameList = (struct afsmon_hostEntry *)0;
4060
4061 /* The -config option is mutually exclusive with the -fshosts,-cmhosts
4062 * options */
4063
4064 if (as->parms[P_CONFIG0].items) {
4065 if (as->parms[P_FSHOSTS5].items || as->parms[P_CMHOSTS6].items) {
4066 fprintf(stderr__stderrp,
4067 "Cannot use -config option with -fshosts or -cmhosts\n");
4068 afsmon_Exit(170);
4069 }
4070 } else {
4071 if (!as->parms[P_FSHOSTS5].items && !as->parms[P_CMHOSTS6].items) {
4072 fprintf(stderr__stderrp,
4073 "Must specify either -config or (-fshosts and/or -cmhosts) options \n");
4074 afsmon_Exit(175);
4075 }
4076 }
4077
4078
4079 /* If a file server host is specified on the command line we reuse
4080 * parse_hostEntry() function . Just the pass the info as if it were
4081 * read off the config file */
4082
4083 if (as->parms[P_FSHOSTS5].items) {
4084 hostPtr = as->parms[P_FSHOSTS5].items;
4085 while (hostPtr != (struct cmd_item *)0) {
4086 sprintf(buf, "fs %s", hostPtr->data);
4087 code = parse_hostEntry(buf);
4088 if (code) {
4089 fprintf(stderr__stderrp, "Could not parse %s\n", hostPtr->data);
4090 afsmon_Exit(180);
4091 }
4092
4093 hostPtr = hostPtr->next;
4094 }
4095 }
4096
4097 /* same as above for -cmhosts */
4098 if (as->parms[P_CMHOSTS6].items) {
4099 hostPtr = as->parms[P_CMHOSTS6].items;
4100 while (hostPtr != (struct cmd_item *)0) {
4101 sprintf(buf, "cm %s", hostPtr->data);
4102 code = parse_hostEntry(buf);
4103 if (code) {
4104 fprintf(stderr__stderrp, "Could not parse %s\n", hostPtr->data);
4105 afsmon_Exit(185);
4106 }
4107
4108 hostPtr = hostPtr->next;
4109 }
4110 }
4111
4112 /* number of slots in circular buffers */
4113 if (as->parms[P_BUFFERS7].items)
4114 num_bufSlots = atoi(as->parms[P_BUFFERS7].items->data);
4115 else
4116 num_bufSlots = DEFAULT_BUFSLOTS0;
4117
4118 /* Initialize xx_showFlags[]. This array is used solely for processing the
4119 * "show" directives in the config file in parse_showEntries() */
4120 for (i = 0; i < NUM_FS_STAT_ENTRIES(275 + 16); i++)
4121 fs_showFlags[i] = 0;
4122 for (i = 0; i < NUM_CM_STAT_ENTRIES571; i++)
4123 cm_showFlags[i] = 0;
4124
4125
4126 /* Process the configuration file if given. This initializes among other
4127 * things, the list of FS & CM names in FSnameList and CMnameList */
4128
4129 if (as->parms[P_CONFIG0].items)
4130 process_config_file(as->parms[P_CONFIG0].items->data);
4131
4132 /* print out the FS and CM lists */
4133 print_FS();
4134 print_CM();
4135
4136 /* Initialize the FS results-to-screen map array if there were no "show fs"
4137 * directives in the config file */
4138 if (fs_showDefault) {
4139 for (i = 0; i < NUM_FS_STAT_ENTRIES(275 + 16); i++)
4140 fs_Display_map[i] = i;
4141 fs_DisplayItems_count = NUM_FS_STAT_ENTRIES(275 + 16);
4142 }
4143
4144 /* Initialize the CM results-to-screen map array if there were no "show cm"
4145 * directives in the config file */
4146 if (cm_showDefault) {
4147 for (i = 0; i < NUM_CM_STAT_ENTRIES571; i++)
4148 cm_Display_map[i] = i;
4149 cm_DisplayItems_count = NUM_CM_STAT_ENTRIES571;
4150 }
4151
4152
4153
4154 /* setup an interrupt signal handler; we ain't wanna leak core */
4155 /* this binding is useful only until gtx is initialized after which the
4156 * keyboard input server takes over. */
4157 if ((signal(SIGINT2, quit_signal)) == SIG_ERR((__sighandler_t *)-1)) {
4158 perror("signal() failed.");
4159 afsmon_Exit(190);
4160 }
4161
4162
4163 /* init error message buffers. these will be used to print error messages
4164 * once gtx is initialized and there is no access to stderr/stdout */
4165 errMsg[0] = '\0';
4166 errMsg1[0] = '\0';
4167
4168 if (num_bufSlots) {
4169
4170 /* initialize fs and cm circular buffers before initiating probes */
4171 if (numFS) {
4172 code = init_fs_buffers();
4173 if (code) {
4174 fprintf(stderr__stderrp, "[ %s ] init_fs_buffers returned %d\n", rn,
4175 code);
4176 afsmon_Exit(195);
4177 }
4178 }
4179
4180 if (numCM) {
4181 code = init_cm_buffers();
4182 if (code) {
4183 fprintf(stderr__stderrp, "[ %s ] init_cm_buffers returned %d\n", rn,
4184 code);
4185 afsmon_Exit(200);
4186 }
4187 }
4188 }
4189
4190 /* allocate and initialize buffers for holding fs & cm results in ascii
4191 * format suitable for updating the screen */
4192 code = init_print_buffers();
4193 if (code) {
4194 fprintf(stderr__stderrp, "[ %s ] init_print_buffers returned %d\n", rn, code);
4195 afsmon_Exit(205);
4196 }
4197
4198 /* perform gtx initializations */
4199 code = gtx_initialize();
4200 if (code) {
4201 fprintf(stderr__stderrp, "[ %s ] gtx_initialize returned %d\n", rn, code);
4202 afsmon_Exit(210);
4203 }
4204
4205 /* start xstat probes */
4206 afsmon_execute();
4207
4208 return (0); /* will not return from the call to afsmon_execute() */
4209
4210} /* afsmonInit() */
4211
4212
4213/*-----------------------------------------------------------------------
4214 * Function: main()
4215 ------------------------------------------------------------------------*/
4216
4217#include "AFS_component_version_number.c"
4218
4219int
4220main(int argc, char **argv)
4221{ /* main() */
4222 afs_int32 code; /*Return code */
4223 struct cmd_syndesc *ts; /*Ptr to cmd line syntax descriptor */
4224
4225#ifdef AFS_AIX32_ENV
4226 /*
4227 * The following signal action for AIX is necessary so that in case of a
4228 * crash (i.e. core is generated) we can include the user's data section
4229 * in the core dump. Unfortunately, by default, only a partial core is
4230 * generated which, in many cases, isn't too useful.
4231 */
4232 struct sigaction nsa;
4233
4234 sigemptyset(&nsa.sa_mask);
4235 nsa.sa_handler__sigaction_u.__sa_handler = SIG_DFL((__sighandler_t *)0);
4236 nsa.sa_flags = SA_FULLDUMP;
4237 sigaction(SIGSEGV11, &nsa, NULL((void *)0));
4238#endif
4239
4240 /*
4241 * Set up the commands we understand.
4242 */
4243 ts = cmd_CreateSyntax("initcmd", afsmonInit, NULL((void *)0), "initialize the program");
4244 cmd_AddParm(ts, "-config", CMD_SINGLE2, CMD_OPTIONAL1,
4245 "configuration file");
4246 cmd_AddParm(ts, "-frequency", CMD_SINGLE2, CMD_OPTIONAL1,
4247 "poll frequency, in seconds");
4248 cmd_AddParm(ts, "-output", CMD_SINGLE2, CMD_OPTIONAL1, "storage file name");
4249 cmd_AddParm(ts, "-detailed", CMD_FLAG1, CMD_OPTIONAL1,
4250 "output detailed statistics to storage file");
4251#ifdef notdef
4252 /* we hope to use this .... eventually! */
4253 cmd_AddParm(ts, "-package", CMD_SINGLE2, CMD_REQUIRED0,
4254 "Graphics Package to use");
4255#endif
4256 cmd_AddParm(ts, "-debug", CMD_SINGLE2, CMD_OPTIONAL1,
4257 "turn debugging output on to the named file");
4258 cmd_AddParm(ts, "-fshosts", CMD_LIST3, CMD_OPTIONAL1,
4259 "list of file servers to monitor");
4260 cmd_AddParm(ts, "-cmhosts", CMD_LIST3, CMD_OPTIONAL1,
4261 "list of cache managers to monitor");
4262 cmd_AddParm(ts, "-buffers", CMD_SINGLE2, CMD_OPTIONAL1,
4263 "number of buffer slots");
4264
4265 /*
4266 * Parse command-line switches & execute afsmonitor
4267 */
4268
4269 code = cmd_Dispatch(argc, argv);
4270 if (code)
4271 afsmon_Exit(1);
4272 else
4273 afsmon_Exit(2);
4274
4275 exit(0); /* redundant, but gets rid of warning */
4276} /*main */