prototypes-fixes-20020821
[openafs.git] / src / xstat / xstat_fs.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Description:
12  *      Implementation of the client side of the AFS File Server extended
13  *      statistics facility.
14  *
15  *------------------------------------------------------------------------*/
16
17 #include <afsconfig.h>
18 #include <afs/param.h>
19
20 RCSID("$Header$");
21
22 #include "xstat_fs.h"                   /*Interface for this module*/
23 #include <lwp.h>                        /*Lightweight process package*/
24
25 #ifdef HAVE_STRING_H
26 #include <string.h>
27 #else
28 #ifdef HAVE_STRINGS_H
29 #include <strings.h>
30 #endif
31 #endif
32
33 #define LWP_STACK_SIZE  (16 * 1024)
34
35 /*
36  * Routines we need that don't have explicit include file definitions.
37  */
38 extern int RXAFSCB_ExecuteRequest();    /*AFS callback dispatcher*/
39 extern char *hostutil_GetNameByINet();  /*Host parsing utility*/
40
41 /*
42  * Help out the linker by explicitly importing the callback routines
43  * File Servers may be lobbing at us.
44  */
45 extern afs_int32 SRXAFSCB_CallBack();
46 extern afs_int32 SRXAFSCB_InitCallBackState3();
47 extern afs_int32 SRXAFSCB_Probe();
48 extern afs_int32 SRXAFSCB_GetCE();
49 extern afs_int32 SRXAFSCB_GetLock();
50
51 /*
52  * Exported variables.
53  */
54 int xstat_fs_numServers;                        /*Num connected servers*/
55 struct xstat_fs_ConnectionInfo
56     *xstat_fs_ConnInfo;                         /*Ptr to connection array*/
57 int numCollections;                             /*Number of data collections*/
58 struct xstat_fs_ProbeResults xstat_fs_Results;  /*Latest probe results*/
59 char terminationEvent;                          /*One-shot termination event*/
60
61 afs_int32 xstat_fsData[AFS_MAX_XSTAT_LONGS];            /*Buffer for collected data*/
62
63 /*
64  * Private globals.
65  */
66 static int xstat_fs_ProbeFreqInSecs;            /*Probe freq. in seconds*/
67 static int xstat_fs_initflag = 0;               /*Was init routine called?*/
68 static int xstat_fs_debug = 0;                  /*Debugging output enabled?*/
69 static int xstat_fs_oneShot = 0;                /*One-shot operation?*/
70 static int (*xstat_fs_Handler)();               /*Probe handler routine*/
71 static PROCESS probeLWP_ID;                     /*Probe LWP process ID*/
72 static int xstat_fs_numCollections;             /*Number of desired collections*/
73 static afs_int32 *xstat_fs_collIDP;                     /*Ptr to collection IDs desired*/
74
75 /*
76  * We have to pass a port to Rx to start up our callback listener
77  * service, but 7001 is already taken up by the Cache Manager.  So,
78  * we make up our own.
79  */
80 #define XSTAT_FS_CBPORT 7101
81
82
83 /*------------------------------------------------------------------------
84  * [private] xstat_fs_CleanupInit
85  *
86  * Description:
87  *      Set up for recovery after an error in initialization (i.e.,
88  *      during a call to xstat_fs_Init.
89  *
90  * Arguments:
91  *      None.
92  *
93  * Returns:
94  *      0 on success,
95  *      Error value otherwise.
96  *
97  * Environment:
98  *      This routine is private to the module.
99  *
100  * Side Effects:
101  *      Zeros out basic data structures.
102  *------------------------------------------------------------------------*/
103
104 static int xstat_fs_CleanupInit()
105
106 { /*xstat_fs_CleanupInit*/
107
108     afs_int32 code;                     /*Return code from callback stubs*/
109     struct rx_call *rxcall;     /*Bogus param*/
110     AFSCBFids *Fids_Array;      /*Bogus param*/
111     AFSCBs *CallBack_Array;     /*Bogus param*/
112
113     xstat_fs_ConnInfo = (struct xstat_fs_ConnectionInfo *)0;
114     xstat_fs_Results.probeNum = 0;
115     xstat_fs_Results.probeTime = 0;
116     xstat_fs_Results.connP = (struct xstat_fs_ConnectionInfo *)0;
117     xstat_fs_Results.collectionNumber = 0;
118     xstat_fs_Results.data.AFS_CollData_len = AFS_MAX_XSTAT_LONGS;
119     xstat_fs_Results.data.AFS_CollData_val = (afs_int32 *)xstat_fsData;
120     xstat_fs_Results.probeOK = 0;
121
122     rxcall         = (struct rx_call *)0;
123     Fids_Array     = (AFSCBFids *)0;
124     CallBack_Array = (AFSCBs *)0;
125
126     /*
127      * Call each of the callback routines our module provides (in
128      * xstat_fs_callback.c) to make sure they're all there.
129      */
130     code = SRXAFSCB_CallBack(rxcall, Fids_Array, CallBack_Array);
131     if (code)
132         return(code);
133     code = SRXAFSCB_InitCallBackState3(rxcall, (afsUUID *) 0);
134     if (code)
135         return(code);
136     code = SRXAFSCB_Probe(rxcall);
137     return(code);
138
139 } /*xstat_fs_CleanupInit*/
140
141
142 /*------------------------------------------------------------------------
143  * [exported] xstat_fs_Cleanup
144  *
145  * Description:
146  *      Clean up our memory and connection state.
147  *
148  * Arguments:
149  *      int a_releaseMem : Should we free up malloc'ed areas?
150  *
151  * Returns:
152  *      0 on total success,
153  *      -1 if the module was never initialized, or there was a problem
154  *              with the xstat_fs connection array.
155  *
156  * Environment:
157  *      xstat_fs_numServers should be properly set.  We don't do anything
158  *      unless xstat_fs_Init() has already been called.
159  *
160  * Side Effects:
161  *      Shuts down Rx connections gracefully, frees allocated space
162  *      (if so directed).
163  *------------------------------------------------------------------------*/
164
165 int xstat_fs_Cleanup(a_releaseMem)
166     int a_releaseMem;
167
168 { /*xstat_fs_Cleanup*/
169
170     static char rn[] = "xstat_fs_Cleanup";      /*Routine name*/
171     int code;                                   /*Return code*/
172     int conn_idx;                               /*Current connection index*/
173     struct xstat_fs_ConnectionInfo *curr_conn;  /*Ptr to xstat_fs connection*/
174
175     /*
176      * Assume the best, but check the worst.
177      */
178     if (!xstat_fs_initflag) {
179         fprintf(stderr, "[%s] Refused; module not initialized\n", rn);
180         return(-1);
181     }
182     else
183         code = 0;
184
185     /*
186      * Take care of all Rx connections first.  Check to see that the
187      * server count is a legal value.
188      */
189     if (xstat_fs_numServers <= 0) {
190         fprintf(stderr,
191                 "[%s] Illegal number of servers (xstat_fs_numServers = %d)\n",
192                 rn, xstat_fs_numServers);
193         code = -1;
194     }
195     else {
196         if (xstat_fs_ConnInfo != (struct xstat_fs_ConnectionInfo *)0) {
197             /*
198              * The xstat_fs connection structure array exists.  Go through
199              * it and close up any Rx connections it holds.
200              */
201             curr_conn = xstat_fs_ConnInfo;
202             for (conn_idx = 0; conn_idx < xstat_fs_numServers; conn_idx++) {
203                 if (curr_conn->rxconn != (struct rx_connection *)0) {
204                     rx_DestroyConnection(curr_conn->rxconn);
205                     curr_conn->rxconn = (struct rx_connection *)0;
206                 }
207                 curr_conn++;
208             } /*for each xstat_fs connection*/
209         } /*xstat_fs connection structure exists*/
210     } /*Legal number of servers*/
211
212     /*
213      * If asked to, release the space we've allocated.
214      */
215     if (a_releaseMem) {
216         if (xstat_fs_ConnInfo != (struct xstat_fs_ConnectionInfo *)0)
217             free(xstat_fs_ConnInfo);
218     }
219
220     /*
221      * Return the news, whatever it is.
222      */
223     return(code);
224
225 } /*xstat_fs_Cleanup*/
226
227
228 /*------------------------------------------------------------------------
229  * [private] xstat_fs_LWP
230  *
231  * Description:
232  *      This LWP iterates over the server connections and gathers up
233  *      the desired statistics from each one on a regular basis.  When
234  *      the sweep is done, the associated handler function is called
235  *      to process the new data.
236  *
237  * Arguments:
238  *      None.
239  *
240  * Returns:
241  *      Nothing.
242  *
243  * Environment:
244  *      Started by xstat_fs_Init(), uses global structures and the
245  *      global private xstat_fs_oneShot variable.
246  *
247  * Side Effects:
248  *      Nothing interesting.
249  *------------------------------------------------------------------------*/
250
251 static void xstat_fs_LWP()
252
253 { /*xstat_fs_LWP*/
254
255     static char rn[] = "xstat_fs_LWP";          /*Routine name*/
256     register afs_int32 code;                            /*Results of calls*/
257     int oneShotCode;                            /*Result of one-shot signal*/
258     struct timeval tv;                          /*Time structure*/
259     int conn_idx;                               /*Connection index*/
260     struct xstat_fs_ConnectionInfo *curr_conn;  /*Current connection*/
261     afs_int32 srvVersionNumber;                 /*Xstat version #*/
262     afs_int32 clientVersionNumber;                      /*Client xstat version*/
263     afs_int32 numColls;                         /*Number of collections to get*/
264     afs_int32 *currCollIDP;                             /*Curr collection ID desired*/
265
266     static afs_int32 xstat_VersionNumber;               /*Version # of server*/
267
268     /*
269      * Set up some numbers we'll need.
270      */
271     clientVersionNumber = AFS_XSTAT_VERSION;
272
273     while (1) { /*Service loop*/
274         /*
275          * Iterate through the server connections, gathering data.
276          * Don't forget to bump the probe count and zero the statistics
277          * areas before calling the servers.
278          */
279         if (xstat_fs_debug)
280             printf("[%s] Waking up, getting data from %d server(s)\n",
281                    rn, xstat_fs_numServers);
282         curr_conn = xstat_fs_ConnInfo;
283         xstat_fs_Results.probeNum++;
284
285         for (conn_idx = 0; conn_idx < xstat_fs_numServers; conn_idx++) {
286             /*
287              * Grab the statistics for the current File Server, if the
288              * connection is valid.
289              */
290             if (xstat_fs_debug)
291                 printf("[%s] Getting collections from File Server '%s'\n",
292                        rn, curr_conn->hostName);
293             if (curr_conn->rxconn != (struct rx_connection *)0) {
294                 if (xstat_fs_debug)
295                     printf("[%s] Connection OK, calling RXAFS_GetXStats\n",
296                            rn);
297
298                 currCollIDP = xstat_fs_collIDP;
299                 for (numColls = 0;
300                      numColls < xstat_fs_numCollections;
301                      numColls++, currCollIDP++) {
302                     /*
303                      * Initialize the per-probe values.
304                      */
305                     if (xstat_fs_debug)
306                         printf("[%s] Asking for data collection %d\n",
307                                rn, *currCollIDP);
308                     xstat_fs_Results.collectionNumber = *currCollIDP;
309                     xstat_fs_Results.data.AFS_CollData_len = AFS_MAX_XSTAT_LONGS;
310                     memset(xstat_fs_Results.data.AFS_CollData_val, 0, AFS_MAX_XSTAT_LONGS * 4);
311                     
312                     xstat_fs_Results.connP = curr_conn;
313                     
314                     if (xstat_fs_debug) {
315                         printf("%s: Calling RXAFS_GetXStats, conn=0x%x, clientVersionNumber=%d, collectionNumber=%d, srvVersionNumberP=0x%x, timeP=0x%x, dataP=0x%x\n",
316                                rn, curr_conn->rxconn,
317                                clientVersionNumber,
318                                *currCollIDP,
319                                &srvVersionNumber,
320                                &(xstat_fs_Results.probeTime),
321                                &(xstat_fs_Results.data));
322                         printf("%s: [bufflen=%d, buffer at 0x%x]\n",
323                                rn,
324                                xstat_fs_Results.data.AFS_CollData_len,
325                                xstat_fs_Results.data.AFS_CollData_val);
326                     }
327
328                     xstat_fs_Results.probeOK =
329                         RXAFS_GetXStats(curr_conn->rxconn,
330                                         clientVersionNumber,
331                                         *currCollIDP,
332                                         &srvVersionNumber,
333                                         &(xstat_fs_Results.probeTime),
334                                         &(xstat_fs_Results.data));
335                     
336                     /*
337                      * Now that we (may) have the data for this connection,
338                      * call the associated handler function.  The handler does
339                      * not take any explicit parameters, but rather gets to the
340                      * goodies via some of the objects exported by this module.
341                      */
342                     if (xstat_fs_debug)
343                         printf("[%s] Calling handler routine.\n", rn);
344                     code = xstat_fs_Handler();
345                     if (code)
346                         fprintf(stderr,
347                                 "[%s] Handler returned error code %d\n",
348                                 rn, code);
349                     
350                 } /*For each collection*/
351             } /*Valid Rx connection*/
352             
353             /*
354              * Advance the xstat_fs connection pointer.
355              */
356             curr_conn++;
357
358         } /*For each xstat_fs connection*/
359
360         /*
361          * All (valid) connections have been probed.  Fall asleep for the
362          * prescribed number of seconds, unless we're a one-shot.  In
363          * that case, we need to signal our caller that we're done.
364          */
365         if (xstat_fs_debug)
366             printf("[%s] Polling complete for probe round %d.\n",
367                    rn, xstat_fs_Results.probeNum);
368
369         if (xstat_fs_oneShot) {
370             /*
371              * One-shot execution desired.  Signal our main procedure
372              * that we've finished our collection round.
373              */
374             if (xstat_fs_debug)
375                 printf("[%s] Signalling main process at 0x%x\n",
376                        rn, &terminationEvent);
377             oneShotCode = LWP_SignalProcess(&terminationEvent);
378             if (oneShotCode)
379                 fprintf(stderr,
380                         "[%s] Error %d from LWP_SignalProcess()",
381                         rn, oneShotCode);
382             break; /*from the perpetual while loop*/
383         } /*One-shot execution*/
384         else {
385             /*
386              * Continuous execution desired.  Sleep for the required
387              * number of seconds.
388              */
389             tv.tv_sec  = xstat_fs_ProbeFreqInSecs;
390             tv.tv_usec = 0;
391             if (xstat_fs_debug)
392                 printf("[%s] Falling asleep for %d seconds\n",
393                        rn, xstat_fs_ProbeFreqInSecs);
394             code = IOMGR_Select(0,      /*Num fids*/
395                                 0,      /*Descs ready for reading*/
396                                 0,      /*Descs ready for writing*/
397                                 0,      /*Descs w/exceptional conditions*/
398                                 &tv);   /*Ptr to timeout structure*/
399             if (code)
400                 fprintf(stderr,
401                         "[%s] IOMGR_Select returned code %d\n",
402                         rn, code);
403         } /*Continuous execution*/
404     } /*Service loop*/
405
406 } /*xstat_fs_LWP*/
407
408
409 /*------------------------------------------------------------------------
410  * [exported] xstat_fs_Init
411  *
412  * Description:
413  *      Initialize the xstat_fs module: set up Rx connections to the
414  *      given set of File Servers, start up the probe and callback LWPs,
415  *      and associate the routine to be called when a probe completes.
416  *      Also, let it know which collections you're interested in.
417  *
418  * Arguments:
419  *      int a_numServers                  : Num. servers to connect to.
420  *      struct sockaddr_in *a_socketArray : Array of server sockets.
421  *      int a_ProbeFreqInSecs             : Probe frequency in seconds.
422  *      int (*a_ProbeHandler)()           : Ptr to probe handler fcn.
423  *      int a_flags                       : Various flags.
424  *      int a_numCollections              : Number of collections desired.
425  *      afs_int32 *a_collIDP                      : Ptr to collection IDs.
426  *
427  * Returns:
428  *      0 on success,
429  *      -2 for (at least one) connection error,
430  *      LWP process creation code, if it failed,
431  *      -1 for other fatal errors.
432  *
433  * Environment:
434  *      *** MUST BE THE FIRST ROUTINE CALLED FROM THIS PACKAGE ***
435  *      Also, the server security object CBsecobj MUST be a static,
436  *      since it has to stick around after this routine exits.
437  *
438  * Side Effects:
439  *      Sets up just about everything.
440  *------------------------------------------------------------------------*/
441
442 int xstat_fs_Init(a_numServers, a_socketArray, a_ProbeFreqInSecs, a_ProbeHandler,
443                   a_flags, a_numCollections, a_collIDP)
444     int a_numServers;
445     struct sockaddr_in *a_socketArray;
446     int a_ProbeFreqInSecs;
447     int (*a_ProbeHandler)();
448     int a_flags;
449     int a_numCollections;
450     afs_int32 *a_collIDP;
451
452 { /*xstat_fs_Init*/
453
454     static char rn[] = "xstat_fs_Init";         /*Routine name*/
455     register afs_int32 code;                            /*Return value*/
456     static struct rx_securityClass *CBsecobj;   /*Callback security object*/
457     struct rx_securityClass *secobj;            /*Client security object*/
458     struct rx_service *rxsrv_afsserver;         /*Server for AFS*/
459     int arg_errfound;                           /*Argument error found?*/
460     int curr_srv;                               /*Current server idx*/
461     struct xstat_fs_ConnectionInfo *curr_conn;  /*Ptr to current conn*/
462     char *hostNameFound;                        /*Ptr to returned host name*/
463     int conn_err;                               /*Connection error?*/
464     int PortToUse;                              /*Callback port to use*/
465     int collIDBytes;                            /*Num bytes in coll ID array*/
466
467     /*
468      * If we've already been called, snicker at the bozo, gently
469      * remind him of his doubtful heritage, and return success.
470      */
471     if (xstat_fs_initflag) {
472         fprintf(stderr, "[%s] Called multiple times!\n", rn);
473         return(0);
474     }
475     else
476         xstat_fs_initflag = 1; 
477
478     /*
479      * Check the parameters for bogosities.
480      */
481     arg_errfound = 0;
482     if (a_numServers <= 0) {
483         fprintf(stderr, "[%s] Illegal number of servers: %d\n",
484                 rn, a_numServers);
485         arg_errfound = 1;
486     }
487     if (a_socketArray == (struct sockaddr_in *)0) {
488         fprintf(stderr, "[%s] Null server socket array argument\n", rn);
489         arg_errfound = 1;
490     }
491     if (a_ProbeFreqInSecs <= 0) {
492         fprintf(stderr, "[%s] Illegal probe frequency: %d\n",
493                 rn, a_ProbeFreqInSecs);
494         arg_errfound = 1;
495     }
496     if (a_ProbeHandler == (int (*)())0) {
497         fprintf(stderr, "[%s] Null probe handler function argument\n",
498                 rn);
499         arg_errfound = 1;
500     }
501     if (a_numCollections <= 0) {
502         fprintf(stderr, "[%s] Illegal collection count argument: %d\n",
503                 rn, a_numServers);
504         arg_errfound = 1;
505     }
506     if (a_collIDP == NULL) {
507         fprintf(stderr, "[%s] Null collection ID array argument\n", rn);
508         arg_errfound = 1;
509     }
510     if (arg_errfound)
511         return(-1);
512
513     /*
514      * Record our passed-in info.
515      */
516     xstat_fs_debug           = (a_flags & XSTAT_FS_INITFLAG_DEBUGGING);
517     xstat_fs_oneShot         = (a_flags & XSTAT_FS_INITFLAG_ONE_SHOT);
518     xstat_fs_numServers      = a_numServers;
519     xstat_fs_Handler         = a_ProbeHandler;
520     xstat_fs_ProbeFreqInSecs = a_ProbeFreqInSecs;
521     xstat_fs_numCollections  = a_numCollections;
522     collIDBytes = xstat_fs_numCollections * sizeof(afs_int32);
523     xstat_fs_collIDP         = (afs_int32 *)(malloc(collIDBytes));
524     memcpy(xstat_fs_collIDP, a_collIDP, collIDBytes);
525     if (xstat_fs_debug) {
526         printf("[%s] Asking for %d collection(s): ", rn, xstat_fs_numCollections);
527         for (curr_srv = 0; curr_srv < xstat_fs_numCollections; curr_srv++)
528             printf("%d ", *(xstat_fs_collIDP+curr_srv));
529         printf("\n");
530     }
531
532     /*
533      * Get ready in case we have to do a cleanup - basically, zero
534      * everything out.
535      */
536     code = xstat_fs_CleanupInit();
537     if (code)
538         return(code);
539
540     /*
541      * Allocate the necessary data structures and initialize everything
542      * else.
543      */
544     xstat_fs_ConnInfo =
545         (struct xstat_fs_ConnectionInfo *)
546             malloc(a_numServers * sizeof(struct xstat_fs_ConnectionInfo));
547     if (xstat_fs_ConnInfo == (struct xstat_fs_ConnectionInfo *)0) {
548         fprintf(stderr,
549                 "[%s] Can't allocate %d connection info structs (%d bytes)\n",
550                 rn, a_numServers,
551                 (a_numServers * sizeof(struct xstat_fs_ConnectionInfo)));
552         return(-1);     /*No cleanup needs to be done yet*/
553     }
554
555     /*
556      * Initialize the Rx subsystem, just in case nobody's done it.
557      */
558     if (xstat_fs_debug)
559         printf("[%s] Initializing Rx\n", rn);
560     PortToUse = XSTAT_FS_CBPORT;
561
562     do {
563         code = rx_Init(htons(PortToUse));
564         if (code) {
565             if (code == RX_ADDRINUSE) {
566                 if (xstat_fs_debug)
567                     fprintf(stderr,
568                             "[%s] Callback port %d in use, advancing\n",
569                             rn, PortToUse);
570                 PortToUse++;
571             }
572             else {
573                 fprintf(stderr, "[%s] Fatal error in rx_Init()\n", rn);
574                 return(-1);
575             }
576         }
577     } while (code);
578     if (xstat_fs_debug)
579         printf("[%s] Rx initialized on port %d\n", rn, PortToUse);
580
581     /*
582      * Create a null Rx server security object, to be used by the
583      * Callback listener.
584      */
585     CBsecobj = (struct rx_securityClass *)
586         rxnull_NewServerSecurityObject();
587     if (CBsecobj == (struct rx_securityClass *)0) {
588         fprintf(stderr,
589                 "[%s] Can't create callback listener's security object.\n",
590                 rn);
591         xstat_fs_Cleanup(1); /*Delete already-malloc'ed areas*/
592         return(-1);
593     }
594     if (xstat_fs_debug)
595         printf("[%s] Callback server security object created\n", rn);
596     
597     /*
598      * Create a null Rx client security object, to be used by the
599      * probe LWP.
600      */
601     secobj = rxnull_NewClientSecurityObject();
602     if (secobj == (struct rx_securityClass *)0) {
603         fprintf(stderr,
604                 "[%s] Can't create probe LWP client security object.\n",
605                 rn);
606         xstat_fs_Cleanup(1); /*Delete already-malloc'ed areas*/
607         return(-1);
608     }
609     if (xstat_fs_debug)
610         printf("[%s] Probe LWP client security object created\n", rn);
611
612     curr_conn = xstat_fs_ConnInfo;
613     conn_err = 0;
614     for (curr_srv = 0; curr_srv < a_numServers; curr_srv++) {
615         /*
616          * Copy in the socket info for the current server, resolve its
617          * printable name if possible.
618          */
619         if (xstat_fs_debug) {
620             printf("[%s] Copying in the following socket info:\n",
621                    rn);
622             printf("[%s] IP addr 0x%lx, port %d\n", rn,
623                    (a_socketArray + curr_srv)->sin_addr.s_addr,
624                    (a_socketArray + curr_srv)->sin_port);
625         }
626         memcpy(&(curr_conn->skt), a_socketArray + curr_srv, sizeof(struct sockaddr_in));
627         
628         hostNameFound =
629             hostutil_GetNameByINet(curr_conn->skt.sin_addr.s_addr);
630         if (hostNameFound == NULL) {
631             fprintf(stderr,
632                     "[%s] Can't map Internet address %lu to a string name\n",
633                     rn, curr_conn->skt.sin_addr.s_addr);
634             curr_conn->hostName[0] = '\0';
635         }
636         else {
637             strcpy(curr_conn->hostName, hostNameFound);
638             if (xstat_fs_debug)
639                 printf("[%s] Host name for server index %d is %s\n",
640                        rn, curr_srv, curr_conn->hostName);
641         }
642         
643         /*
644          * Make an Rx connection to the current server.
645          */
646         if (xstat_fs_debug)
647             printf("[%s] Connecting to srv idx %d, IP addr 0x%lx, port %d, service 1\n",
648                    rn, curr_srv, curr_conn->skt.sin_addr.s_addr,
649                    curr_conn->skt.sin_port);
650
651         curr_conn->rxconn =
652             rx_NewConnection(curr_conn->skt.sin_addr.s_addr, /*Server addr*/
653                              curr_conn->skt.sin_port,        /*Server port*/
654                              1,                              /*AFS service #*/
655                              secobj,                         /*Security obj*/
656                              0);                             /*# of above*/
657         if (curr_conn->rxconn == (struct rx_connection *)0) {
658             fprintf(stderr,
659                     "[%s] Can't create Rx connection to server '%s' (%lu)\n",
660                     rn, curr_conn->hostName, curr_conn->skt.sin_addr.s_addr);
661             conn_err = 1;
662         }
663         if (xstat_fs_debug)
664             printf("[%s] New connection at 0x%lx\n",
665                    rn, curr_conn->rxconn);
666
667         /*
668          * Bump the current xstat_fs connection to set up.
669          */
670         curr_conn++;
671
672     } /*for curr_srv*/
673
674     /*
675      * Create the AFS callback service (listener).
676      */
677     if (xstat_fs_debug)
678         printf("[%s] Creating AFS callback listener\n", rn);
679     rxsrv_afsserver =
680         rx_NewService(0,                        /*Use default port*/
681                       1,                        /*Service ID*/
682                       "afs",                    /*Service name*/
683                       &CBsecobj,                /*Ptr to security object(s)*/
684                       1,                        /*# of security objects*/
685                       RXAFSCB_ExecuteRequest);  /*Dispatcher*/
686     if (rxsrv_afsserver == (struct rx_service *)0) {
687         fprintf(stderr,
688                 "[%s] Can't create callback Rx service/listener\n",
689                 rn);
690         xstat_fs_Cleanup(1); /*Delete already-malloc'ed areas*/
691         return(-1);
692     }
693     if (xstat_fs_debug)
694         printf("[%s] Callback listener created\n", rn);
695
696     /*
697      * Start up the AFS callback service.
698      */
699     if (xstat_fs_debug)
700         printf("[%s] Starting up callback listener.\n", rn);
701     rx_StartServer(0); /*Don't donate yourself to LWP pool*/
702
703     /*
704      * Start up the probe LWP.
705      */
706     if (xstat_fs_debug)
707         printf("[%s] Creating the probe LWP\n", rn);
708     code =
709         LWP_CreateProcess(xstat_fs_LWP,         /*Function to start up*/
710                           LWP_STACK_SIZE,       /*Stack size in bytes*/
711                           1,                    /*Priority*/
712                           (void *) 0,           /*Parameters*/
713                           "xstat_fs Worker",    /*Name to use*/
714                           &probeLWP_ID);        /*Returned LWP process ID*/
715     if (code) {
716         fprintf(stderr,
717                 "[%s] Can't create xstat_fs LWP!  Error is %d\n",
718                 rn, code);
719         xstat_fs_Cleanup(1); /*Delete already-malloc'ed areas*/
720         return(code);
721     }
722     if (xstat_fs_debug)
723         printf("[%s] Probe LWP process structure located at 0x%x\n",
724                rn, probeLWP_ID);
725
726     /*
727      * Return the final results.
728      */
729     if (conn_err)
730         return(-2);
731     else
732         return(0);
733
734 } /*xstat_fs_Init*/
735
736
737 /*------------------------------------------------------------------------
738  * [exported] xstat_fs_ForceProbeNow
739  *
740  * Description:
741  *      Wake up the probe LWP, forcing it to execute a probe immediately.
742  *
743  * Arguments:
744  *      None.
745  *
746  * Returns:
747  *      0 on success,
748  *      Error value otherwise.
749  *
750  * Environment:
751  *      The module must have been initialized.
752  *
753  * Side Effects:
754  *      As advertised.
755  *------------------------------------------------------------------------*/
756
757 int xstat_fs_ForceProbeNow()
758
759 { /*xstat_fs_ForceProbeNow*/
760
761     static char rn[] = "xstat_fs_ForceProbeNow";        /*Routine name*/
762
763     /*
764      * There isn't a prayer unless we've been initialized.
765      */
766     if (!xstat_fs_initflag) {
767         fprintf(stderr, "[%s] Must call xstat_fs_Init first!\n", rn);
768         return(-1);
769     }
770
771     /*
772      * Kick the sucker in the side.
773      */
774     IOMGR_Cancel(probeLWP_ID);
775
776     /*
777      * We did it, so report the happy news.
778      */
779     return(0);
780
781 } /*xstat_fs_ForceProbeNow*/