afsmonitor-formatting-strings-update-20010602
[openafs.git] / src / afsmonitor / afsmon-win.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Afsmon-win: Curses interface for the Afsmonitor using the gtx library.
12  *
13  *-------------------------------------------------------------------------*/
14
15 #include <stdio.h>
16 #include <signal.h>
17 #include <math.h>
18 #include <cmd.h>
19 #include <afs/param.h>
20 #include <string.h>
21 #undef IN
22 #include <time.h>
23
24 #include <afs/param.h>
25
26 #include <gtxwindows.h>         /*Generic window package*/
27 #include <gtxobjects.h>         /*Object definitions*/
28 #if 0
29 #include <gtxtextcb.h>          /*Text object circular buffer interface*/
30 #include <gtxtextobj.h>         /*Text object interface*/
31 #endif
32 #include <gtxlightobj.h>        /*Light object interface*/
33 #include <gtxcurseswin.h>       /*Curses window package*/
34 #include <gtxdumbwin.h>         /*Dumb terminal window package*/
35 #include <gtxX11win.h>          /*X11 window package*/
36 #include <gtxframe.h>           /*Frame package*/
37
38 #include <afs/xstat_fs.h>  
39 #include <afs/xstat_cm.h> 
40
41
42 #include "afsmonitor.h"
43 #include "afsmon-labels.h"
44
45
46 /* afsmonitor version number */
47 static char afsmon_version[] = "1.0";
48
49 /* EXTERNAL VARIABLES (from afsmonitor.c) */
50
51 extern int afsmon_debug;        /* debug info to file ? */
52 extern FILE *debugFD;           /* debugging file descriptor */
53 extern char errMsg[256];        /* buffers used to print error messages after*/ 
54 extern char errMsg1[256];       /* gtx is initialized (stderr/stdout gone !) */ 
55
56 /* number of fileservers and cache managers to monitor */
57 extern int numFS;
58 extern int numCM;
59
60 /* number of FS alerts and number of hosts on FS alerts */
61 extern int num_fs_alerts;
62 extern int numHosts_onfs_alerts;
63
64 /* number of CM alerts and number of hosts on FS alerts */
65 extern int num_cm_alerts;
66 extern int numHosts_oncm_alerts;
67
68 /* ptr to array holding the results of FS probes in ascii format */     
69 extern struct fs_Display_Data *prev_fsData;
70
71 /* ptr to array holding the results of CM probes in ascii format */     
72 extern struct cm_Display_Data *prev_cmData;
73
74 extern int afsmon_fs_curr_probeNum;     /* current fs probe number */
75 extern int afsmon_fs_prev_probeNum;     /* previous fs probe number */
76 extern int afsmon_cm_curr_probeNum;     /* current cm probe number */
77 extern int afsmon_cm_prev_probeNum;     /* previous cm probe number */
78
79 extern int afsmon_probefreq;            /* probe frequency */
80
81 /* map of fs results items we must display. This array contains indices to
82 the fs_varNames[] array corresponding to the stats we want to display. It is
83 initialized while processing the config file */
84
85 extern short fs_Display_map[XSTAT_FS_FULLPERF_RESULTS_LEN];
86 extern int fs_DisplayItems_count;      /* number of items to display */
87
88 extern short cm_Display_map[XSTAT_FS_FULLPERF_RESULTS_LEN];
89 extern int cm_DisplayItems_count;      /* number of items to display */
90
91
92 /* GTX VARIABLES */
93
94 /* minimum window size */
95 #define MINX 80
96 #define MINY 12
97
98 /* justifications */
99 #define RIGHT_JUSTIFY 0
100 #define LEFT_JUSTIFY 1
101 #define CENTER 2
102
103 /* width of overview frame objects */
104 /* field widths include the terminating null character */
105
106 #define PROGNAME_O_WIDTH (maxX/2)       /* program name object */
107 #define OVW_PAGENUM_O_WIDTH     29      /* page number object */
108 #define OVW_PROBENUM_O_WIDTH  39        /* probe number object */
109 #define OVW_CMD_O_WIDTH  (maxX/2)       /* cmd line object */
110 #define OVW_NUMFS_O_WIDTH       40      /* num FSs monitored */
111 #define OVW_NUMCM_O_WIDTH       40      /* num CMs monitored */
112 #define OVW_FSALERTS_O_WIDTH 40         /* num FS alerts */
113 #define OVW_CMALERTS_O_WIDTH 40         /* num CM alerts */
114 #define OVW_HOSTNAME_O_WIDTH (maxX / 2) /* FS & CM host names */
115 #define OVW_HOSTNAME_O_WIDTH_HGL 30     /* cosmetic, atleast this many chars
116                                         will be highlightned */
117
118 /* widths of FS and CM frame objects */
119 #define FC_NUMHOSTS_O_WIDTH  (maxX - 8) /* number of fs monitored. leave 4
120                                         chars on either side for '<<','>>' */
121 #define FC_PAGENUM_O_WIDTH 43
122 #define FC_HOSTNAME_O_WIDTH 11          /* width of FS hostnames column */
123 #define FC_CMD_O_WIDTH    55            /* width of cmd line */
124 #define FC_PROBENUM_O_WIDTH 30          /* width of probe number object */
125 #define FC_ARROWS_O_WIDTH    4          /* width of arrow indicators */
126 #define FC_COLUMN_WIDTH    11           /* width of data columns */
127
128 /* bit definitions for use in resolving command line */
129 /* these bits are set in the xx_pageType variables to indicate what commands
130 are acceptable */
131
132 #define CMD_NEXT  1             /* next page ? */
133 #define CMD_PREV  2             /* previous page ? */
134 #define CMD_LEFT  4             /* left scroll ? */
135 #define CMD_RIGHT 8             /* right scroll ? */
136 #define CMD_FS    16            /* file servers frame exists ? */
137 #define CMD_CM    32            /* cache managers frame exists ? */
138
139
140 #define FC_NUM_FIXED_LINES 10           /* number of fixed lines */
141 #define FC_FIRST_HOST_ROW 8             /* first host entry row number */
142 #define FC_FIRST_LABEL_ROW 4            /* first label row number */
143
144 /* number of fixed lines (that dont change) on the overview screen */
145 #define OVW_NUM_FIXED_LINES 7
146 #define OVW_FIRST_HOST_ROW 5   /* row index of first host entry in ovw frame*/
147
148 #define HIGHLIGHT 1             /* highlight object? */
149
150 static char blankline[256];     /* blank line */
151
152 /* maximum X & Y coordinates of the frames */
153 int maxX;
154 int maxY;
155
156 struct gwin *afsmon_win;        /* afsmonitor window */
157 int gtx_initialized = 0;
158
159 /* Overview screen related definitions */
160
161 struct gtx_frame *ovwFrame;             /* overview screen frame */
162 struct gwin_sizeparams frameDims;       /* frame dimensions. all frames have
163                                         same dimensions */
164
165 /* overview frame object names */
166 struct onode *ovw_progName_o;           /* program name object */
167 struct onode *ovw_pageNum_o;            /* page number onject */
168 struct onode *ovw_cmd_o;                /* command line object */
169 struct onode *ovw_probeNum_o;           /* probe number object */
170 struct onode *ovw_numFS_o;              /* num FS monitored */
171 struct onode *ovw_numCM_o;              /* num CM monitored */
172 struct onode *ovw_FSalerts_o;           /* nunber of FS alerts */
173 struct onode *ovw_CMalerts_o;           /* nunber of CM alerts */
174 struct onode *initMsg_o;                /* initialization message */
175
176 /* number of pages of data for the overview frame */
177 int ovw_numPages = 0;
178 int ovw_currPage = 1;           /* current page number */
179
180 static int ovw_pageType = 0;    /* one of the above types */
181
182 /* number of rows of server names that can be displayed on one overview page*/
183 int ovw_numHosts_perPage;
184
185 /* ptr to a block of ovw_numHosts_perPage number of objects for file servers */
186 struct onode **ovw_fsNames_o;
187 /*ptr to a block of ovw_numHosts_perPage number of objects for cache managers */
188 struct onode **ovw_cmNames_o;
189
190 /* When the ovw_refresh routine is called by the keyboard handlers the
191 following variable is used to determine if fs/cm/fs&cm info must be updated */
192 int ovw_update_info = 0;
193
194 /* Variables needed to display an intialization message on startup */
195 static char *initMsg = "AFSMonitor Collecting Statistics ...";
196 static int initMsg_on = 0;      /* message on ? */
197
198 /* FILE SERVER Screen related definitions */
199
200 struct gtx_frame *fsFrame;              /* File Server screen frame */
201
202 struct onode *fs_pageNum_o;             /* fs page number object */
203 struct onode *fs_cmd_o;                 /* fs command line object */
204 struct onode *fs_probeNum_o;            /* fs probe number object */
205 struct onode *fs_numFS_o;               /* fs number of FSs object */
206 struct onode *fs_leftArrows_o;          /* fs cols on left signal object */
207 struct onode *fs_rightArrows_o;         /* fs cols on right signal object */
208 struct onode **fs_hostNames_o;          /* ptr to host names objects */
209
210 /* bit-map to characterize page type and contents of command prompt */
211 static int fs_pageType = 0;
212
213 /* coordinates for the File Servers screen */
214
215 /* we use page numbers to navigate vertically (ie, across hosts) and column
216 numbers to navigate horizontally */
217
218 int fs_numHosts_perPage;        /* number of file servers per page */
219 int fs_cols_perPage;            /* number of data columns per file server page*/
220 int fs_currPage;                /* current FS page number */
221 int fs_numPages;                /* number of FS pages */
222
223 /* column numbers are index to the mapping structure fs_Display_map. this
224 map contains the indices of datums that should be displayed */
225
226 int fs_numCols;         /* number of columns of FS data (excluding hostname)*/
227                         /* this is the same as fs_DisplayItems_count */
228 /* following column indices run from 1 to (fs_numCols -1) */
229 int fs_curr_LCol = 0;   /* column number of leftmost column on display */
230 int fs_curr_RCol = 0;   /* column number of rightmost column on display */
231 int fs_Data_Available = 0; /* atleast one fs probe cycle completed ? */
232
233
234 /* structure that defines a line of data in the fs/cm frames */
235
236 /* we store each datum value in two objects, one below the other. The reason
237 for doing this is to conserve screen area. most of the datums are just longs
238 and will fit into one object. some of them are timing values and require 13
239 characters to be displayed - such fields may overflow to the second object
240 placed below the first one. */
241
242 struct ServerInfo_line {
243         struct onode *host_o;           /* hostname object */
244         struct onode **data_o[2];       /* ptrs to two arrays of data objects.*/
245                                                 
246 };
247
248 struct ServerInfo_line *fs_lines;       /* ptr to the file server data objects*/
249
250 /* file server label onodes - three rows of them */
251 struct onode **fsLabels_o[3];
252
253 /* CACHE MANAGER Screen related definitions */
254
255 struct gtx_frame *cmFrame;              /* Cache Manager screen frame */
256
257 struct onode *cm_pageNum_o;             /* cm page number object */
258 struct onode *cm_cmd_o;                 /* cm command line object */
259 struct onode *cm_probeNum_o;            /* cm probe number object */
260 struct onode *cm_numCM_o;               /* cm number of FSs object */
261 struct onode *cm_leftArrows_o;          /* fs cols on left signal object */
262 struct onode *cm_rightArrows_o;         /* fs cols on right signal object */
263
264 struct onode **cm_hostNames_o;          /* ptr to host names objects */
265
266 /* bit-map to characterize page type and contents of command prompt */
267 static int cm_pageType = 0;
268
269 /* coordinates for the Cache Managers screen */
270
271 /* we use page numbers to navigate vertically (ie, across hosts) and column
272 numbers to navigate horizontally */
273
274 int cm_numHosts_perPage;        /* number of cache managers per page */
275 int cm_cols_perPage;            /* number of data columns per file server page*/
276 int cm_currPage;                /* current CM page number */
277 int cm_numPages;                /* number of CM pages */
278
279 /* column numbers are index to the mapping structure cm_Display_map. this
280 map contains the indices of datums that should be displayed */
281
282 int cm_numCols;         /* number of columns of FS data (excluding hostname)*/
283                         /* this is the same as cm_DisplayItems_count */
284 /* following column indices run from 1 to (cm_numCols -1) */
285 int cm_curr_LCol = 0;   /* column number of leftmost column on display */
286 int cm_curr_RCol = 0;   /* column number of rightmost column on display */
287 int cm_Data_Available = 0; /* atleast one cm probe cycle completed ? */
288
289
290 /* structure that defines a line of data in the fs/cm frames */
291 struct ServerInfo_line *cm_lines;       /* ptr to the file server data objects*/
292
293 /* file server label onodes - three rows of them */
294 struct onode **cmLabels_o[3];
295
296
297
298 /*------------------------------------------------------------------------
299  * initLightObject
300  *
301  * Description:
302  *      Create and initialize a light onode according to the given
303  *      parameters.
304  *      ( Borrowed from scout.c )
305  *
306  * Arguments:
307  *      char *a_name       : Ptr to the light's string name.
308  *      int a_x            : X offset.
309  *      int a_y            : Y offset.
310  *      int a_width        : Width in chars.
311  *      struct gwin *a_win : Ptr to window structure.
312  *
313  * Returns:
314  *      Ptr to new light onode on success,
315  *      A null pointer otherwise.
316  *
317  * Environment:
318  *      See above.
319  *
320  * Side Effects:
321  *      As advertised.
322  *------------------------------------------------------------------------*/
323
324 static struct onode *
325 initLightObject(a_name, a_x, a_y, a_width, a_win)
326     char *a_name;
327     int a_x;
328     int a_y;
329     int a_width;
330     struct gwin *a_win;
331
332 { /*initLightObject*/
333
334     static char rn[] = "initLightObject";       /*Routine name*/
335     struct onode *newlightp;                    /*Ptr to new light onode*/
336     struct gator_light_crparams light_crparams; /*Light creation params*/
337     char *truncname;                            /*Truncated name, if needed*/
338     int name_len;                               /*True length of name*/
339
340 /* the following debug statement floods the debug file */
341 #ifdef DEBUG_DETAILED
342     if (afsmon_debug) {
343         fprintf(debugFD,"[ %s ] Called, a_name= %s, a_x= %d, a_y= %d, a_width= %d, a_win= %d\n",
344         rn, a_name, a_x, a_y, a_width, a_win);
345         fflush(debugFD);
346     }
347 #endif
348
349     newlightp = (struct onode *)0;
350
351     /*
352       * Set up the creation parameters according to the information we've
353       * received.
354       */
355     light_crparams.onode_params.cr_type = GATOR_OBJ_LIGHT;
356     name_len = strlen(a_name);
357
358     if (name_len <= a_width)
359       sprintf(light_crparams.onode_params.cr_name, "%s", a_name);
360     else {
361       /*
362         * We need to truncate the given name, leaving a `*' at the end to
363         * show us it's been truncated.
364         */
365       truncname = light_crparams.onode_params.cr_name;
366       strncpy(truncname, a_name, a_width-1);
367       truncname[a_width-1] = '*';
368       truncname[a_width]   = 0;
369     }
370     light_crparams.onode_params.cr_x          = a_x;
371     light_crparams.onode_params.cr_y          = a_y;
372     light_crparams.onode_params.cr_width      = a_width;
373     light_crparams.onode_params.cr_height     = 1;
374     light_crparams.onode_params.cr_window     = a_win;
375     light_crparams.onode_params.cr_home_obj   = (struct onode *)0;
376     light_crparams.onode_params.cr_prev_obj   = (struct onode *)0;
377     light_crparams.onode_params.cr_parent_obj = (struct onode *)0;
378     light_crparams.onode_params.cr_helpstring = (char *)0;
379
380     light_crparams.appearance = 0;
381     light_crparams.flashfreq  = 0;
382     sprintf(light_crparams.label, "%s", a_name);
383     light_crparams.label_x = 0;
384     light_crparams.label_y = 0;
385
386     newlightp =
387       gator_objects_create((struct onode_createparams *)(&light_crparams));
388
389     /*
390       * Return the news, happy or not.
391       */
392     return(newlightp);
393
394 } /*initLightObject*/
395
396
397
398 /*------------------------------------------------------------------------
399  * justify_light
400  *
401  * Description:
402  *      Place the chars in the source buffer into the target buffer
403  *      with the desired justification, either centered, left-justified
404  *      or right-justified.  Also, support inidication of truncation
405  *      with a star (*), either on the left or right of the string,
406  *      and whether we're justifying a labeled disk quantity.
407  *
408  *      (derived from mini_justify() in scout.c)
409  *
410  * Arguments:
411  *      char *a_srcbuff     : Ptr to source char buffer.
412  *      char *a_dstbuff     : Ptr to dest char buffer.
413  *      int a_dstwidth      : Width of dest buffer in chars.
414  *      int a_justification : Kind of justification.
415  *      int a_rightTrunc    : If non-zero, place the truncation char
416  *                            on the right of the string.  Otherwise,
417  *                            place it on the left.
418  *
419  * Returns:
420  *      0 on success,
421  *      -1 otherwise.
422  *
423  *------------------------------------------------------------------------*/
424
425 int 
426 justify_light(a_srcbuff, a_dstbuff, a_dstwidth, a_justification, a_rightTrunc)
427     char *a_srcbuff;
428     char *a_dstbuff;
429     int a_dstwidth;
430     int a_justification;
431     int a_rightTrunc;
432
433 { /*justify_light*/
434
435     static char rn[] = "justify_light"; /*Routine name*/
436     int leftpad_chars;                  /*# of chars for left-padding*/
437     int num_src_chars;                  /*# of chars in source*/
438     int true_num_src_chars;             /*# src chars before truncation*/
439     int trunc_needed;                   /*Is truncation needed?*/
440
441
442 /* the following debug statement floods the debug file */
443 #ifdef DEBUG_DETAILED
444     if (afsmon_debug) {
445         fprintf(debugFD,"[ %s ] Called, a_srcbuff= %s, a_dstbuff= %d, a_dstwidth= %d, a_justification= %d, a_rightTrunc= %d\n",
446         rn, a_srcbuff, a_dstbuff, a_dstwidth, a_justification, a_rightTrunc);
447         fflush(debugFD);
448     }
449 #endif
450
451
452     /*
453      * If the destination width will overrun the gtx string storage,
454      * we automatically shorten up.
455      */
456     if (a_dstwidth > GATOR_LABEL_CHARS) {
457       /* 
458       if (afsmon_debug) {
459         fprintf(debugFD,
460         "[%s] Dest width (%d) > gtx buflen (%d), shrinking dest width\n",
461                 rn, a_dstwidth, GATOR_LABEL_CHARS);
462         fflush(debugFD);
463       }
464       */
465       a_dstwidth = GATOR_LABEL_CHARS;
466     }
467
468     /*
469      * If our source string is too long, prepare for truncation.
470      */
471     true_num_src_chars = strlen(a_srcbuff);
472     if (true_num_src_chars >= a_dstwidth) {
473         trunc_needed = 1;
474         num_src_chars = a_dstwidth - 1;
475         leftpad_chars = 0;
476         if (!a_rightTrunc)
477             a_srcbuff += (true_num_src_chars - num_src_chars);
478     }
479     else {
480         trunc_needed = 0;
481         num_src_chars = true_num_src_chars;
482         
483         /*
484          * Compute the necessary left-padding.
485          */
486         switch (a_justification) {
487             
488           case RIGHT_JUSTIFY:
489             leftpad_chars = (a_dstwidth - 1) - num_src_chars;
490             break;
491             
492           case LEFT_JUSTIFY:
493             /*
494              * This is the really easy one.
495              */
496             leftpad_chars = 0;
497             break;
498             
499           case CENTER:
500             leftpad_chars = ((a_dstwidth - 1) - num_src_chars) / 2;
501             break;
502             
503           default:
504             if (afsmon_debug) {
505             fprintf(debugFD, "[%s] Illegal justification command: %d",
506                     rn, a_justification);
507             fprintf(debugFD, "[%s] Called with '%s', dest width=%d\n",
508                     rn, a_srcbuff, a_dstwidth);
509             fflush(debugFD);
510             }
511             return(-1);
512         } /*Switch on justification type*/
513     }
514
515     /*
516      * Clear out the dest buffer, then place the source string at the
517      * appropriate padding location.  Remember to place a string
518      * terminator at the end of the dest buffer, plus whatever truncation
519      * may be needed.  If we're left-truncating, we've already shifted
520      * the src buffer appropriately.
521      */
522     strncpy(a_dstbuff, blankline, a_dstwidth);
523     strncpy(a_dstbuff+leftpad_chars, a_srcbuff, num_src_chars);
524     *(a_dstbuff+a_dstwidth-1) = '\0';
525     if (trunc_needed) {
526         if (a_rightTrunc)
527             *(a_dstbuff+a_dstwidth-2) = '*'; /*Truncate on the right*/
528         else {
529                 *a_dstbuff = '*';            /*Truncate on the left, non-disk*/
530         }
531     } /*Handle truncations*/
532
533     /*
534      * Return the good news.
535      */
536     return(0);
537
538 } /*justify_light*/
539
540
541
542 /*-----------------------------------------------------------------------
543  * afsmonExit_gtx()
544  *
545  * Description:
546  *      Call the exit routine. This function is mapped
547  *      to the keys Q and \ 3 in all the frames and is called by the 
548  *      gtx input server.
549  *----------------------------------------------------------------------*/
550
551 int
552 afsmonExit_gtx()
553 {
554     static char rn[] = "afsmonExit_gtx";
555
556     if (afsmon_debug) {
557         fprintf(debugFD,"[ %s ] Called\n",rn);
558         fflush(debugFD);
559     }
560
561         afsmon_Exit(0);
562 }
563
564
565 /*-----------------------------------------------------------------------
566  * ovw_refresh()
567  *
568  * Description:
569  *      Refresh the overview screen with the contents of the specified page.
570  *      There are two parts to the overview screen - the file server column
571  *      and the cache manager column and each of them is independent of the
572  *      other. Hence it takes as an argumnet the "type" of update to be
573  *      performed.
574  *
575  * Returns:
576  *      Success: 0
577  *      Failure: Exits afsmonitor.
578  *----------------------------------------------------------------------*/
579
580 int
581 ovw_refresh(a_pageNum, a_updateType)
582 int a_pageNum;          /* page to refresh overview display */
583 int a_updateType;       /* OVW_UPDATE_FS = update fs column only,
584                            OVW_UPDATE_CM = update cm column only,
585                            OVW_UPDATE_BOTH = update fs & cm columns. Note that 
586                            we do not want to update a column until the 
587                            corresponding probe cycle has completed */
588 {       /* ovw_refresh */
589
590    static char rn[] = "ovw_refresh";    /* routine name */
591    struct onode **tmp_fsNames_o;                /* ptr to fsNames onodes */
592    struct gator_lightobj *tmp_lightobj; /* ptr for object's display data */
593    struct fs_Display_Data *fsDataP;     /* ptr to FS display data array */
594    struct onode **tmp_cmNames_o;                /* ptr to fsNames onodes */
595    struct cm_Display_Data *cmDataP;     /* ptr to CM display data array */
596    int fsIdx;                           /* for counting # of CM hosts */
597    int cmIdx;                           /* for counting # of CM hosts */
598    int next_page = 0;                   /* is there a next ovw page ? */
599    int prev_page = 0;                   /* is there a previous ovw page */
600    char cmdLine[80];                    /* buffer for command line */
601    char printBuf[256];                  /* buffer to print to screen */
602    int i;
603    int code;
604    int len;
605
606    if (afsmon_debug) {
607         fprintf(debugFD,"[ %s ] Called, a_pageNum= %d, a_updateType= %d\n",
608                 rn, a_pageNum, a_updateType);
609         fflush(debugFD);
610    }
611
612    /* if the data is not yet available  ie., not one probe cycle has 
613    completed, do nothing */
614
615    if ( (a_updateType & OVW_UPDATE_FS) && !fs_Data_Available)
616         return(0);
617    if ( (a_updateType & OVW_UPDATE_CM) && !cm_Data_Available)
618         return(0);
619    
620
621    /* validate page number */
622    if (a_pageNum < 1 || a_pageNum > ovw_numPages) {
623         sprintf(errMsg,"[ %s ] called with incorrect page number %d\n",
624                 rn,a_pageNum);
625         afsmon_Exit(235);
626    }
627
628    /* set the current page number */
629    ovw_currPage = a_pageNum;
630
631    /* turn off init message */
632    if (initMsg_on) {
633         initMsg_on = 0;
634         gtxframe_RemoveFromList(ovwFrame, initMsg_o);
635    }
636
637    /* update the labels */
638
639    /* version label */
640    tmp_lightobj=(struct gator_lightobj *) ovw_progName_o->o_data;
641    sprintf(printBuf,"AFSMonitor [Version %s]",afsmon_version);
642    justify_light(printBuf,tmp_lightobj->label,strlen(printBuf)+1, 
643                 LEFT_JUSTIFY,1);
644    gator_light_set(ovw_progName_o,1);
645
646    /* page number label */
647    tmp_lightobj=(struct gator_lightobj *) ovw_pageNum_o->o_data;
648    sprintf(printBuf,"[System Overview, p. %d of %d]",ovw_currPage,ovw_numPages);
649    justify_light(printBuf,tmp_lightobj->label, OVW_PAGENUM_O_WIDTH, 
650                 RIGHT_JUSTIFY,1);
651    gator_light_set(ovw_pageNum_o,1);
652
653    /* file servers monitored label */
654    tmp_lightobj=(struct gator_lightobj *) ovw_numFS_o->o_data;
655    sprintf(printBuf,"    %d File Servers monitored",numFS);
656    justify_light(printBuf,tmp_lightobj->label, strlen(printBuf)+1, 
657                 LEFT_JUSTIFY,1);
658    
659    /* cache managers monitored label */
660    tmp_lightobj=(struct gator_lightobj *) ovw_numCM_o->o_data;
661    sprintf(printBuf,"    %d Cache Managers monitored",numCM);
662    justify_light(printBuf,tmp_lightobj->label, strlen(printBuf)+1, 
663                 LEFT_JUSTIFY,1);
664
665
666    /* no. of fs alerts label */
667    tmp_lightobj=(struct gator_lightobj *) ovw_FSalerts_o->o_data;
668    sprintf(printBuf,"    %d alerts on %d machines",
669                 num_fs_alerts,numHosts_onfs_alerts);
670    justify_light(printBuf,tmp_lightobj->label, strlen(printBuf)+1, 
671                 LEFT_JUSTIFY,1);
672
673    /* no. of cm alerts label */
674    tmp_lightobj=(struct gator_lightobj *) ovw_CMalerts_o->o_data;
675    sprintf(printBuf,"    %d alerts on %d machines",
676                 num_cm_alerts,numHosts_oncm_alerts);
677    justify_light(printBuf,tmp_lightobj->label, strlen(printBuf)+1, 
678                 LEFT_JUSTIFY,1);
679
680    /* command line */
681    /* determine if we have fs/cm, more/previous pages of data to display */
682
683    ovw_pageType = 0;
684    if (numFS && fs_Data_Available) 
685         ovw_pageType |= CMD_FS;         /* we have an fs frame & data avail. */
686    if (numCM && cm_Data_Available) 
687         ovw_pageType |= CMD_CM;         /* we have a cm frame & data avail. */
688    if (ovw_currPage > 1) 
689         ovw_pageType |= CMD_PREV;       /* got a previous page */
690    if (ovw_currPage < ovw_numPages) 
691         ovw_pageType |= CMD_NEXT;       /* got a next page */
692
693    strcpy(cmdLine,"Command [");
694    if ( (ovw_pageType & CMD_FS) && (ovw_pageType & CMD_CM) )
695         strcat(cmdLine,"fs, cm");
696    else if (ovw_pageType & CMD_FS)
697         strcat(cmdLine,"fs");
698    else if (ovw_pageType & CMD_CM)
699         strcat(cmdLine,"cm");
700         
701    if (ovw_pageType & CMD_PREV)
702         strcat(cmdLine,", prev");
703    if (ovw_pageType & CMD_NEXT)
704         strcat(cmdLine,", next");
705
706    strcat(cmdLine,"]? ");
707
708
709
710
711    /* display the command line */
712    tmp_lightobj=(struct gator_lightobj *) ovw_cmd_o->o_data;
713    sprintf(printBuf,"%s", cmdLine);
714    justify_light(printBuf,tmp_lightobj->label, strlen(printBuf)+1, 
715                 LEFT_JUSTIFY,1);
716    gator_light_set(ovw_cmd_o, 1);
717         
718    /* display probe numbers line */
719    tmp_lightobj=(struct gator_lightobj *) ovw_probeNum_o->o_data;
720    sprintf(printBuf,"[probes %d(fs) %d(cm), freq=%d sec]",
721         afsmon_fs_prev_probeNum, afsmon_cm_prev_probeNum,afsmon_probefreq);
722    justify_light(printBuf,tmp_lightobj->label, OVW_PROBENUM_O_WIDTH, 
723                 RIGHT_JUSTIFY,1);
724    gator_light_set(ovw_probeNum_o, 1);
725         
726
727
728    /* update the file server names column if we are asked to */
729
730    if (numFS && (a_updateType & OVW_UPDATE_FS)) {
731
732    /* move to the right spot in the FS display data array */
733    fsDataP = prev_fsData;
734    fsIdx = 0;
735    for(i=0; i < ((a_pageNum-1) * ovw_numHosts_perPage); i++) {
736         fsDataP++;
737         fsIdx++;
738    }
739    
740    /* get the address to the first FS name */
741    tmp_fsNames_o = ovw_fsNames_o;
742
743    for (i=0; i < ovw_numHosts_perPage; i++) {
744         if (fsIdx < numFS) {    /* this could be the last & partial page */
745
746                 if (fsDataP->hostName[0] == '\0') {
747                         sprintf(errMsg,"[ %s ] empty fs display entry \n",rn);
748                         afsmon_Exit(240);
749                 }
750
751                 /* check if the probe succeeded. if it did check for thresholds
752                 overflow. A failed probe is indicated by "PF" */
753
754                 if (! fsDataP->probeOK) {
755                         sprintf(printBuf,"[ PF] %s", fsDataP->hostName);
756                 } else if (fsDataP->ovfCount)   /* thresholds overflow */
757                         sprintf(printBuf,"[%3d] %s",
758                         fsDataP->ovfCount,fsDataP->hostName);
759                 else {
760                         sprintf(printBuf,"      %s",fsDataP->hostName);
761
762                 }
763                 if (afsmon_debug) 
764                 fprintf(debugFD,"[ %s ] to display %s\n",rn,printBuf);
765
766                 tmp_lightobj=(struct gator_lightobj *) (*tmp_fsNames_o)->o_data;
767
768                 if (strlen(printBuf)+1 < OVW_HOSTNAME_O_WIDTH_HGL)
769                         len = OVW_HOSTNAME_O_WIDTH_HGL;
770                 else 
771                         len = strlen(printBuf)+1;
772
773                 code = justify_light(printBuf,tmp_lightobj->label,
774                         len, LEFT_JUSTIFY, 1);
775                 if (code) {
776                         if (afsmon_debug) {
777                         fprintf(debugFD,"[ %s ] justify_code returned %d\n",
778                                 rn,code);
779                 }
780                 }
781                 
782                 /* highlighten if overflowed or probe failed */
783
784                 if (fsDataP->ovfCount || ! fsDataP->probeOK)    
785                         code = gator_light_set(*tmp_fsNames_o,1);
786                 else
787                         code = gator_light_set(*tmp_fsNames_o,0);
788
789
790         } else {        /* no more hosts, blank the rest of the entries */
791                 tmp_lightobj=(struct gator_lightobj *) (*tmp_fsNames_o)->o_data;
792                 sprintf(tmp_lightobj->label,"%s","");
793         }
794
795         tmp_fsNames_o++;        /* next onode */
796         fsDataP++;              /* next host's data */
797         fsIdx++;                /* host index */
798    }
799    }            /* if numFS */
800
801    /* if we have any cache managers, update them if we are asked to */
802    if (numCM && (a_updateType & OVW_UPDATE_CM)){        
803
804    /* move to the right spot in the CM display data array */
805    cmDataP = prev_cmData;
806    cmIdx = 0;
807    for(i=0; i < ((a_pageNum-1) * ovw_numHosts_perPage); i++) {
808         cmDataP++;
809         cmIdx++;
810    }
811    
812    /* get the address to the first CM name */
813    tmp_cmNames_o = ovw_cmNames_o;
814
815    for (i=0; i < ovw_numHosts_perPage; i++) {
816         if (cmIdx < numCM) {    /* this could be the last & partial page */
817
818                 if (cmDataP->hostName[0] == '\0') {
819                         sprintf(errMsg,"[ %s ] empty cm display entry \n",rn);
820                         afsmon_Exit(245);
821                 }
822
823                 /* check if the probe succeeded. if it did check for thresholds
824                 overflow. A failed probe is indicated by "PF" */
825
826                 if (! cmDataP->probeOK) {
827                         sprintf(printBuf,"[ PF] %s", cmDataP->hostName);
828                 } else if (cmDataP->ovfCount) { /* thresholds overflow */
829                         sprintf(printBuf,"[%3d] %s",
830                         cmDataP->ovfCount,cmDataP->hostName);
831                 } else 
832                         sprintf(printBuf,"      %s",cmDataP->hostName);
833                 
834                 if (afsmon_debug)
835                         fprintf(debugFD,"[ %s ] to display %s\n",rn,printBuf);
836
837                 tmp_lightobj=(struct gator_lightobj *) (*tmp_cmNames_o)->o_data;
838
839                 if (strlen(printBuf)+1 < OVW_HOSTNAME_O_WIDTH_HGL)
840                         len = OVW_HOSTNAME_O_WIDTH_HGL;
841                 else 
842                         len = strlen(printBuf)+1;
843
844                 code = justify_light(printBuf,tmp_lightobj->label,
845                         len, LEFT_JUSTIFY, 1);
846                 if (code) {
847                         if (afsmon_debug) {
848                         fprintf(debugFD,"[ %s ] justify_code returned %d\n",
849                                 rn,code);
850                 }
851                 }
852
853                 /* highlighten if overflow or if probe failed */
854                 if (cmDataP->ovfCount || ! cmDataP->probeOK)
855                         code = gator_light_set(*tmp_cmNames_o,1);
856                 else 
857                         code = gator_light_set(*tmp_cmNames_o,0);
858
859
860         } else {        /* no more hosts, blank the rest of the entries */
861                 tmp_lightobj=(struct gator_lightobj *) (*tmp_cmNames_o)->o_data;
862                 sprintf(tmp_lightobj->label,"%s","");
863         }
864
865         tmp_cmNames_o++;        /* next onode */
866         cmDataP++;              /* next host's data */
867         cmIdx++;                /* host index */
868    }
869    }    /* if numCM */
870
871    /* redraw the display if the overview screen is currently displayed */
872    if (afsmon_win->w_frame == ovwFrame)
873         WOP_DISPLAY(afsmon_win);
874
875    return(0);
876
877 }       /* ovw_refresh */
878         
879
880
881 /*-----------------------------------------------------------------------
882  * Switch_ovw_2_fs()
883  *
884  * Description:
885  *              Switch from the overview screen to the FS screen
886  *----------------------------------------------------------------------*/
887 int
888 Switch_ovw_2_fs()
889 {
890    static char rn[] = "Switch_ovw_2_fs";
891
892     if (afsmon_debug) {
893         fprintf(debugFD,"[ %s ] Called\n",rn);
894         fflush(debugFD);
895     }
896
897    /* bind the File Server frame to the window */
898    if (ovw_pageType & CMD_FS)
899         gtxframe_SetFrame(afsmon_win,fsFrame);
900    return(0);
901 }
902
903 /*-----------------------------------------------------------------------
904  * Switch_ovw_2_cm()
905  *
906  * Description:
907  *              Switch from the overview screen to the CM screen
908  *----------------------------------------------------------------------*/
909 int
910 Switch_ovw_2_cm()
911 {
912    static char rn[] = "Switch_ovw_2_cm";
913
914    if (afsmon_debug) {
915         fprintf(debugFD,"[ %s ] Called\n",rn);
916         fflush(debugFD);
917    }
918
919    /* bind the Cache Managers frame to the window */
920    if (ovw_pageType & CMD_CM)
921         gtxframe_SetFrame(afsmon_win,cmFrame);
922    return(0);
923 }
924
925 /*-----------------------------------------------------------------------
926  * Switch_ovw_next()
927  *
928  * Description:
929  *              Switch to the next page in overview screen
930  *----------------------------------------------------------------------*/
931 int
932 Switch_ovw_next()
933 {
934    static char rn[] = "Switch_ovw_next";
935
936    if (afsmon_debug) {
937         fprintf(debugFD,"[ %s ] Called\n",rn);
938         fflush(debugFD);
939    }
940
941    if (ovw_pageType & CMD_NEXT) {
942         /* call refresh with the next page number */
943         ovw_refresh(ovw_currPage + 1,ovw_update_info);
944    }
945
946    return(0);
947 }
948
949 /*-----------------------------------------------------------------------
950  * Switch_ovw_last()
951  *
952  * Description:
953  *              Switch to the last page in the overview screen
954  *----------------------------------------------------------------------*/
955 int
956 Switch_ovw_last()
957 {
958    static char rn[] = "Switch_ovw_last";
959
960     if (afsmon_debug) {
961         fprintf(debugFD,"[ %s ] Called\n",rn);
962         fflush(debugFD);
963     }
964
965    if (ovw_pageType & CMD_NEXT) {
966         /* call refresh with the last page number */
967         ovw_refresh(ovw_numPages, ovw_update_info);
968    }
969
970    return(0);
971 }
972
973 /*-----------------------------------------------------------------------
974  * Switch_ovw_prev()
975  *
976  * Description:
977  *              Switch to the previous page in the overview screen
978  *----------------------------------------------------------------------*/
979 int
980 Switch_ovw_prev()
981 {
982    static char rn[] = "Switch_ovw_prev";
983
984     if (afsmon_debug) {
985         fprintf(debugFD,"[ %s ] Called\n",rn);
986         fflush(debugFD);
987     }
988
989    if (ovw_pageType & CMD_PREV) {
990         /* call refresh with the previous page number */
991         ovw_refresh(ovw_currPage - 1,ovw_update_info);
992    }
993    return(0);
994 }
995
996 /*-----------------------------------------------------------------------
997  * Switch_ovw_first()
998  *
999  * Description:
1000  *              Switch to the first page in the overview screen
1001  *----------------------------------------------------------------------*/
1002 int
1003 Switch_ovw_first()
1004 {
1005    static char rn[] = "Switch_ovw_first";
1006
1007     if (afsmon_debug) {
1008         fprintf(debugFD,"[ %s ] Called\n",rn);
1009         fflush(debugFD);
1010     }
1011
1012    if (ovw_pageType & CMD_PREV) {
1013         /* refresh with the first page number */
1014         ovw_refresh(1, ovw_update_info);
1015    }
1016    return(0);
1017 }
1018
1019 /*-----------------------------------------------------------------------
1020  * create_ovwFrame_objects()
1021  *
1022  * Description:
1023  *      Create the gtx objects (onodes) for the overview frame and setup
1024  *      the keyboard bindings.
1025  *      Only as many objects as can fit on the display are created. The
1026  *      positions and lengths of all these objects are fixed at creation.
1027  *      These objects are updated with new data at the end of each probe
1028  *      cycle.
1029  *
1030  * Returns:
1031  *      Success: 0
1032  *      Failure: Exits afsmonitor.
1033  *----------------------------------------------------------------------*/
1034
1035 int
1036 create_ovwFrame_objects()
1037 {       /* create_ovwFrame_objects */
1038
1039    static char rn[] = "create_ovwFrame_objects";
1040    int hostLines;       /* number of lines of host names to display */
1041    struct onode **ovw_fsNames_o_Ptr;    /* index to list of fs names onodes */
1042    struct onode **ovw_cmNames_o_Ptr;    /* index to list of cm names onodes */
1043    int code;
1044    int i;
1045
1046     if (afsmon_debug) {
1047         fprintf(debugFD,"[ %s ] Called\n",rn);
1048         fflush(debugFD);
1049     }
1050
1051    /* get frame dimensions, it must be atleast 80x10 for any sensible output*/
1052    WOP_GETDIMENSIONS(ovwFrame->window,&frameDims);
1053    maxX = frameDims.maxx;
1054    maxY = frameDims.maxy;
1055    if (maxX < MINX || maxY < MINY) {
1056         sprintf(errMsg1,"[ %s ] Window size must be atleaset 80x12\n",
1057                 rn);
1058         return(-1);
1059    }
1060    if (afsmon_debug)
1061         fprintf(debugFD,"maxX = %d maxY = %d\n",maxX,maxY);
1062
1063
1064    /* Print an Intial message to the screen. The init message is 36 chars
1065       long */
1066    initMsg_o = initLightObject(initMsg,
1067                 maxX/2 - 18,maxY/3,sizeof(initMsg),afsmon_win);
1068    if (initMsg_o == (struct onode *)0) {
1069         sprintf(errMsg,"[ %s ] Failed to create initMsg_o onode\n",rn);
1070         afsmon_Exit(250);
1071    }
1072    code = gtxframe_AddToList(ovwFrame,initMsg_o);
1073    code = gator_light_set(initMsg_o,HIGHLIGHT);
1074    initMsg_on = 1;
1075
1076
1077
1078    /* create the command line object */
1079
1080    ovw_cmd_o = initLightObject("",
1081                 0,maxY-1,OVW_CMD_O_WIDTH,afsmon_win);
1082    if (ovw_cmd_o == (struct onode *)0) {
1083         sprintf(errMsg,"[ %s ] Failed to create command onode\n",rn);
1084         afsmon_Exit(265);
1085    }
1086    code = gtxframe_AddToList(ovwFrame,ovw_cmd_o);
1087    code = gator_light_set(ovw_cmd_o,HIGHLIGHT);
1088
1089    /* create the program name object */
1090
1091    ovw_progName_o = initLightObject("",0,0,
1092                                 PROGNAME_O_WIDTH,afsmon_win);
1093    if (ovw_progName_o == (struct onode *)0) {
1094         sprintf(errMsg,"[ %s ] Failed to create programName onode\n",rn);
1095         afsmon_Exit(255);
1096    }
1097    code = gtxframe_AddToList(ovwFrame,ovw_progName_o);
1098    code = gator_light_set(ovw_progName_o,HIGHLIGHT);
1099
1100    /* create the page number object */
1101
1102    ovw_pageNum_o = initLightObject("",
1103                 maxX-OVW_PAGENUM_O_WIDTH,0,OVW_PAGENUM_O_WIDTH,afsmon_win);
1104    if (ovw_pageNum_o == (struct onode *)0) {
1105         sprintf(errMsg,"[ %s ] Failed to create pageNumber onode\n",rn);
1106         afsmon_Exit(260);
1107    }
1108    code = gtxframe_AddToList(ovwFrame,ovw_pageNum_o);
1109    code = gator_light_set(ovw_pageNum_o,HIGHLIGHT);
1110                 
1111    /* create the probe number object */
1112    ovw_probeNum_o = initLightObject("",
1113         maxX-OVW_PROBENUM_O_WIDTH,maxY-1,OVW_PROBENUM_O_WIDTH,afsmon_win);
1114    if (ovw_probeNum_o == (struct onode *)0) {
1115         sprintf(errMsg,"[ %s ] Failed to create probe number onode\n",rn);
1116         afsmon_Exit(270);
1117    }
1118    code = gtxframe_AddToList(ovwFrame,ovw_probeNum_o);
1119    code = gator_light_set(ovw_probeNum_o,HIGHLIGHT);
1120
1121    /* create the numFS monitored object */
1122    ovw_numFS_o = initLightObject("",
1123                 0,2,FC_NUMHOSTS_O_WIDTH,afsmon_win);
1124    if (ovw_numFS_o == (struct onode *)0) {
1125         sprintf(errMsg,"[ %s ] Failed to create numFS onode\n",rn);
1126         afsmon_Exit(275);
1127    }
1128    code = gtxframe_AddToList(ovwFrame,ovw_numFS_o);
1129
1130    /* create the numCM monitored object */
1131    ovw_numCM_o = initLightObject("",
1132                 maxX/2,2,OVW_NUMCM_O_WIDTH,afsmon_win);
1133    if (ovw_numCM_o == (struct onode *)0) {
1134         sprintf(errMsg,"[ %s ] Failed to create numCM_o onode\n",rn);
1135         afsmon_Exit(280);
1136    }
1137    code = gtxframe_AddToList(ovwFrame,ovw_numCM_o);
1138
1139    /* create the number-of-FS-alerts object */
1140    ovw_FSalerts_o = initLightObject("",
1141                 0,3,OVW_FSALERTS_O_WIDTH,afsmon_win);
1142    if (ovw_FSalerts_o == (struct onode *)0) {
1143         sprintf(errMsg,"[ %s ] Failed to create FSalerts_o onode\n",rn);
1144         afsmon_Exit(285);
1145    }
1146    code = gtxframe_AddToList(ovwFrame,ovw_FSalerts_o);
1147    
1148    /* create the number-of-CM-alerts object */
1149    ovw_CMalerts_o = initLightObject("",
1150                 maxX/2,3,OVW_CMALERTS_O_WIDTH,afsmon_win);
1151    if (ovw_CMalerts_o == (struct onode *)0) {
1152         sprintf(errMsg,"[ %s ] Failed to create CMalerts_o onode\n",rn);
1153         afsmon_Exit(290);
1154    }
1155    code = gtxframe_AddToList(ovwFrame,ovw_CMalerts_o);
1156
1157    /* create file-server-name and cache-manager-names objects */
1158    ovw_numHosts_perPage = maxY - OVW_NUM_FIXED_LINES;
1159
1160    /* allocate memory for a list of onode pointers for file server names */
1161    ovw_fsNames_o = (struct onode **) malloc(
1162                         sizeof(struct onode *) * ovw_numHosts_perPage); 
1163    if (ovw_fsNames_o == (struct onode **)0) {
1164         sprintf(errMsg,"[ %s ] Failed to allocate memory for FS onodes\n",rn);
1165         afsmon_Exit(295);
1166    }
1167
1168    /* create file server name objects */
1169    ovw_fsNames_o_Ptr = ovw_fsNames_o;
1170    for (i=0; i< ovw_numHosts_perPage; i++) {
1171         *ovw_fsNames_o_Ptr = initLightObject("",
1172                 0,OVW_FIRST_HOST_ROW+i,OVW_HOSTNAME_O_WIDTH,afsmon_win);
1173         if (*ovw_fsNames_o_Ptr == (struct onode *)0) {
1174                 sprintf(errMsg,"[ %s ] Failed to create an FS name onode\n",rn);
1175                 afsmon_Exit(300);
1176         }
1177         /*
1178         if (afsmon_debug) {
1179                 fprintf(debugFD,"[ %s ] fsName_o  %d:  %d\n",
1180                         rn,i,*ovw_fsNames_o_Ptr);
1181                 fflush(debugFD);
1182         }
1183         */
1184         code = gtxframe_AddToList(ovwFrame,*ovw_fsNames_o_Ptr);
1185         ovw_fsNames_o_Ptr++;
1186
1187    }
1188         
1189                         
1190    /* allocate memory for a list of onode pointers for cache manager names */
1191    ovw_cmNames_o = (struct onode **) malloc(
1192                         sizeof(struct onode *) * ovw_numHosts_perPage); 
1193    if (ovw_cmNames_o == (struct onode **)0) {
1194         sprintf(errMsg,"[ %s ] Failed to allocate memory for CM onodes\n",rn);
1195         afsmon_Exit(305);
1196    }
1197
1198    /* create cache manager name objects */
1199    ovw_cmNames_o_Ptr = ovw_cmNames_o;
1200    for (i=0; i< ovw_numHosts_perPage; i++) {
1201         *ovw_cmNames_o_Ptr = initLightObject("",
1202                 maxX/2,OVW_FIRST_HOST_ROW+i,OVW_HOSTNAME_O_WIDTH,afsmon_win);
1203         if (*ovw_cmNames_o_Ptr == (struct onode *)0) {
1204                 sprintf(errMsg,"[ %s ] Failed to create a CM name onode\n",rn);
1205                 afsmon_Exit(310);
1206         }
1207         code = gtxframe_AddToList(ovwFrame,*ovw_cmNames_o_Ptr);
1208         ovw_cmNames_o_Ptr++;
1209    }
1210
1211
1212    /* Calculate the number of pages of overview data to display */
1213    /* host information starts at the 6th line from top and stops at 3rd
1214    line from bottom of screen */
1215
1216    if (numFS > numCM) hostLines = numFS;
1217         else hostLines = numCM;
1218
1219    ovw_numPages = hostLines / (maxY - OVW_NUM_FIXED_LINES); 
1220    if ( hostLines % (maxY - OVW_NUM_FIXED_LINES) )
1221         ovw_numPages++;
1222    
1223    if (afsmon_debug)
1224         fprintf(debugFD,"[ %s ] number of ovw pages = %d\n",rn,ovw_numPages);
1225
1226    /* When the ovw_refresh() routine is called by the keyboard handlers the
1227    following variable is used to determine if fs/cm/fs&cm info must be
1228    updated */
1229    ovw_update_info = 0;
1230    if (numFS)
1231         ovw_update_info |= OVW_UPDATE_FS;
1232    if (numCM)
1233         ovw_update_info |= OVW_UPDATE_CM;
1234
1235   /* bind the overview frame to a keyboard input handler */
1236
1237    /* bind Q and \ 3 to exit */
1238    keymap_BindToString(ovwFrame->keymap,"Q",afsmonExit_gtx,(char *)0,(char *)0);
1239    keymap_BindToString(ovwFrame->keymap,"\ 3",afsmonExit_gtx,(char *)0,(char *)0);
1240
1241   /* f -> switch of fs frame */
1242   keymap_BindToString(ovwFrame->keymap,"f",Switch_ovw_2_fs,(char *)0,(char *)0);
1243   /* c -> switch of cm frame */
1244   keymap_BindToString(ovwFrame->keymap,"c",Switch_ovw_2_cm,(char *)0,(char *)0);
1245   /* n -> switch to next overview page */
1246   keymap_BindToString(ovwFrame->keymap,"n",Switch_ovw_next,(char *)0,(char *)0);
1247   /* N -> switch to last overview page */
1248   keymap_BindToString(ovwFrame->keymap,"N",Switch_ovw_last,(char *)0,(char *)0);
1249   /* p -> switch to previous overview page */
1250   keymap_BindToString(ovwFrame->keymap,"p",Switch_ovw_prev,(char *)0,(char *)0);
1251   /* P -> switch to first overview page */
1252   keymap_BindToString(ovwFrame->keymap,"P",Switch_ovw_first,(char *)0,(char *)0);
1253
1254    
1255    return(0);
1256 }       /* create_ovwFrame_objects */
1257
1258
1259 /*-----------------------------------------------------------------------
1260  * resolve_CmdLine()
1261  *
1262  * Description:
1263  *      This function is called to determine the permissible keyboard
1264  *      operations on the FS and CM frames. This information is used
1265  *      to create an appropriate command line prompt. It also generates
1266  *      a bit map of the permissible operations on this page which is
1267  *      used by the keyboard-input handler routines.
1268  *
1269  * Returns:
1270  *      Success: page-type (bit map of permissible operations)
1271  *      Failure: -1
1272  *----------------------------------------------------------------------*/
1273
1274 int
1275 resolve_CmdLine(a_buffer, a_currFrame, a_currPage, a_numPages, 
1276                 a_numCols, a_curr_LCol, a_cols_perPage, a_Data_Available)
1277 char *a_buffer;         /* buffer to copy command line */
1278 int a_currFrame;        /* current frame ovw, fs or cm? */
1279 int a_currPage;         /* current page number */
1280 int a_numPages;         /* number of pages of data */
1281 int a_numCols;          /* number of columns of data to display */
1282 int a_curr_LCol;        /* current number of leftmost column */
1283 int a_cols_perPage;     /* number of columns per page */
1284
1285 {       /* resolve_CmdLine */
1286    static char rn[] = "resolve_CmdLine";
1287    int pageType;
1288
1289     if (afsmon_debug) {
1290         fprintf(debugFD,"[ %s ] Called, a_buffer= %d, a_currFrame= %d, a_currPage= %d, a_numPages= %d, a_numCols= %d, a_curr_LCol= %d, a_cols_perPage= %d\n",
1291         rn, a_buffer, a_currFrame, a_currPage, a_numPages, a_numCols, 
1292         a_curr_LCol, a_cols_perPage);
1293         fflush(debugFD);
1294     }
1295
1296    pageType = 0;
1297
1298    /* determine if we have fs/cm frames. If we do, note that we should not
1299       let the user seen the initial junk we have there until the probe
1300       results are available  */
1301    if (a_currFrame == 1) {              /* in the fs frame */
1302         if (numCM && cm_Data_Available) pageType |= CMD_CM;
1303    } else if (a_currFrame == 2)  {      /* in the cm frame */
1304         if (numFS && fs_Data_Available) pageType |= CMD_FS;
1305    } else {
1306         if (afsmon_debug) {
1307                 fprintf(debugFD,"[ %s ] Wrong frame type %d\n",rn,a_currFrame);
1308                 fflush(debugFD);
1309         }
1310         return(-1);
1311    }
1312
1313    /* do we have next/previous pages */
1314    if ( a_currPage < a_numPages )
1315         pageType |= CMD_NEXT;   /* have a next page */
1316    if ( a_currPage > 1 )
1317         pageType |= CMD_PREV;   /* have a previous page */
1318    
1319    if ( a_numCols > a_cols_perPage ) {
1320         if ( a_curr_LCol > 0 )
1321                 pageType |= CMD_LEFT;   /* have columns on left */
1322         if ( (a_curr_LCol + a_cols_perPage )  < a_numCols )
1323                 pageType |= CMD_RIGHT;  /* have columns on right */
1324    }
1325                 
1326    /* now build the command line */
1327
1328    strcpy(a_buffer,"Command [oview");
1329    if ( pageType & CMD_FS)
1330         strcat(a_buffer,", fs");
1331    if ( pageType & CMD_CM)
1332         strcat(a_buffer,", cm");
1333    if ( pageType & CMD_PREV )
1334         strcat(a_buffer,", prev");      
1335    if ( pageType & CMD_NEXT )
1336         strcat(a_buffer,", next");      
1337    if ( pageType & CMD_LEFT )
1338         strcat(a_buffer,", left");      
1339    if ( pageType & CMD_RIGHT )
1340         strcat(a_buffer,", right");     
1341    strcat(a_buffer,"]? ");
1342
1343    return(pageType);
1344
1345 }       /* resolve_CmdLine */
1346
1347 /*-----------------------------------------------------------------------
1348  * display_Server_datum()
1349  *
1350  * Description:
1351  *      The data in the file server & cache manager frames are displayed
1352  *      in two objects, one below the other. If the data is too long to
1353  *      fit in the first object it will overflow into the next. This is
1354  *      to conserve real estate on the screen. This function copies the 
1355  *      contents of the source buffer adjusted to the two objects if the
1356  *      probe had succeded. Otherwise it enters "--" in the first object 
1357  *      blanks out the second. If the object needs to be highlightned
1358  *      (due to a threshold crossing) it is done.
1359  *
1360  * Returns:
1361  *      0 always
1362  *----------------------------------------------------------------------*/
1363 int
1364 display_Server_datum(a_srcBuf, a_firstObj_o, a_secondObj_o, 
1365                 a_probeOK, a_just, a_highlight)
1366
1367 char *a_srcBuf;                 /* source buffer */
1368 struct onode *a_firstObj_o;             /* first object */
1369 struct onode *a_secondObj_o;            /* second object */
1370 int a_probeOK;                  /* probe OK ? */
1371 int a_just;                     /* justification */
1372 int a_highlight;                /* highlight object  ? */
1373
1374 {       /* display_Server_datum */
1375
1376     static char rn[] = "display_Server_datum";
1377     struct gator_lightobj *tmp_lightobj1;
1378     struct gator_lightobj *tmp_lightobj2;
1379     char part1[FC_COLUMN_WIDTH+2];
1380     char part2[FC_COLUMN_WIDTH+2];
1381     int code;
1382
1383     if (afsmon_debug) {
1384         if (a_highlight)
1385         fprintf(debugFD,"[ %s ] Called, a_srcBuf= %s, a_firstObj_o= %d, a_secondObj_o= %d, a_probeOK= %d, a_just= %d, a_highlight= %d\n", rn, 
1386         a_srcBuf, a_firstObj_o, a_secondObj_o, a_probeOK, a_just, a_highlight);
1387         fflush(debugFD);
1388     }
1389
1390
1391     tmp_lightobj1 = (struct gator_lightobj *) a_firstObj_o->o_data;
1392     tmp_lightobj2 = (struct gator_lightobj *) a_secondObj_o->o_data;
1393
1394     if (a_probeOK) {    /* probe is ok so fill in the data */
1395
1396         /* check if it would fit in one object */
1397         if (strlen(a_srcBuf) < FC_COLUMN_WIDTH) {
1398                 strcpy(part1, a_srcBuf );
1399                 strcpy(part2, "");
1400         } else {
1401                 /* break up the src string into 2 parts */
1402                 /* note that column width includes terminator */
1403                 strncpy(part1, a_srcBuf, FC_COLUMN_WIDTH-1);
1404                 part1[FC_COLUMN_WIDTH-1] = '\0';
1405                 strncpy(part2, a_srcBuf+FC_COLUMN_WIDTH-1, FC_COLUMN_WIDTH-1);
1406
1407         }
1408
1409    } else {     /* probe failed, enter "--"s */
1410         strcpy(part1,"--");
1411         strcpy(part2,"");
1412    }
1413
1414    /* if (afsmon_debug) {
1415         fprintf(debugFD,"[ %s ] %s split to %s & %s\n",rn,a_srcBuf,part1,part2);
1416         fflush(debugFD);
1417    } */
1418
1419    /* initialize both the objects */
1420
1421    code = justify_light(part1, tmp_lightobj1->label,
1422                 FC_COLUMN_WIDTH, a_just, 1);
1423    if (code) {
1424         if (afsmon_debug) {
1425         fprintf(debugFD,"[ %s ] justify_light failed 1 \n",rn);
1426         fflush(debugFD);
1427         }
1428    }
1429
1430    code = justify_light(part2, tmp_lightobj2->label,
1431         FC_COLUMN_WIDTH, a_just, 1);
1432    if (code) {
1433         if (afsmon_debug) {
1434         fprintf(debugFD,"[ %s ] justify_light failed 1 \n",rn);
1435         fflush(debugFD);
1436         }
1437    }
1438
1439    /* highlight them */
1440    if (a_highlight && (part1[0] != '-'))
1441         gator_light_set(a_firstObj_o, 1);
1442    else
1443         gator_light_set(a_firstObj_o, 0);
1444    if (a_highlight && (part2[0] != '\0'))
1445         gator_light_set(a_secondObj_o, 1);
1446    else
1447         gator_light_set(a_secondObj_o, 0);
1448         
1449
1450
1451    return(0);
1452
1453 }       /* display_Server_datum */
1454
1455
1456 /*-----------------------------------------------------------------------
1457  * display_Server_label()
1458  *
1459  * Description:
1460  *      Display the given server label in three objects. The label is
1461  *      partitioned into three parts by '/'s and each part is copied
1462  *      into each label object.
1463  *
1464  * Returns:
1465  *      0 always.
1466  *----------------------------------------------------------------------*/
1467
1468 int
1469 display_Server_label(a_srcBuf, a_firstObj_o, a_secondObj_o, a_thirdObj_o)
1470 char *a_srcBuf;
1471 struct onode *a_firstObj_o;             /* first object */
1472 struct onode *a_secondObj_o;            /* second object */
1473 struct onode *a_thirdObj_o;             /* third object */
1474
1475 {       /* display_Server_label */
1476
1477    static char rn[] = "display_Server_label";
1478    char part[3][20];            /* buffer for three parts of label */
1479    char *strPtr;
1480    struct gator_lightobj *tmp_lightobj;
1481    struct onode *objPtr_o[3];
1482    int code;
1483    int strLen;
1484    int len;
1485    int i;
1486    int j;
1487
1488 /* the following debug statement floods the debug file */
1489 #ifdef DEBUG_DETAILED
1490     if (afsmon_debug) {
1491         fprintf(debugFD,"[ %s ] Called, a_srcBuf= %s, a_firstObj_o= %d, a_secondObj_o= %d, a_thirdObj_o= %d\n",
1492         rn, a_srcBuf, a_firstObj_o, a_secondObj_o, a_thirdObj_o);
1493         fflush(debugFD);
1494     }
1495 #endif
1496
1497
1498    /* break the label string into three parts */
1499
1500    part[0][0] = '\0'; part[1][0] = '\0'; part[2][0] = '\0';
1501    /* now for a dumb precaution */
1502
1503    strLen = strlen(a_srcBuf);
1504    len = 0;
1505    strPtr = a_srcBuf;
1506    for(i=0; i < 3; i++) {
1507         j = 0;
1508         while (*strPtr != '\0' && (len++ <= strLen)) {
1509                 if (*strPtr == '/') {
1510                         strPtr++; 
1511                         break;
1512                 }
1513                 else part[i][j] = *strPtr;
1514                 strPtr++;
1515                 j++;
1516         }
1517         part[i][j] = '\0';
1518    }
1519         
1520    /* 
1521    if (afsmon_debug) {
1522         fprintf(debugFD,"[ %s ] LABELS %s -> %s %s %s\n",
1523                 rn, a_srcBuf, part[0], part[1], part[2]);
1524         fflush(debugFD);
1525    }
1526    */
1527
1528    objPtr_o[0] = a_firstObj_o;
1529    objPtr_o[1] = a_secondObj_o;
1530    objPtr_o[2] = a_thirdObj_o;
1531
1532    /* display each label justified CENTER */
1533
1534    for (i = 0; i < 3; i++) {
1535    tmp_lightobj = (struct gator_lightobj *) objPtr_o[i]->o_data;
1536         code = justify_light(part[i], tmp_lightobj->label,
1537                 FC_COLUMN_WIDTH, CENTER, 1);
1538         if (code) {
1539                 if (afsmon_debug) {
1540                 fprintf(debugFD,"[ %s ] justify_light %d failed \n",rn,i);
1541                 fflush(debugFD);
1542                 }
1543         }
1544    }
1545
1546 }       /* display_Server_label */
1547
1548
1549
1550
1551
1552 /*-----------------------------------------------------------------------
1553  * fs_refresh()
1554  *
1555  * Description:
1556  *      Refresh the File Servers screen with the given page number starting
1557  *      at the given left-column number. The appropriate contents of 
1558  *      prev_fsData are displayed. 
1559  *      First the status labels at the four corners of the screen are
1560  *      updated. Next the column labels are updated and then each row
1561  *      of statistics.
1562  *      
1563  * Returns:
1564  *      Success: 0
1565  *      Failure: Exits afsmoitor on a severe error.
1566  *----------------------------------------------------------------------*/
1567
1568
1569 int
1570 fs_refresh(a_pageNum, a_LcolNum)
1571 int a_pageNum;          /* page to display */
1572 int a_LcolNum;          /* starting (leftmost) column number */
1573
1574 {       /* fs_refresh */
1575
1576    static char rn[] = "fs_refresh";     /* routine name */
1577    struct gator_lightobj *tmp_lightobj; /* ptr for object's display data */
1578    struct fs_Display_Data *fsDataP;     /* ptr to FS display data array */
1579    struct ServerInfo_line *tmp_fs_lines_P;      /* tmp ptr to fs_lines */
1580    struct onode **firstSlot_o_Ptr;      /* ptr to first data slot of a datum */
1581    struct onode **secondSlot_o_Ptr;     /* ptr to second data slot of a datum */
1582    struct onode **fsLabels_o_Ptr1;      /* ptr to label row 0 */
1583    struct onode **fsLabels_o_Ptr2;      /* ptr to label row 1 */
1584    struct onode **fsLabels_o_Ptr3;      /* ptr to label row 2 */
1585    char cmdLine[80];                    /* buffer for command line */
1586    char printBuf[256];                  /* buffer to print to screen */
1587    int i;
1588    int j;
1589    int k;
1590    int code;
1591    int fsIdx;
1592    int labelIdx;
1593    int dataIndex;                       /* index to the data[] field of 
1594                                         struct fs_Display_Data */
1595
1596    if (afsmon_debug) {
1597         fprintf(debugFD,"[ %s ] Called with row %d col %d \n",
1598                 rn, a_pageNum, a_LcolNum);
1599         fflush(debugFD);
1600    }
1601
1602
1603    /* if the data is not yet available, ie., not one probe cycle has 
1604    completed, do nothing */
1605
1606    if (! fs_Data_Available)
1607         return(0);
1608
1609
1610   /* validate the page number & column number */
1611   if (a_pageNum < 1 || a_pageNum > fs_numPages) {
1612         if (afsmon_debug) {
1613         fprintf(debugFD,"[ %s ] Called with wrong page # %d \n",rn, a_pageNum);
1614         fflush(debugFD);
1615         }
1616         afsmon_Exit(315);
1617    }
1618   if (a_LcolNum < 0 || a_LcolNum > fs_numCols) {
1619         if (afsmon_debug) {
1620         fprintf(debugFD,"[ %s ] Called with wrong column #%d\n",rn, a_LcolNum);
1621         fflush(debugFD);
1622         }
1623         afsmon_Exit(320);
1624    }
1625
1626    
1627
1628    /* update the fixed labels */
1629
1630    /* we reuse the ovw version lable and hence do not have to do anything
1631    for it here */
1632
1633    /* page number label */
1634    tmp_lightobj=(struct gator_lightobj *) fs_pageNum_o->o_data;
1635    sprintf(printBuf,"[File Servers, p. %d of %d, c. %d of %d]",
1636                 a_pageNum, fs_numPages, a_LcolNum +1, fs_numCols);      
1637    justify_light(printBuf,tmp_lightobj->label, FC_PAGENUM_O_WIDTH, 
1638                 RIGHT_JUSTIFY,1);
1639    gator_light_set(fs_pageNum_o,1);
1640
1641    /* file servers monitored label */
1642    tmp_lightobj=(struct gator_lightobj *) fs_numFS_o->o_data;
1643    sprintf(printBuf,"%d File Servers monitored, %d alerts on %d machines",
1644                 numFS, num_fs_alerts, numHosts_onfs_alerts);
1645    justify_light(printBuf,tmp_lightobj->label, FC_NUMHOSTS_O_WIDTH, CENTER,1);
1646    
1647
1648    /* command line */
1649
1650    /* figure out what we need to show in the prompt & set the page type */
1651    /* the fs_pageType variable is in turn used by the keyboard handler 
1652    routines to call fs_refresh() with the correct parameters */
1653
1654    fs_pageType = resolve_CmdLine( cmdLine, 1 /* fs frame*/, a_pageNum,
1655                 fs_numPages, fs_numCols, a_LcolNum, fs_cols_perPage);
1656
1657    /* display the command line */
1658    tmp_lightobj=(struct gator_lightobj *) fs_cmd_o->o_data;
1659    sprintf(printBuf,"%s", cmdLine);
1660    justify_light(printBuf,tmp_lightobj->label, strlen(printBuf)+1, 
1661                 LEFT_JUSTIFY,1);
1662    gator_light_set(fs_cmd_o, 1);
1663         
1664    /* update the probe number label */
1665    tmp_lightobj=(struct gator_lightobj *) fs_probeNum_o->o_data;
1666    sprintf(printBuf,"[FS probes %d, freq=%d sec]", 
1667         afsmon_fs_prev_probeNum, afsmon_probefreq);
1668    justify_light(printBuf,tmp_lightobj->label, FC_PROBENUM_O_WIDTH, 
1669                 RIGHT_JUSTIFY,1);
1670    gator_light_set(fs_probeNum_o, 1);
1671         
1672    /* update "columns on left" signal */
1673    tmp_lightobj=(struct gator_lightobj *) fs_leftArrows_o->o_data;
1674    if (fs_pageType & CMD_LEFT)
1675         strcpy(printBuf, "<<<");
1676    else
1677         strcpy(printBuf,"");
1678    justify_light(printBuf,tmp_lightobj->label, FC_ARROWS_O_WIDTH, 
1679                 LEFT_JUSTIFY,1);
1680    gator_light_set(fs_leftArrows_o, 0);
1681         
1682    /* update "columns on right" signal */
1683    tmp_lightobj=(struct gator_lightobj *) fs_rightArrows_o->o_data;
1684    if (fs_pageType & CMD_RIGHT)
1685         strcpy(printBuf, ">>>");
1686    else
1687         strcpy(printBuf,"");
1688    justify_light(printBuf,tmp_lightobj->label, FC_ARROWS_O_WIDTH, 
1689                 RIGHT_JUSTIFY,1);
1690    gator_light_set(fs_rightArrows_o, 0);
1691
1692
1693
1694    /* UPDATE THE COLUMN LABELS */
1695
1696    /* the column index is also used to index the label arrays */
1697    labelIdx = a_LcolNum;
1698
1699    /* get the pointers to the three arrays of label onodes */
1700    fsLabels_o_Ptr1 = fsLabels_o[0];
1701    fsLabels_o_Ptr2 = fsLabels_o[1];
1702    fsLabels_o_Ptr3 = fsLabels_o[2];
1703
1704    for(k=0; k < fs_cols_perPage; k++) {
1705
1706         if (labelIdx < fs_numCols) {
1707                 dataIndex = fs_Display_map[labelIdx];
1708                 code = display_Server_label( fs_labels[dataIndex], 
1709                                 *fsLabels_o_Ptr1,
1710                                 *fsLabels_o_Ptr2,
1711                                 *fsLabels_o_Ptr3);
1712
1713                 labelIdx++;     /* next label */
1714         } else {
1715                 code = display_Server_label( "//", 
1716                                 *fsLabels_o_Ptr1,
1717                                 *fsLabels_o_Ptr2,
1718                                 *fsLabels_o_Ptr3);
1719         }
1720
1721         fsLabels_o_Ptr1++;      /* next onode in label row 1 */
1722         fsLabels_o_Ptr2++;      /* next onode in label row 2 */
1723         fsLabels_o_Ptr3++;      /* next onode in label row 3 */
1724
1725    }    /* labels for each column */
1726
1727
1728     /* UPDATE THE FILE SERVER STATISTICS */
1729
1730    /* move to the right spot in the FS display data array */
1731    fsDataP = prev_fsData;
1732    fsIdx = 0;
1733    for(i=0; i < ((a_pageNum-1) * fs_numHosts_perPage); i++) {
1734         fsDataP++;
1735         fsIdx++;
1736    }
1737    
1738    if (fsIdx >= numFS) {        /* whoops! screwed up */
1739         sprintf(errMsg,"[ %s ] Programming error 1\n");
1740         afsmon_Exit(325);
1741    }
1742
1743    /* get the pointer to the first line of onodes of the file server frame */ 
1744    tmp_fs_lines_P = fs_lines;
1745
1746    for (i=0; i < fs_numHosts_perPage; i++) {
1747
1748
1749         /* if this is the last page we may not have file servers to fill up
1750         the page, so check the index */
1751         if (fsIdx < numFS) {    
1752
1753            if (fsDataP->hostName[0] == '\0') {
1754                 sprintf(errMsg,"[ %s ] empty fs display entry \n",rn);
1755                 afsmon_Exit(330);
1756                 }
1757
1758            /* display the hostname , first names only please! */
1759            
1760            sprintf(printBuf, fsDataP->hostName);
1761            for(j=0; j<strlen(printBuf); j++) {
1762                 if (printBuf[j] == '.') {
1763                         printBuf[j] = '\0';
1764                         break;
1765                 }
1766            }
1767
1768            tmp_lightobj=(struct gator_lightobj *)tmp_fs_lines_P->host_o->o_data;
1769            code = justify_light(printBuf,tmp_lightobj->label,
1770                 FC_HOSTNAME_O_WIDTH, LEFT_JUSTIFY, 1);
1771            if (code) {
1772                 fprintf(debugFD,"[ %s ] justify_code returned %d\n",rn, code);
1773                 fflush(debugFD);
1774            }
1775
1776            /* use the current column value to index into the fs_Display_map
1777            array to obtain the index of the item to display. check if its
1778            overflow flag is set and highlight if so. if the probe had failed
1779            enter "--" is all columns */
1780
1781            /* each host has two rows of slots for datums. get the pointers to 
1782            both the arrays */
1783
1784            firstSlot_o_Ptr = tmp_fs_lines_P->data_o[0];
1785            secondSlot_o_Ptr = tmp_fs_lines_P->data_o[1];
1786            fs_curr_RCol = a_LcolNum;    /* starting column number from which
1787                                 we are asked to display data */
1788
1789            for(j=0; j < fs_cols_perPage; j++) {         /* for each column */
1790
1791              /* if there is another column of data */
1792              if (fs_curr_RCol < fs_numCols) {
1793
1794                 dataIndex = fs_Display_map[fs_curr_RCol];
1795
1796                 code = display_Server_datum( fsDataP->data[dataIndex], 
1797                                 *firstSlot_o_Ptr,
1798                                 *secondSlot_o_Ptr,
1799                                 fsDataP->probeOK,
1800                                 RIGHT_JUSTIFY,
1801                                 fsDataP->threshOvf[dataIndex]);
1802
1803                 fs_curr_RCol++;
1804               } else    {       /* no more data, blank out columns */
1805                 code = display_Server_datum( "", 
1806                                 *firstSlot_o_Ptr,
1807                                 *secondSlot_o_Ptr,
1808                                 1,              /* probe ok */
1809                                 RIGHT_JUSTIFY,
1810                                 0);             /* no overflow */
1811                 }
1812
1813
1814                 firstSlot_o_Ptr++;              /* onode of next column */
1815                 secondSlot_o_Ptr++;             /* onode of next column */
1816
1817            }            /* for each column */
1818
1819            /* the loop could have taken the right-column-index one over,
1820            adjust it now */
1821            if (fs_curr_RCol == fs_numCols)
1822                 fs_curr_RCol--;
1823
1824         
1825         }               /* if fdIdx < numFS */
1826         
1827
1828         /* if fsIdx >= numFS , blank out all succeding rows */
1829
1830         if (fsIdx >= numFS) {
1831            
1832            /* blank out host name object */
1833            tmp_lightobj=(struct gator_lightobj *)tmp_fs_lines_P->host_o->o_data;
1834            code = justify_light("",tmp_lightobj->label,
1835                 FC_HOSTNAME_O_WIDTH, LEFT_JUSTIFY, 1);
1836            if (code) {
1837                 fprintf(debugFD,"[ %s ] justify_code returned %d\n",rn, code);
1838                 fflush(debugFD);
1839            }
1840
1841            firstSlot_o_Ptr = tmp_fs_lines_P->data_o[0];
1842            secondSlot_o_Ptr = tmp_fs_lines_P->data_o[1];
1843
1844            for (k=0; k<fs_cols_perPage; k++) {
1845                 code = display_Server_datum( "", 
1846                                 *firstSlot_o_Ptr,
1847                                 *secondSlot_o_Ptr,
1848                                 1,                      /* probe OK */
1849                                 RIGHT_JUSTIFY,
1850                                 0);                     /* dont highlight*/
1851
1852                 firstSlot_o_Ptr++;
1853                 secondSlot_o_Ptr++;
1854            }
1855
1856         }       /* fsIDx >= numFS */
1857
1858
1859        tmp_fs_lines_P++;        /* pointer to next line in the frame */
1860        fsDataP++;       /* next host's data */
1861        fsIdx++;         /* host index */
1862
1863
1864    }    /* for each row in the File Servers frame */
1865
1866    /* redraw the display if the File Servers screen is currently displayed */
1867    if(afsmon_win->w_frame == fsFrame)
1868         WOP_DISPLAY(afsmon_win);
1869
1870    /* update the global page & column numbers to reflect the changes */
1871    fs_currPage = a_pageNum;
1872    fs_curr_LCol = a_LcolNum;;
1873
1874    return(0);
1875
1876 }       /* fs_refresh */
1877
1878
1879
1880
1881 /*-----------------------------------------------------------------------
1882  * Switch_fs_2_ovw()
1883  *
1884  * Description:
1885  *      Switch from the File Server screen to the Overview Screen
1886  *----------------------------------------------------------------------*/
1887 int
1888 Switch_fs_2_ovw()
1889 {
1890    /* bind the overview frame to the window */
1891    gtxframe_SetFrame(afsmon_win,ovwFrame);
1892    return(0);
1893 }
1894
1895 /*-----------------------------------------------------------------------
1896  * Switch_fs_2_cm()
1897  *
1898  * Description:
1899  *      Switch from the File Server screen to the Cache Managers screen. 
1900  *----------------------------------------------------------------------*/
1901 int
1902 Switch_fs_2_cm()
1903 {
1904    if (fs_pageType & CMD_CM) {
1905         /* bind the overview Cache Managers to the window */
1906         gtxframe_SetFrame(afsmon_win,cmFrame);
1907    }
1908         return(0);
1909 }
1910
1911 /*-----------------------------------------------------------------------
1912  * Switch_fs_next()
1913  *
1914  * Description:
1915  *      Switch to next page of file server screen 
1916  *----------------------------------------------------------------------*/
1917 int
1918 Switch_fs_next()
1919 {
1920    static char rn[] = "Switch_fs_next";
1921
1922    if (fs_pageType & CMD_NEXT) {
1923         /* we have a next page, refresh with next page number */
1924         fs_refresh(fs_currPage+1, fs_curr_LCol);
1925   }
1926
1927   return(0);
1928 }
1929
1930 /*-----------------------------------------------------------------------
1931  * Switch_fs_last()
1932  *
1933  * Description:
1934  *      Switch to last page of file server screen 
1935  *----------------------------------------------------------------------*/
1936 int
1937 Switch_fs_last()
1938 {
1939    static char rn[] = "Switch_fs_last";
1940
1941
1942    if (fs_pageType & CMD_NEXT) {
1943         /* we have a next page, refresh with the last page number */
1944         fs_refresh(fs_numPages, fs_curr_LCol);
1945   }
1946
1947   return(0);
1948 }
1949
1950 /*-----------------------------------------------------------------------
1951  * Switch_fs_prev()
1952  *
1953  * Description:
1954  *      Switch to previous page of file server screen 
1955  *----------------------------------------------------------------------*/
1956 int
1957 Switch_fs_prev()
1958 {
1959    static char rn[] = "Switch_fs_prev";
1960
1961    if (fs_pageType & CMD_PREV) {
1962         /* we have a previous page, refresh with the rpevious page number */
1963         fs_refresh(fs_currPage -1, fs_curr_LCol);
1964   }
1965         return(0);
1966 }
1967
1968 /*-----------------------------------------------------------------------
1969  * Switch_fs_first()
1970  *
1971  * Description:
1972  *      Switch to first page of file server screen 
1973  *----------------------------------------------------------------------*/
1974 int
1975 Switch_fs_first()
1976 {
1977    static char rn[] = "Switch_fs_first";
1978
1979    if (fs_pageType & CMD_PREV) {
1980         /* we have a previous page, got to first page */
1981         fs_refresh(1 , fs_curr_LCol);
1982   }
1983         return(0);
1984 }
1985
1986 /*-----------------------------------------------------------------------
1987  * Switch_fs_left()
1988  *
1989  * Description:
1990  *      Scroll left on the file server screen 
1991  *----------------------------------------------------------------------*/
1992 int
1993 Switch_fs_left()
1994 {
1995    static char rn[] = "Switch_fs_left";
1996
1997    if (fs_pageType & CMD_LEFT) {
1998         /* we have columns on left, refresh with new column number */
1999         fs_refresh(fs_currPage, fs_curr_LCol - fs_cols_perPage);
2000    }
2001    return(0);
2002 }
2003
2004
2005 /*-----------------------------------------------------------------------
2006  * Switch_fs_leftmost()
2007  *
2008  * Description:
2009  *      Scroll to first column on  the file server screen 
2010  *----------------------------------------------------------------------*/
2011 int
2012 Switch_fs_leftmost()
2013 {
2014    static char rn[] = "Switch_fs_leftmost";
2015
2016    if (fs_pageType & CMD_LEFT) {
2017         /* we have columns on left, go to the first */
2018         fs_refresh(fs_currPage, 0);
2019    }
2020    return(0);
2021 }
2022
2023 /*-----------------------------------------------------------------------
2024  * Switch_fs_right()
2025  *
2026  * Description:
2027  *      Scroll right on the file server screen 
2028  *----------------------------------------------------------------------*/
2029 int
2030 Switch_fs_right()
2031 {
2032    static char rn[] = "Switch_fs_right";
2033
2034    if (fs_pageType & CMD_RIGHT) {
2035         /* we have columns on right, refresh with new column number */
2036         fs_refresh(fs_currPage, fs_curr_LCol + fs_cols_perPage);
2037    }
2038         return(0);
2039 }
2040
2041 /*-----------------------------------------------------------------------
2042  * Switch_fs_rightmost()
2043  *
2044  * Description:
2045  *      Scroll to last column on the file server screen 
2046  *----------------------------------------------------------------------*/
2047 int
2048 Switch_fs_rightmost()
2049 {
2050    static char rn[] = "Switch_fs_rightmost";
2051    int curr_LCol;
2052
2053
2054    if (fs_pageType & CMD_RIGHT) {
2055         /* we have columns on right, go to the last column */
2056         if (fs_numCols % fs_cols_perPage)
2057            curr_LCol = (fs_numCols / fs_cols_perPage) * fs_cols_perPage;
2058         else
2059            curr_LCol = ((fs_numCols / fs_cols_perPage)-1) * fs_cols_perPage;
2060
2061         fs_refresh(fs_currPage, curr_LCol);
2062    }
2063         return(0);
2064 }
2065
2066
2067 /*-----------------------------------------------------------------------
2068  * create_FSframe_objects()
2069  *
2070  * Description:
2071  *      Create the gtx objects (onodes) for the Fileservers frame and setup
2072  *      the keyboard bindings.
2073  *      Only as many objects as can fit on the display are created. The
2074  *      positions and lengths of all these objects are fixed at creation.
2075  *      These objects are updated with new data at the end of each probe
2076  *      cycle.
2077  *
2078  * Returns:
2079  *      Success: 0
2080  *      Failure: Exits afsmonitor.
2081  *----------------------------------------------------------------------*/
2082
2083 int
2084 create_FSframe_objects()
2085 {       /* create_FSframe_objects */
2086    static char rn[] = "create_FSframe_objects";
2087    struct ServerInfo_line *fs_lines_Ptr;        
2088    struct onode **fs_data_o_Ptr;        
2089    struct onode **fsLabels_o_Ptr;
2090    int x_pos;
2091    int y_pos;
2092    int code;
2093    int i;
2094    int j;
2095    int numBytes;
2096    int arrIdx;
2097
2098
2099     if (afsmon_debug) {
2100         fprintf(debugFD,"[ %s ] Called\n",rn);
2101         fflush(debugFD);
2102     }
2103
2104    /* create the command line object */
2105    fs_cmd_o = initLightObject("Command [oview, cm, prev, next, left, right] ? ",
2106                 0,maxY-1,FC_CMD_O_WIDTH,afsmon_win);
2107    if (fs_cmd_o == (struct onode *)0) {
2108         sprintf(errMsg,"[ %s ] Failed to create fs command onode\n",rn);
2109         afsmon_Exit(340);
2110    }
2111    code = gtxframe_AddToList(fsFrame,fs_cmd_o);
2112    code = gator_light_set(fs_cmd_o,HIGHLIGHT);
2113
2114    /* we already have the dimensions for the frame - same as the ovw frame */
2115    /* use the ovw program name object for the fs screen too */
2116
2117    code = gtxframe_AddToList(fsFrame, ovw_progName_o);
2118
2119
2120    /* create the page number object */
2121    fs_pageNum_o = initLightObject("[File Servers, p. X of X, c. Y of Y]",
2122                 maxX-FC_PAGENUM_O_WIDTH,0,FC_PAGENUM_O_WIDTH,afsmon_win);
2123    if (fs_pageNum_o == (struct onode *)0) {
2124         sprintf(errMsg,"[ %s ] Failed to create pageNumber onode\n",rn);
2125         afsmon_Exit(335);
2126    }
2127    code = gtxframe_AddToList(fsFrame,fs_pageNum_o);
2128    code = gator_light_set(fs_pageNum_o,HIGHLIGHT);
2129    
2130    /* create the probe number object */
2131    fs_probeNum_o = initLightObject("[FS probes 1, freq=30 sec]",
2132         maxX-FC_PROBENUM_O_WIDTH ,maxY-1, FC_PROBENUM_O_WIDTH, afsmon_win);
2133    if (fs_probeNum_o == (struct onode *)0) {
2134         sprintf(errMsg,"[ %s ] Failed to create fs probeNum onode\n",rn);
2135         afsmon_Exit(345);
2136    }
2137    code = gtxframe_AddToList(fsFrame,fs_probeNum_o);
2138    code = gator_light_set(fs_probeNum_o,HIGHLIGHT);
2139
2140
2141    /* create the numFS monitored object */
2142    fs_numFS_o = initLightObject(
2143                 "       0 File Servers monitored, 0 alerts on 0 machines",
2144                 4,2,FC_NUMHOSTS_O_WIDTH,afsmon_win);
2145    if (fs_numFS_o == (struct onode *)0) {
2146         sprintf(errMsg,"[ %s ] Failed to create numFS onode for the fs frame\n",
2147                 rn);
2148         afsmon_Exit(350);
2149    }
2150    code = gtxframe_AddToList(fsFrame,fs_numFS_o);
2151
2152    /* create the "more columns to left" indicator */
2153    fs_leftArrows_o = initLightObject("<<<", 0,2,FC_ARROWS_O_WIDTH, afsmon_win);
2154    if (fs_leftArrows_o == (struct onode *)0) {
2155         sprintf(errMsg,"[ %s ] Failed to create leftArrows onode for the fs frame\n", rn);
2156         afsmon_Exit(355);
2157    }
2158    code = gtxframe_AddToList(fsFrame,fs_leftArrows_o);
2159
2160    /* create the "more columns to right" indicator */
2161    fs_rightArrows_o = initLightObject(">>>", maxX-FC_ARROWS_O_WIDTH, 2,
2162                                 FC_ARROWS_O_WIDTH, afsmon_win);
2163    if (fs_rightArrows_o == (struct onode *)0) {
2164         sprintf(errMsg,"[ %s ] Failed to create rightArrows onode for the fs frame\n", rn);
2165         afsmon_Exit(360);
2166    }
2167    code = gtxframe_AddToList(fsFrame,fs_rightArrows_o);
2168
2169
2170
2171
2172    /* calculate the maximum number of hosts per page (2 rows per host) */
2173    fs_numHosts_perPage = (maxY - FC_NUM_FIXED_LINES) / 2;       
2174
2175    /* determine the number of data columns that can fit in a page */
2176    fs_cols_perPage = (maxX - FC_HOSTNAME_O_WIDTH ) / (FC_COLUMN_WIDTH);
2177
2178    if (afsmon_debug) {
2179         fprintf(debugFD,"[ %s ] fs_numHosts_perPage=%d fs_cols_perPage=%d\n",
2180                 rn,fs_numHosts_perPage, fs_cols_perPage);
2181         fflush(debugFD);
2182    }
2183
2184    /* the above two variables give us the information needed to create
2185    the objects for displaying the file server information */
2186
2187    /* allocate memory for all the onode pointers required to display
2188    the file server statistics */
2189
2190    numBytes = fs_numHosts_perPage * sizeof(struct ServerInfo_line);
2191    fs_lines = (struct ServerInfo_line *) malloc(numBytes);
2192    if (fs_lines == (struct ServerInfo_line *)0) {
2193         sprintf(errMsg,"[ %s ] Failed to allocate %d bytes for FS data lines\n",
2194                 rn, numBytes);
2195         afsmon_Exit(365);
2196    }
2197
2198    /* for each line of server statistics allocate memory to store two arrays 
2199    of data onodes */
2200
2201    fs_lines_Ptr = fs_lines;
2202    for(i=0; i<fs_numHosts_perPage; i++) {
2203    for(arrIdx=0; arrIdx<2; arrIdx++) {
2204         numBytes = fs_cols_perPage * sizeof(struct onode *);
2205         fs_lines_Ptr->data_o[arrIdx] = (struct onode **) malloc(numBytes);
2206         if (fs_lines_Ptr->data_o[arrIdx] == (struct onode **)0) {
2207         sprintf(errMsg,"[ %s ] Failed to allocate %d bytes for FS data onodes\n",
2208                 rn, numBytes);
2209         afsmon_Exit(370);
2210         }
2211    }
2212    fs_lines_Ptr++;
2213    }
2214
2215    /* now allocate the onodes itself */
2216
2217    fs_lines_Ptr = fs_lines;
2218    for(i=0; i<fs_numHosts_perPage; i++) {
2219
2220         /* initialize host name onode */
2221         fs_lines_Ptr->host_o = initLightObject("FSHostName",
2222                 0,FC_FIRST_HOST_ROW + 2*i, FC_HOSTNAME_O_WIDTH, afsmon_win);
2223         if (fs_lines_Ptr->host_o == (struct onode *)0) {
2224                 sprintf(errMsg,"[ %s ] Failed to create an FS name onode\n",rn);
2225                 afsmon_Exit(375);
2226         }
2227         code = gtxframe_AddToList(fsFrame, fs_lines_Ptr->host_o);
2228
2229         /* if (afsmon_debug) {
2230                 fprintf(debugFD,"[ %s ] Addr of host_o = %d for line %d\n",
2231                         rn,fs_lines_Ptr->host_o,i);
2232                 fflush(debugFD);
2233         } */
2234
2235         /* initialize data onodes for this host */
2236
2237         for(arrIdx=0; arrIdx<2; arrIdx++) {     /* for each array index */
2238
2239         fs_data_o_Ptr = fs_lines_Ptr->data_o[arrIdx];
2240         for(j=0; j<fs_cols_perPage; j++) {      /* for each column */
2241
2242                 char tmpBuf[20];
2243
2244                 /* determine x & y coordinate for this data object */
2245                 /* the 1's are for leaving a blank after each column */
2246                 x_pos = FC_HOSTNAME_O_WIDTH + (j * (FC_COLUMN_WIDTH));
2247                 y_pos = FC_FIRST_HOST_ROW + 2*i + arrIdx;
2248
2249                 sprintf(tmpBuf,"-FSData %d-",arrIdx);
2250                 *fs_data_o_Ptr = initLightObject(tmpBuf,
2251                         x_pos, y_pos, FC_COLUMN_WIDTH, afsmon_win);
2252                 if (*fs_data_o_Ptr == (struct onode *)0) {
2253                 sprintf(errMsg,"[ %s ] Failed to create an FS data onode\n",rn);
2254                 afsmon_Exit(380);
2255                 }
2256                 code = gtxframe_AddToList(fsFrame, *fs_data_o_Ptr);
2257
2258                 fs_data_o_Ptr++;
2259         }       /* for each column */
2260         }       /* for each onode array index */                        
2261
2262         fs_lines_Ptr++; 
2263    }    /* for each host slot */
2264
2265
2266    /* INITIALIZE COLUMN LABELS */
2267
2268
2269    /* allocate memory for two arrays of onode pointers for file server column
2270    labels */
2271    for( arrIdx=0; arrIdx < 3; arrIdx++) {
2272
2273    fsLabels_o[arrIdx] = (struct onode **) malloc(
2274                         sizeof(struct onode *) * fs_cols_perPage); 
2275    if (fsLabels_o[arrIdx] == (struct onode **)0) {
2276         sprintf(errMsg,"[ %s ] Failed to allocate memory for FS label onodes\n",
2277                 rn);
2278         afsmon_Exit(385);
2279    }
2280
2281    /* create cache manager name objects */
2282    fsLabels_o_Ptr = fsLabels_o[arrIdx];
2283    for (i=0; i< fs_cols_perPage; i++) {
2284         *fsLabels_o_Ptr = initLightObject("",
2285                 FC_HOSTNAME_O_WIDTH + i * FC_COLUMN_WIDTH,
2286                 FC_FIRST_LABEL_ROW + arrIdx, 
2287                 FC_COLUMN_WIDTH,afsmon_win);
2288
2289         if (*fsLabels_o_Ptr == (struct onode *)0) {
2290                 sprintf(errMsg,"[ %s ] Failed to create a FS label onode\n",rn);
2291                 afsmon_Exit(390);
2292         }
2293         code = gtxframe_AddToList(fsFrame,*fsLabels_o_Ptr);
2294         fsLabels_o_Ptr++;
2295    }
2296
2297    }
2298
2299
2300    /* initialize the column & page counters */
2301
2302    fs_currPage = 1;             
2303    fs_numCols = fs_DisplayItems_count;  
2304    fs_numPages = numFS / fs_numHosts_perPage;
2305    if (numFS % fs_numHosts_perPage)
2306         fs_numPages++;
2307    fs_curr_LCol = 0;    /* leftmost col */
2308    fs_curr_RCol = 0;    /* rightmost col */
2309
2310    /* create keyboard bindings */
2311    /* bind Q and \ 3 to exit */
2312    keymap_BindToString(fsFrame->keymap,"Q",afsmonExit_gtx,(char *)0,(char *)0);
2313    keymap_BindToString(fsFrame->keymap,"\ 3",afsmonExit_gtx,(char *)0,(char *)0);
2314
2315    /* o = overview, c = cm, n = next, p = prev, l = left, r = right 
2316       N = last page, P = first page, L = leftmost col, R = rightmost col */
2317
2318    keymap_BindToString(fsFrame->keymap,"o",Switch_fs_2_ovw,(char *)0,(char *)0);
2319    keymap_BindToString(fsFrame->keymap,"c",Switch_fs_2_cm,(char *)0,(char *)0);
2320    keymap_BindToString(fsFrame->keymap,"n",Switch_fs_next,(char *)0,(char *)0);
2321    keymap_BindToString(fsFrame->keymap,"N",Switch_fs_last,(char *)0,(char *)0);
2322    keymap_BindToString(fsFrame->keymap,"p",Switch_fs_prev,(char *)0,(char *)0);
2323    keymap_BindToString(fsFrame->keymap,"P",Switch_fs_first,(char *)0,(char *)0);
2324    keymap_BindToString(fsFrame->keymap,"l",Switch_fs_left,(char *)0,(char *)0);
2325    keymap_BindToString(fsFrame->keymap,"L",Switch_fs_leftmost,(char *)0,(char *)0);
2326    keymap_BindToString(fsFrame->keymap,"r",Switch_fs_right,(char *)0,(char *)0);
2327    keymap_BindToString(fsFrame->keymap,"R",Switch_fs_rightmost,(char *)0,(char *)0);
2328
2329    return(0);
2330 }       /* create_FSframe_objects */
2331
2332
2333 /*-----------------------------------------------------------------------
2334  * Function:    cm_refresh()
2335  *
2336  * Description:
2337  *      Refresh the Cache Managers screen with the given page number starting
2338  *      at the given left-column number. The appropriate contents of 
2339  *      prev_cmData are displayed. 
2340  *      First the status labels at the four corners of the screen are
2341  *      updated. Next the column labels are updated and then each row
2342  *      of statistics.
2343  *      
2344  * Returns:
2345  *      Success: 0
2346  *      Failure: Exits afsmoitor on a severe error.
2347  *----------------------------------------------------------------------*/
2348
2349 int
2350 cm_refresh(a_pageNum, a_LcolNum)
2351 int a_pageNum;          /* page to display */
2352 int a_LcolNum;          /* starting (leftmost) column number */
2353
2354 {       /* cm_refresh */
2355
2356    static char rn[] = "cm_refresh";     /* routine name */
2357    struct gator_lightobj *tmp_lightobj; /* ptr for object's display data */
2358    struct cm_Display_Data *cmDataP;     /* ptr to CM display data array */
2359    struct ServerInfo_line *tmp_cm_lines_P;      /* tmp ptr to cm_lines */
2360    struct onode **firstSlot_o_Ptr;      /* ptr to first data slot of a datum */
2361    struct onode **secondSlot_o_Ptr;     /* ptr to second data slot of a datum */
2362    struct onode **cmLabels_o_Ptr1;      /* ptr to label row 0 */
2363    struct onode **cmLabels_o_Ptr2;      /* ptr to label row 1 */
2364    struct onode **cmLabels_o_Ptr3;      /* ptr to label row 2 */
2365    char cmdLine[80];                    /* buffer for command line */
2366    char printBuf[256];                  /* buffer to print to screen */
2367    int i;
2368    int j;
2369    int k;
2370    int code;
2371    int cmIdx;
2372    int labelIdx;
2373    int dataIndex;                       /* index to the data[] field of 
2374                                         struct cm_Display_Data */
2375
2376    if (afsmon_debug) {
2377         fprintf(debugFD,"[ %s ] Called, a_pageNum= %d, a_LcolNum= %d \n",
2378                 rn, a_pageNum, a_LcolNum);
2379         fflush(debugFD);
2380    }
2381
2382
2383    /* if the data is not yet available, ie., not one probe cycle has 
2384    completed, do nothing */
2385
2386    if (! cm_Data_Available)
2387         return(0);
2388
2389
2390   /* validate the page number & column number */
2391   if (a_pageNum < 1 || a_pageNum > cm_numPages) {
2392         if (afsmon_debug) {
2393         fprintf(debugFD,"[ %s ] Called with wrong page # %d \n",rn, a_pageNum);
2394         fflush(debugFD);
2395         }
2396         afsmon_Exit(395);
2397    }
2398   if (a_LcolNum < 0 || a_LcolNum > cm_numCols) {
2399         if (afsmon_debug) {
2400         fprintf(debugFD,"[ %s ] Called with wrong column #%d\n",rn, a_LcolNum);
2401         fflush(debugFD);
2402         }
2403         afsmon_Exit(400);
2404    }
2405
2406    
2407
2408    /* update the fixed labels */
2409
2410    /* we reuse the ovw version lable and hence do not have to do anything
2411    for it here */
2412
2413    /* page number label */
2414    tmp_lightobj=(struct gator_lightobj *) cm_pageNum_o->o_data;
2415    sprintf(printBuf,"[Cache Managers, p.%d of %d, c.%d of %d]",
2416                 a_pageNum, cm_numPages, a_LcolNum +1, cm_numCols);      
2417    justify_light(printBuf,tmp_lightobj->label, FC_PAGENUM_O_WIDTH, 
2418                 RIGHT_JUSTIFY,1);
2419    gator_light_set(cm_pageNum_o,1);
2420
2421    /* file servers monitored label */
2422    tmp_lightobj=(struct gator_lightobj *) cm_numCM_o->o_data;
2423    sprintf(printBuf,"%d Cache Managers monitored, %d alerts on %d machines",
2424                 numCM, num_cm_alerts, numHosts_oncm_alerts);
2425    justify_light(printBuf,tmp_lightobj->label, FC_NUMHOSTS_O_WIDTH, CENTER,1);
2426    
2427
2428    /* command line */
2429
2430    /* figure out what we need to show in the prompt & set the page type */
2431    /* the cm_pageType variable is in turn used by the keyboard handler 
2432    routines to call cm_refresh() with the correct parameters */
2433
2434    cm_pageType = resolve_CmdLine( cmdLine, 2 /* cm frame */, a_pageNum,
2435                 cm_numPages, cm_numCols, a_LcolNum, cm_cols_perPage);
2436
2437    /* display the command line */
2438    tmp_lightobj=(struct gator_lightobj *) cm_cmd_o->o_data;
2439    sprintf(printBuf,"%s", cmdLine);
2440    justify_light(printBuf,tmp_lightobj->label, strlen(printBuf)+1, 
2441                 LEFT_JUSTIFY,1);
2442    gator_light_set(cm_cmd_o, 1);
2443         
2444    /* update the probe number label */
2445    tmp_lightobj=(struct gator_lightobj *) cm_probeNum_o->o_data;
2446    sprintf(printBuf,"[CM probes %d, freq=%d sec]", 
2447         afsmon_cm_prev_probeNum, afsmon_probefreq);
2448    justify_light(printBuf,tmp_lightobj->label, FC_PROBENUM_O_WIDTH, 
2449                 RIGHT_JUSTIFY,1);
2450    gator_light_set(cm_cmd_o, 1);
2451         
2452    /* update "columns on left" signal */
2453    tmp_lightobj=(struct gator_lightobj *) cm_leftArrows_o->o_data;
2454    if (cm_pageType & CMD_LEFT)
2455         strcpy(printBuf, "<<<");
2456    else
2457         strcpy(printBuf,"");
2458    justify_light(printBuf,tmp_lightobj->label, FC_ARROWS_O_WIDTH, 
2459                 LEFT_JUSTIFY,1);
2460    gator_light_set(cm_leftArrows_o, 0);
2461         
2462    /* update "columns on right" signal */
2463    tmp_lightobj=(struct gator_lightobj *) cm_rightArrows_o->o_data;
2464    if (cm_pageType & CMD_RIGHT)
2465         strcpy(printBuf, ">>>");
2466    else
2467         strcpy(printBuf,"");
2468    justify_light(printBuf,tmp_lightobj->label, FC_ARROWS_O_WIDTH, 
2469                 RIGHT_JUSTIFY,1);
2470    gator_light_set(cm_rightArrows_o, 0);
2471
2472
2473
2474    /* UPDATE THE COLUMN LABELS */
2475
2476    /* the column index is also used to index the label arrays */
2477    labelIdx = a_LcolNum;
2478
2479    /* get the pointers to the three arrays of label onodes */
2480    cmLabels_o_Ptr1 = cmLabels_o[0];
2481    cmLabels_o_Ptr2 = cmLabels_o[1];
2482    cmLabels_o_Ptr3 = cmLabels_o[2];
2483
2484    for(k=0; k < cm_cols_perPage; k++) {
2485
2486         if (labelIdx < cm_numCols) {
2487                 dataIndex = cm_Display_map[labelIdx];
2488                 code = display_Server_label( cm_labels[dataIndex], 
2489                                 *cmLabels_o_Ptr1,
2490                                 *cmLabels_o_Ptr2,
2491                                 *cmLabels_o_Ptr3);
2492
2493                 labelIdx++;     /* next label */
2494         } else {
2495                 code = display_Server_label( "//", 
2496                                 *cmLabels_o_Ptr1,
2497                                 *cmLabels_o_Ptr2,
2498                                 *cmLabels_o_Ptr3);
2499         }
2500
2501         cmLabels_o_Ptr1++;      /* next onode in label row 1 */
2502         cmLabels_o_Ptr2++;      /* next onode in label row 2 */
2503         cmLabels_o_Ptr3++;      /* next onode in label row 3 */
2504
2505    }    /* labels for each column */
2506
2507
2508     /* UPDATE THE FILE SERVER STATISTICS */
2509
2510    /* move to the right spot in the CM display data array */
2511    cmDataP = prev_cmData;
2512    cmIdx = 0;
2513    for(i=0; i < ((a_pageNum-1) * cm_numHosts_perPage); i++) {
2514         cmDataP++;
2515         cmIdx++;
2516    }
2517    
2518    if (cmIdx >= numCM) {        /* whoops! screwed up */
2519         sprintf(errMsg,"[ %s ] Programming error 1\n", rn);
2520         afsmon_Exit(405);
2521    }
2522
2523    /* get the pointer to the first line of onodes of the file server frame */ 
2524    tmp_cm_lines_P = cm_lines;
2525
2526    for (i=0; i < cm_numHosts_perPage; i++) {
2527
2528
2529         /* if this is the last page we may not have file servers to fill up
2530         the page, so check the index */
2531         if (cmIdx < numCM) {    
2532
2533            if (cmDataP->hostName[0] == '\0') {
2534                 sprintf(errMsg,"[ %s ] empty cm display entry \n",rn);
2535                 afsmon_Exit(410);
2536                 }
2537
2538            /* display the hostname , first names only please! */
2539            
2540            sprintf(printBuf, cmDataP->hostName);
2541            for(j=0; j<strlen(printBuf); j++) {
2542                 if (printBuf[j] == '.') {
2543                         printBuf[j] = '\0';
2544                         break;
2545                 }
2546            }
2547
2548            tmp_lightobj=(struct gator_lightobj *)tmp_cm_lines_P->host_o->o_data;
2549            code = justify_light(printBuf,tmp_lightobj->label,
2550                 FC_HOSTNAME_O_WIDTH, LEFT_JUSTIFY, 1);
2551            if (code) {
2552                 fprintf(debugFD,"[ %s ] justify_code returned %d\n",rn, code);
2553                 fflush(debugFD);
2554            }
2555
2556            /* use the current column value to index into the cm_Display_map
2557            array to obtain the index of the item to display. check if its
2558            overflow flag is set and highlight if so. if the probe had failed
2559            enter "--" is all columns */
2560
2561            /* each host has two rows of slots for datums. get the pointers to 
2562            both the arrays */
2563
2564            firstSlot_o_Ptr = tmp_cm_lines_P->data_o[0];
2565            secondSlot_o_Ptr = tmp_cm_lines_P->data_o[1];
2566            cm_curr_RCol = a_LcolNum;    /* starting column number from which
2567                                 we are asked to display data */
2568
2569            for(j=0; j < cm_cols_perPage; j++) {         /* for each column */
2570
2571              /* if there is another column of data */
2572              if (cm_curr_RCol < cm_numCols) {
2573
2574                 dataIndex = cm_Display_map[cm_curr_RCol];
2575
2576                 code = display_Server_datum( cmDataP->data[dataIndex], 
2577                                 *firstSlot_o_Ptr,
2578                                 *secondSlot_o_Ptr,
2579                                 cmDataP->probeOK,
2580                                 RIGHT_JUSTIFY,
2581                                 cmDataP->threshOvf[dataIndex]);
2582
2583                 cm_curr_RCol++;
2584               } else    {       /* no more data, blank out columns */
2585                 code = display_Server_datum( "", 
2586                                 *firstSlot_o_Ptr,
2587                                 *secondSlot_o_Ptr,
2588                                 1,                      /* probe ok */
2589                                 RIGHT_JUSTIFY,
2590                                 0);                     /* no overflow */
2591                 }
2592
2593
2594                 firstSlot_o_Ptr++;              /* onode of next column */
2595                 secondSlot_o_Ptr++;             /* onode of next column */
2596
2597            }            /* for each column */
2598
2599            /* the loop could have taken the right-column-index one over,
2600            adjust it now */
2601            if (cm_curr_RCol == cm_numCols)
2602                 cm_curr_RCol--;
2603
2604         
2605         }               /* if fdIdx < numCM */
2606         
2607
2608         /* if cmIdx >= numCM , blank out all succeding rows */
2609
2610         if (cmIdx >= numCM) {
2611            
2612            /* blank out host name object */
2613            tmp_lightobj=(struct gator_lightobj *)tmp_cm_lines_P->host_o->o_data;
2614            code = justify_light("",tmp_lightobj->label,
2615                 FC_HOSTNAME_O_WIDTH, LEFT_JUSTIFY, 1);
2616            if (code) {
2617                 fprintf(debugFD,"[ %s ] justify_code returned %d\n",rn, code);
2618                 fflush(debugFD);
2619            }
2620
2621            firstSlot_o_Ptr = tmp_cm_lines_P->data_o[0];
2622            secondSlot_o_Ptr = tmp_cm_lines_P->data_o[1];
2623
2624            for (k=0; k<cm_cols_perPage; k++) {
2625                 code = display_Server_datum( "", 
2626                                 *firstSlot_o_Ptr,
2627                                 *secondSlot_o_Ptr,
2628                                 1,                      /* probe OK */
2629                                 RIGHT_JUSTIFY,
2630                                 0);                     /* dont highlight*/
2631
2632                 firstSlot_o_Ptr++;
2633                 secondSlot_o_Ptr++;
2634            }
2635
2636         }       /* cmIDx >= numCM */
2637
2638
2639        tmp_cm_lines_P++;        /* pointer to next line in the frame */
2640        cmDataP++;       /* next host's data */
2641        cmIdx++;         /* host index */
2642
2643
2644    }    /* for each row in the Cache Manager frame */
2645
2646    /* redraw the display if the Cache Managers screen is currently displayed*/
2647    if(afsmon_win->w_frame == cmFrame)
2648         WOP_DISPLAY(afsmon_win);
2649
2650    /* update the global page & column numbers to reflect the changes */
2651    cm_currPage = a_pageNum;
2652    cm_curr_LCol = a_LcolNum;;
2653
2654    return(0);
2655
2656 }       /* cm_refresh */
2657
2658
2659
2660 /*-----------------------------------------------------------------------
2661  * Switch_cm_2_ovw()
2662  *
2663  * Description:
2664  *      Switch from the Cache Manager screen to the Overview Screen
2665  *----------------------------------------------------------------------*/
2666 int
2667 Switch_cm_2_ovw()
2668 {
2669    /* bind the overview frame to the window */
2670    gtxframe_SetFrame(afsmon_win,ovwFrame);
2671    return(0);
2672 }
2673
2674 /*-----------------------------------------------------------------------
2675  * Switch_cm_2_fs()
2676  *
2677  * Description:
2678  *      Switch from the Cache Manager screen to the File Servers screen 
2679  *----------------------------------------------------------------------*/
2680 int
2681 Switch_cm_2_fs()
2682 {
2683    if (cm_pageType & CMD_FS) {
2684         /* bind the file servers frame to the window */
2685         gtxframe_SetFrame(afsmon_win,fsFrame);
2686    }
2687         return(0);
2688 }
2689
2690 /*-----------------------------------------------------------------------
2691  * Switch_cm_next()
2692  *
2693  * Description:
2694  *      Switch to next page of cache managers screen 
2695  *----------------------------------------------------------------------*/
2696 int
2697 Switch_cm_next()
2698 {
2699    static char rn[] = "Switch_cm_next";
2700
2701    if (cm_pageType & CMD_NEXT) {
2702         /* we have a next page, refresh with next page number */
2703         cm_refresh(cm_currPage+1, cm_curr_LCol);
2704   }
2705
2706   return(0);
2707 }
2708
2709 /*-----------------------------------------------------------------------
2710  * Switch_cm_last()
2711  *
2712  * Description:
2713  *      Switch to last page of file server screen 
2714  *----------------------------------------------------------------------*/
2715 int
2716 Switch_cm_last()
2717 {
2718    static char rn[] = "Switch_cm_last";
2719
2720
2721    if (cm_pageType & CMD_NEXT) {
2722         /* we have a next page, refresh with last page number */
2723         cm_refresh(cm_numPages, cm_curr_LCol);
2724   }
2725
2726   return(0);
2727 }
2728
2729 /*-----------------------------------------------------------------------
2730  * Switch_cm_prev()
2731  *
2732  * Description:
2733  *      Switch to previous page of cache managers screen 
2734  *----------------------------------------------------------------------*/
2735 int
2736 Switch_cm_prev()
2737 {
2738    static char rn[] = "Switch_cm_prev";
2739
2740    if (cm_pageType & CMD_PREV) {
2741         /* we have a previous page, refresh to previous page */
2742         cm_refresh(cm_currPage-1, cm_curr_LCol);
2743   }
2744         return(0);
2745 }
2746
2747 /*-----------------------------------------------------------------------
2748  * Switch_cm_first()
2749  *
2750  * Description:
2751  *      Switch to first page of cache managers screen 
2752  *----------------------------------------------------------------------*/
2753 int
2754 Switch_cm_first()
2755 {
2756    static char rn[] = "Switch_cm_first";
2757
2758    if (cm_pageType & CMD_PREV) {
2759         /* we have a previous page, refresh to first page */
2760         cm_refresh(1, cm_curr_LCol);
2761   }
2762         return(0);
2763 }
2764
2765 /*-----------------------------------------------------------------------
2766  * Switch_cm_left()
2767  *
2768  * Description:
2769  *      Scroll left on the cache managers screen 
2770  *----------------------------------------------------------------------*/
2771 int
2772 Switch_cm_left()
2773 {
2774    static char rn[] = "Switch_cm_left";
2775
2776    if (cm_pageType & CMD_LEFT) {
2777         /* we have columns on left, refresh with new column number */
2778         cm_refresh(cm_currPage, cm_curr_LCol - cm_cols_perPage);
2779    }
2780    return(0);
2781 }
2782
2783
2784 /*-----------------------------------------------------------------------
2785  * Switch_cm_leftmost()
2786  *
2787  * Description:
2788  *      Scroll to first column on  the cache managers screen 
2789  *----------------------------------------------------------------------*/
2790 int
2791 Switch_cm_leftmost()
2792 {
2793    static char rn[] = "Switch_cm_leftmost";
2794
2795    if (cm_pageType & CMD_LEFT) {
2796         /* we have columns on left, go to the first column */
2797         cm_refresh(cm_currPage, 0);
2798    }
2799    return(0);
2800 }
2801
2802 /*-----------------------------------------------------------------------
2803  * Switch_cm_right()
2804  *
2805  * Description:
2806  *      Scroll right on the cache managers screen 
2807  *----------------------------------------------------------------------*/
2808 int
2809 Switch_cm_right()
2810 {
2811    static char rn[] = "Switch_cm_right";
2812
2813    if (cm_pageType & CMD_RIGHT) {
2814         /* we have columns on right, refresh with new column number */
2815         cm_refresh(cm_currPage, cm_curr_LCol + cm_cols_perPage);
2816    }
2817         return(0);
2818 }
2819
2820 /*-----------------------------------------------------------------------
2821  * Switch_cm_rightmost()
2822  *
2823  * Description:
2824  *      Scroll to last column on the cache managers screen 
2825  *----------------------------------------------------------------------*/
2826 int
2827 Switch_cm_rightmost()
2828 {
2829    static char rn[] = "Switch_cm_rightmost";
2830    int curr_LCol;
2831
2832
2833    if (cm_pageType & CMD_RIGHT) {
2834         /* we have columns on right, go to the last column */
2835         if (cm_numCols % cm_cols_perPage) 
2836            curr_LCol = (cm_numCols / cm_cols_perPage) * cm_cols_perPage;
2837         else 
2838         curr_LCol = ((cm_numCols / cm_cols_perPage)-1) * cm_cols_perPage;
2839         cm_refresh(cm_currPage, curr_LCol);
2840    }
2841         return(0);
2842 }
2843
2844
2845 /*-----------------------------------------------------------------------
2846  * create_CMframe_objects()
2847  *
2848  * Description:
2849  *      Create the gtx objects (onodes) for the Cache Managers frame and setup
2850  *      the keyboard bindings.
2851  *      Only as many objects as can fit on the display are created. The
2852  *      positions and lengths of all these objects are fixed at creation.
2853  *      These objects are updated with new data at the end of each probe
2854  *      cycle.
2855  *
2856  * Returns:
2857  *      Success: 0
2858  *      Failure: Exits afsmonitor.
2859  *----------------------------------------------------------------------*/
2860
2861 int
2862 create_CMframe_objects()
2863 {       /* create_CMframe_objects */
2864    static char rn[] = "create_CMframe_objects";
2865    struct ServerInfo_line *cm_lines_Ptr;        
2866    struct onode **cm_data_o_Ptr;        
2867    struct onode **cmLabels_o_Ptr;
2868    int x_pos;
2869    int y_pos;
2870    int code;
2871    int i;
2872    int j;
2873    int numBytes;
2874    int arrIdx;
2875
2876     if (afsmon_debug) {
2877         fprintf(debugFD,"[ %s ] Called\n",rn);
2878         fflush(debugFD);
2879     }
2880
2881
2882
2883    /* create the command line object */
2884    cm_cmd_o = initLightObject("Command [oview, fs, prev, next, left, right] ? ",
2885                 0,maxY-1,FC_CMD_O_WIDTH,afsmon_win);
2886    if (cm_cmd_o == (struct onode *)0) {
2887         sprintf(errMsg,"[ %s ] Failed to create cm command onode\n",rn);
2888         afsmon_Exit(420);
2889    }
2890    code = gtxframe_AddToList(cmFrame,cm_cmd_o);
2891    code = gator_light_set(cm_cmd_o,HIGHLIGHT);
2892
2893
2894    /* we already have the dimensions for the frame - same as the ovw frame */
2895    /* use the ovw program name object for the cm screen too */
2896
2897    code = gtxframe_AddToList(cmFrame, ovw_progName_o);
2898
2899
2900    /* create the page number object */
2901    cm_pageNum_o = initLightObject("[Cache Managers, p. X of X, c. Y of Y]",
2902                 maxX-FC_PAGENUM_O_WIDTH,0,FC_PAGENUM_O_WIDTH,afsmon_win);
2903    if (cm_pageNum_o == (struct onode *)0) {
2904         sprintf(errMsg,"[ %s ] Failed to create pageNumber onode\n",rn);
2905         afsmon_Exit(415);
2906    }
2907    code = gtxframe_AddToList(cmFrame,cm_pageNum_o);
2908    code = gator_light_set(cm_pageNum_o,HIGHLIGHT);
2909    
2910    /* create the probe number object */
2911    cm_probeNum_o = initLightObject("[CM probes 1, freq=30 sec]",
2912         maxX-FC_PROBENUM_O_WIDTH ,maxY-1, FC_PROBENUM_O_WIDTH, afsmon_win);
2913    if (cm_probeNum_o == (struct onode *)0) {
2914         sprintf(errMsg,"[ %s ] Failed to create cm probeNum onode\n",rn);
2915         afsmon_Exit(425);
2916    }
2917    code = gtxframe_AddToList(cmFrame,cm_probeNum_o);
2918    code = gator_light_set(cm_probeNum_o,HIGHLIGHT);
2919
2920
2921    /* create the numCM monitored object */
2922    cm_numCM_o = initLightObject(
2923                 "       0 Cache Mangers monitored, 0 alerts on 0 machines",
2924                 4,2,FC_NUMHOSTS_O_WIDTH,afsmon_win);
2925    if (cm_numCM_o == (struct onode *)0) {
2926         sprintf(errMsg,"[ %s ] Failed to create numCM onode for the cm frame\n",
2927                 rn);
2928         afsmon_Exit(430);
2929    }
2930    code = gtxframe_AddToList(cmFrame,cm_numCM_o);
2931
2932    /* create the "more columns to left" indicator */
2933    cm_leftArrows_o = initLightObject("<<<", 0,2,FC_ARROWS_O_WIDTH, afsmon_win);
2934    if (cm_leftArrows_o == (struct onode *)0) {
2935         sprintf(errMsg,"[ %s ] Failed to create leftArrows onode for the cm frame\n", rn);
2936         afsmon_Exit(435);
2937    }
2938    code = gtxframe_AddToList(cmFrame,cm_leftArrows_o);
2939
2940    /* create the "more columns to right" indicator */
2941    cm_rightArrows_o = initLightObject(">>>", maxX-FC_ARROWS_O_WIDTH, 2,
2942                                 FC_ARROWS_O_WIDTH, afsmon_win);
2943    if (cm_rightArrows_o == (struct onode *)0) {
2944         sprintf(errMsg,"[ %s ] Failed to create rightArrows onode for the cm frame\n", rn);
2945         afsmon_Exit(440);
2946    }
2947    code = gtxframe_AddToList(cmFrame,cm_rightArrows_o);
2948
2949
2950
2951
2952    /* calculate the maximum number of hosts per page (2 rows per host) */
2953    cm_numHosts_perPage = (maxY - FC_NUM_FIXED_LINES) / 2;       
2954
2955    /* determine the number of data columns that can fit in a page */
2956    cm_cols_perPage = (maxX - FC_HOSTNAME_O_WIDTH ) / (FC_COLUMN_WIDTH);
2957
2958    if (afsmon_debug) {
2959         fprintf(debugFD,"[ %s ] cm_numHosts_perPage=%d cm_cols_perPage=%d\n",
2960                 rn,cm_numHosts_perPage, cm_cols_perPage);
2961         fflush(debugFD);
2962    }
2963
2964    /* the above two variables give us the information needed to create
2965    the objects for displaying the file server information */
2966
2967    /* allocate memory for all the onode pointers required to display
2968    the file server statistics */
2969
2970    numBytes = cm_numHosts_perPage * sizeof(struct ServerInfo_line);
2971    cm_lines = (struct ServerInfo_line *) malloc(numBytes);
2972    if (cm_lines == (struct ServerInfo_line *)0) {
2973         sprintf(errMsg,"[ %s ] Failed to allocate %d bytes for CM data lines\n",
2974                 rn, numBytes);
2975         afsmon_Exit(445);
2976    }
2977
2978    /* for each line of server statistics allocate memory to store two arrays 
2979    of data onodes */
2980
2981    cm_lines_Ptr = cm_lines;
2982    for(i=0; i<cm_numHosts_perPage; i++) {
2983    for(arrIdx=0; arrIdx<2; arrIdx++) {
2984         numBytes = cm_cols_perPage * sizeof(struct onode *);
2985         cm_lines_Ptr->data_o[arrIdx] = (struct onode **) malloc(numBytes);
2986         if (cm_lines_Ptr->data_o[arrIdx] == (struct onode **)0) {
2987         sprintf(errMsg,"[ %s ] Failed to allocate %d bytes for CM data onodes\n",
2988                 rn, numBytes);
2989         afsmon_Exit(450);
2990         }
2991    }
2992    cm_lines_Ptr++;
2993    }
2994
2995    /* now allocate the onodes itself */
2996
2997    cm_lines_Ptr = cm_lines;
2998    for(i=0; i<cm_numHosts_perPage; i++) {
2999
3000         /* initialize host name onode */
3001         cm_lines_Ptr->host_o = initLightObject("CMHostName",
3002                 0,FC_FIRST_HOST_ROW + 2*i, FC_HOSTNAME_O_WIDTH, afsmon_win);
3003         if (cm_lines_Ptr->host_o == (struct onode *)0) {
3004                 sprintf(errMsg,"[ %s ] Failed to create an CM name onode\n",rn);
3005                 afsmon_Exit(455);
3006         }
3007         code = gtxframe_AddToList(cmFrame, cm_lines_Ptr->host_o);
3008
3009         /* if (afsmon_debug) {
3010                 fprintf(debugFD,"[ %s ] Addr of host_o = %d for line %d\n",
3011                         rn,cm_lines_Ptr->host_o,i);
3012                 fflush(debugFD);
3013         } */
3014
3015         /* initialize data onodes for this host */
3016
3017         for(arrIdx=0; arrIdx<2; arrIdx++) {     /* for each array index */
3018
3019         cm_data_o_Ptr = cm_lines_Ptr->data_o[arrIdx];
3020         for(j=0; j<cm_cols_perPage; j++) {      /* for each column */
3021
3022                 char tmpBuf[20];
3023
3024                 /* determine x & y coordinate for this data object */
3025                 /* the 1's are for leaving a blank after each column */
3026                 x_pos = FC_HOSTNAME_O_WIDTH + (j * (FC_COLUMN_WIDTH));
3027                 y_pos = FC_FIRST_HOST_ROW + 2*i + arrIdx;
3028
3029                 sprintf(tmpBuf,"-CMData %d-",arrIdx);
3030                 *cm_data_o_Ptr = initLightObject(tmpBuf,
3031                         x_pos, y_pos, FC_COLUMN_WIDTH, afsmon_win);
3032                 if (*cm_data_o_Ptr == (struct onode *)0) {
3033                 sprintf(errMsg,"[ %s ] Failed to create an CM data onode\n",rn);
3034                 afsmon_Exit(460);
3035                 }
3036                 code = gtxframe_AddToList(cmFrame, *cm_data_o_Ptr);
3037
3038                 cm_data_o_Ptr++;
3039         }       /* for each column */
3040         }       /* for each onode array index */                        
3041
3042         cm_lines_Ptr++; 
3043    }    /* for each host slot */
3044
3045
3046    /* INITIALIZE COLUMN LABELS */
3047
3048
3049    /* allocate memory for two arrays of onode pointers for file server column
3050    labels */
3051    for( arrIdx=0; arrIdx < 3; arrIdx++) {
3052
3053    cmLabels_o[arrIdx] = (struct onode **) malloc(
3054                         sizeof(struct onode *) * cm_cols_perPage); 
3055    if (cmLabels_o[arrIdx] == (struct onode **)0) {
3056         sprintf(errMsg,"[ %s ] Failed to allocate memory for CM label onodes\n",
3057                 rn);
3058         afsmon_Exit(465);
3059    }
3060
3061    /* create cache manager name objects */
3062    cmLabels_o_Ptr = cmLabels_o[arrIdx];
3063    for (i=0; i< cm_cols_perPage; i++) {
3064         *cmLabels_o_Ptr = initLightObject("",
3065                 FC_HOSTNAME_O_WIDTH + i * FC_COLUMN_WIDTH,
3066                 FC_FIRST_LABEL_ROW + arrIdx, 
3067                 FC_COLUMN_WIDTH,afsmon_win);
3068
3069         if (*cmLabels_o_Ptr == (struct onode *)0) {
3070                 sprintf(errMsg,"[ %s ] Failed to create a CM label onode\n",rn);
3071                 afsmon_Exit(470);
3072         }
3073         code = gtxframe_AddToList(cmFrame,*cmLabels_o_Ptr);
3074         cmLabels_o_Ptr++;
3075    }
3076
3077    }
3078
3079
3080
3081
3082
3083
3084    /* initialize the column & page counters */
3085
3086    cm_currPage = 1;             
3087    cm_numCols = cm_DisplayItems_count;  
3088    cm_numPages = numCM / cm_numHosts_perPage;
3089    if (numCM % cm_numHosts_perPage)
3090         cm_numPages++;
3091    cm_curr_LCol = 0;    /* leftmost col */
3092    cm_curr_RCol = 0;    /* rightmost col */
3093
3094    /* create keyboard bindings */
3095    /* bind Q and \ 3 to exit */
3096    keymap_BindToString(cmFrame->keymap,"Q",afsmonExit_gtx,(char *)0,(char *)0);
3097    keymap_BindToString(cmFrame->keymap,"\ 3",afsmonExit_gtx,(char *)0,(char *)0);
3098
3099    /* o = overview, c = cm, n = next, p = prev, l = left, r = right 
3100       N = last page, P = first page, L = leftmost col, R = rightmost col */
3101
3102    keymap_BindToString(cmFrame->keymap,"o",Switch_cm_2_ovw,(char *)0,(char *)0);
3103    keymap_BindToString(cmFrame->keymap,"f",Switch_cm_2_fs,(char *)0,(char *)0);
3104    keymap_BindToString(cmFrame->keymap,"n",Switch_cm_next,(char *)0,(char *)0);
3105    keymap_BindToString(cmFrame->keymap,"N",Switch_cm_last,(char *)0,(char *)0);
3106    keymap_BindToString(cmFrame->keymap,"p",Switch_cm_prev,(char *)0,(char *)0);
3107    keymap_BindToString(cmFrame->keymap,"P",Switch_cm_first,(char *)0,(char *)0);
3108    keymap_BindToString(cmFrame->keymap,"l",Switch_cm_left,(char *)0,(char *)0);
3109    keymap_BindToString(cmFrame->keymap,"L",Switch_cm_leftmost,(char *)0,(char *)0);
3110    keymap_BindToString(cmFrame->keymap,"r",Switch_cm_right,(char *)0,(char *)0);
3111    keymap_BindToString(cmFrame->keymap,"R",Switch_cm_rightmost,(char *)0,(char *)0);
3112
3113    return(0);
3114 }       /* create_CMframe_objects */
3115
3116
3117
3118 /*-----------------------------------------------------------------------
3119  * gtx_initialize()
3120  *
3121  * Description:
3122  *      Initialize the gtx package and call routines to create the objects
3123  *      for the overview, File Servers & Cache Managers screens.
3124  *----------------------------------------------------------------------*/
3125 int
3126 gtx_initialize() 
3127 {       /* gtx_initialize */
3128    static char rn[] = "gtx_initialize"; /* routine name */
3129    int code;
3130
3131     if (afsmon_debug) {
3132         fprintf(debugFD,"[ %s ] Called\n",rn);
3133         fflush(debugFD);
3134     }
3135
3136    afsmon_win = gtx_Init(0,-1); /* 0 => dont start input server,
3137                                    1 => use curses */
3138    if(afsmon_win == (struct gwin *)0) {
3139         sprintf(errMsg,"[ %s ] gtx initialization failed\n",rn);
3140         afsmon_Exit(475);
3141    }
3142    gtx_initialized = 1;
3143
3144    /* Create the Overview frame */
3145
3146    ovwFrame = gtxframe_Create();
3147    if (ovwFrame == (struct gtx_frame *)0) {
3148         sprintf(errMsg,"[ %s ] Failed to create overview frame\n",rn);
3149         afsmon_Exit(480);
3150    }
3151
3152    /* bind the overview frame to the window */
3153    gtxframe_SetFrame(afsmon_win,ovwFrame);
3154
3155    /* create overview frame objects */
3156    code = create_ovwFrame_objects();
3157    if (code) {
3158         sprintf(errMsg,"[ %s ] Error in creating ovw frame objects\n",rn);
3159         afsmon_Exit(485);
3160    }
3161
3162
3163    /* Create the File Server frame */
3164    fsFrame = gtxframe_Create();
3165    if (fsFrame == (struct gtx_frame *)0) {
3166         sprintf(errMsg,"[ %s ] Failed to create file server frame\n",rn);
3167         afsmon_Exit(490);
3168    }
3169
3170
3171    /* Create File Server frame objects */
3172    code = create_FSframe_objects();
3173    if (code) {
3174         sprintf(errMsg,"[ %s ] Error in creating FS frame objects\n",rn);
3175         afsmon_Exit(495);
3176    }
3177
3178    /* Create the Cache Managers frame */
3179    cmFrame = gtxframe_Create();
3180    if (cmFrame == (struct gtx_frame *)0) {
3181         sprintf(errMsg,"[ %s ] Failed to create Cache Managers frame\n",rn);
3182         afsmon_Exit(500);
3183    }
3184
3185    /* Create Cache Managers frame objects */
3186    code = create_CMframe_objects();
3187    if (code) {
3188         sprintf(errMsg,"[ %s ] Error in creating CM frame objects\n",rn);
3189         afsmon_Exit(505);
3190    }
3191
3192    /* misc initializations */
3193    sprintf(blankline,"%255s"," ");
3194
3195    return (0);  
3196 }       /* gtx_initialize */    
3197