/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
#include <afsconfig.h>
#include <afs/param.h>
-RCSID("$Header$");
-
-#include "xstat_fs.h" /*Interface for this module*/
-#include <lwp.h> /*Lightweight process package*/
-
-#define LWP_STACK_SIZE (16 * 1024)
+#include <roken.h>
+#include <afs/opr.h>
-/*
- * Routines we need that don't have explicit include file definitions.
- */
-extern int RXAFSCB_ExecuteRequest(); /*AFS callback dispatcher*/
-extern char *hostutil_GetNameByINet(); /*Host parsing utility*/
+#include "xstat_fs.h" /*Interface for this module */
+#include <pthread.h>
-/*
- * Help out the linker by explicitly importing the callback routines
- * File Servers may be lobbing at us.
- */
-extern afs_int32 SRXAFSCB_CallBack();
-extern afs_int32 SRXAFSCB_InitCallBackState3();
-extern afs_int32 SRXAFSCB_Probe();
-extern afs_int32 SRXAFSCB_GetCE();
-extern afs_int32 SRXAFSCB_GetLock();
+#include <afs/afsutil.h>
+#include <afs/afscbint.h>
/*
* Exported variables.
*/
-int xstat_fs_numServers; /*Num connected servers*/
+int xstat_fs_numServers; /*Num connected servers */
struct xstat_fs_ConnectionInfo
- *xstat_fs_ConnInfo; /*Ptr to connection array*/
-int numCollections; /*Number of data collections*/
-struct xstat_fs_ProbeResults xstat_fs_Results; /*Latest probe results*/
-char terminationEvent; /*One-shot termination event*/
+ *xstat_fs_ConnInfo; /*Ptr to connection array */
+struct xstat_fs_ProbeResults xstat_fs_Results; /*Latest probe results */
-afs_int32 xstat_fsData[AFS_MAX_XSTAT_LONGS]; /*Buffer for collected data*/
+afs_int32 xstat_fsData[AFS_MAX_XSTAT_LONGS]; /*Buffer for collected data */
/*
* Private globals.
*/
-static int xstat_fs_ProbeFreqInSecs; /*Probe freq. in seconds*/
-static int xstat_fs_initflag = 0; /*Was init routine called?*/
-static int xstat_fs_debug = 0; /*Debugging output enabled?*/
-static int xstat_fs_oneShot = 0; /*One-shot operation?*/
-static int (*xstat_fs_Handler)(); /*Probe handler routine*/
-static PROCESS probeLWP_ID; /*Probe LWP process ID*/
-static int xstat_fs_numCollections; /*Number of desired collections*/
-static afs_int32 *xstat_fs_collIDP; /*Ptr to collection IDs desired*/
-
-/*
- * We have to pass a port to Rx to start up our callback listener
- * service, but 7001 is already taken up by the Cache Manager. So,
- * we make up our own.
- */
-#define XSTAT_FS_CBPORT 7101
+static int xstat_fs_ProbeFreqInSecs; /*Probe freq. in seconds */
+static int xstat_fs_initflag = 0; /*Was init routine called? */
+static int xstat_fs_debug = 0; /*Debugging output enabled? */
+static int xstat_fs_oneShot = 0; /*One-shot operation? */
+static int (*xstat_fs_Handler) (void); /*Probe handler routine */
+static pthread_t xstat_fs_thread; /*Probe thread */
+static int xstat_fs_numCollections; /*Number of desired collections */
+static afs_int32 *xstat_fs_collIDP; /*Ptr to collection IDs desired */
+static opr_mutex_t xstat_fs_force_lock; /*Lock to wakeup probe */
+static opr_cv_t xstat_fs_force_cv; /*Condvar to wakeup probe */
/*------------------------------------------------------------------------
* Zeros out basic data structures.
*------------------------------------------------------------------------*/
-static int xstat_fs_CleanupInit()
-
-{ /*xstat_fs_CleanupInit*/
-
- afs_int32 code; /*Return code from callback stubs*/
- struct rx_call *rxcall; /*Bogus param*/
- AFSCBFids *Fids_Array; /*Bogus param*/
- AFSCBs *CallBack_Array; /*Bogus param*/
+static int
+xstat_fs_CleanupInit(void)
+{
+ afs_int32 code; /*Return code from callback stubs */
+ struct rx_call *rxcall; /*Bogus param */
+ AFSCBFids *Fids_Array; /*Bogus param */
+ AFSCBs *CallBack_Array; /*Bogus param */
xstat_fs_ConnInfo = (struct xstat_fs_ConnectionInfo *)0;
xstat_fs_Results.probeNum = 0;
xstat_fs_Results.connP = (struct xstat_fs_ConnectionInfo *)0;
xstat_fs_Results.collectionNumber = 0;
xstat_fs_Results.data.AFS_CollData_len = AFS_MAX_XSTAT_LONGS;
- xstat_fs_Results.data.AFS_CollData_val = (afs_int32 *)xstat_fsData;
+ xstat_fs_Results.data.AFS_CollData_val = (afs_int32 *) xstat_fsData;
xstat_fs_Results.probeOK = 0;
- rxcall = (struct rx_call *)0;
- Fids_Array = (AFSCBFids *)0;
- CallBack_Array = (AFSCBs *)0;
+ rxcall = (struct rx_call *)0;
+ Fids_Array = (AFSCBFids *) 0;
+ CallBack_Array = (AFSCBs *) 0;
/*
* Call each of the callback routines our module provides (in
*/
code = SRXAFSCB_CallBack(rxcall, Fids_Array, CallBack_Array);
if (code)
- return(code);
+ return (code);
code = SRXAFSCB_InitCallBackState3(rxcall, (afsUUID *) 0);
if (code)
- return(code);
+ return (code);
code = SRXAFSCB_Probe(rxcall);
- return(code);
-
-} /*xstat_fs_CleanupInit*/
+ return (code);
+}
/*------------------------------------------------------------------------
* (if so directed).
*------------------------------------------------------------------------*/
-int xstat_fs_Cleanup(a_releaseMem)
- int a_releaseMem;
-
-{ /*xstat_fs_Cleanup*/
-
- static char rn[] = "xstat_fs_Cleanup"; /*Routine name*/
- int code; /*Return code*/
- int conn_idx; /*Current connection index*/
- struct xstat_fs_ConnectionInfo *curr_conn; /*Ptr to xstat_fs connection*/
+int
+xstat_fs_Cleanup(int a_releaseMem)
+{
+ static char rn[] = "xstat_fs_Cleanup"; /*Routine name */
+ int code; /*Return code */
+ int conn_idx; /*Current connection index */
+ struct xstat_fs_ConnectionInfo *curr_conn; /*Ptr to xstat_fs connection */
/*
* Assume the best, but check the worst.
*/
if (!xstat_fs_initflag) {
fprintf(stderr, "[%s] Refused; module not initialized\n", rn);
- return(-1);
- }
- else
+ return (-1);
+ } else
code = 0;
/*
"[%s] Illegal number of servers (xstat_fs_numServers = %d)\n",
rn, xstat_fs_numServers);
code = -1;
- }
- else {
+ } else {
if (xstat_fs_ConnInfo != (struct xstat_fs_ConnectionInfo *)0) {
/*
* The xstat_fs connection structure array exists. Go through
curr_conn->rxconn = (struct rx_connection *)0;
}
curr_conn++;
- } /*for each xstat_fs connection*/
- } /*xstat_fs connection structure exists*/
- } /*Legal number of servers*/
+ } /*for each xstat_fs connection */
+ } /*xstat_fs connection structure exists */
+ } /*Legal number of servers */
/*
* If asked to, release the space we've allocated.
/*
* Return the news, whatever it is.
*/
- return(code);
-
-} /*xstat_fs_Cleanup*/
+ return (code);
+}
/*------------------------------------------------------------------------
* [private] xstat_fs_LWP
*
* Description:
- * This LWP iterates over the server connections and gathers up
+ * This thread iterates over the server connections and gathers up
* the desired statistics from each one on a regular basis. When
* the sweep is done, the associated handler function is called
* to process the new data.
* Nothing interesting.
*------------------------------------------------------------------------*/
-static void xstat_fs_LWP()
-
-{ /*xstat_fs_LWP*/
-
- static char rn[] = "xstat_fs_LWP"; /*Routine name*/
- register afs_int32 code; /*Results of calls*/
- int oneShotCode; /*Result of one-shot signal*/
- struct timeval tv; /*Time structure*/
- int conn_idx; /*Connection index*/
- struct xstat_fs_ConnectionInfo *curr_conn; /*Current connection*/
- afs_int32 srvVersionNumber; /*Xstat version #*/
- afs_int32 clientVersionNumber; /*Client xstat version*/
- afs_int32 numColls; /*Number of collections to get*/
- afs_int32 *currCollIDP; /*Curr collection ID desired*/
-
- static afs_int32 xstat_VersionNumber; /*Version # of server*/
+static void *
+xstat_fs_LWP(void *unused)
+{
+ static char rn[] = "xstat_fs_thread"; /*Routine name */
+ afs_int32 code; /*Results of calls */
+ struct timeval tv; /*Time structure */
+ struct timespec wait; /*Time to wait */
+ int conn_idx; /*Connection index */
+ struct xstat_fs_ConnectionInfo *curr_conn; /*Current connection */
+ afs_int32 srvVersionNumber; /*Xstat version # */
+ afs_int32 clientVersionNumber; /*Client xstat version */
+ afs_int32 numColls; /*Number of collections to get */
+ afs_int32 *currCollIDP; /*Curr collection ID desired */
/*
* Set up some numbers we'll need.
*/
clientVersionNumber = AFS_XSTAT_VERSION;
- while (1) { /*Service loop*/
+ while (1) { /*Service loop */
/*
* Iterate through the server connections, gathering data.
* Don't forget to bump the probe count and zero the statistics
* areas before calling the servers.
*/
if (xstat_fs_debug)
- printf("[%s] Waking up, getting data from %d server(s)\n",
- rn, xstat_fs_numServers);
+ printf("[%s] Waking up, getting data from %d server(s)\n", rn,
+ xstat_fs_numServers);
curr_conn = xstat_fs_ConnInfo;
xstat_fs_Results.probeNum++;
* connection is valid.
*/
if (xstat_fs_debug)
- printf("[%s] Getting collections from File Server '%s'\n",
- rn, curr_conn->hostName);
+ printf("[%s] Getting collections from File Server '%s'\n", rn,
+ curr_conn->hostName);
if (curr_conn->rxconn != (struct rx_connection *)0) {
if (xstat_fs_debug)
printf("[%s] Connection OK, calling RXAFS_GetXStats\n",
rn);
currCollIDP = xstat_fs_collIDP;
- for (numColls = 0;
- numColls < xstat_fs_numCollections;
+ for (numColls = 0; numColls < xstat_fs_numCollections;
numColls++, currCollIDP++) {
/*
* Initialize the per-probe values.
*/
if (xstat_fs_debug)
- printf("[%s] Asking for data collection %d\n",
- rn, *currCollIDP);
+ printf("[%s] Asking for data collection %d\n", rn,
+ *currCollIDP);
xstat_fs_Results.collectionNumber = *currCollIDP;
- xstat_fs_Results.data.AFS_CollData_len = AFS_MAX_XSTAT_LONGS;
- memset(xstat_fs_Results.data.AFS_CollData_val, 0, AFS_MAX_XSTAT_LONGS * 4);
-
+ xstat_fs_Results.data.AFS_CollData_len =
+ AFS_MAX_XSTAT_LONGS;
+ memset(xstat_fs_Results.data.AFS_CollData_val, 0,
+ AFS_MAX_XSTAT_LONGS * 4);
+
xstat_fs_Results.connP = curr_conn;
-
+
if (xstat_fs_debug) {
- printf("%s: Calling RXAFS_GetXStats, conn=0x%x, clientVersionNumber=%d, collectionNumber=%d, srvVersionNumberP=0x%x, timeP=0x%x, dataP=0x%x\n",
- rn, curr_conn->rxconn,
- clientVersionNumber,
- *currCollIDP,
- &srvVersionNumber,
- &(xstat_fs_Results.probeTime),
- &(xstat_fs_Results.data));
- printf("%s: [bufflen=%d, buffer at 0x%x]\n",
- rn,
+ printf
+ ("%s: Calling RXAFS_GetXStats, conn=%p, clientVersionNumber=%d, collectionNumber=%d, srvVersionNumberP=%p, timeP=%p, dataP=%p\n",
+ rn, curr_conn->rxconn, clientVersionNumber,
+ *currCollIDP, &srvVersionNumber,
+ &(xstat_fs_Results.probeTime),
+ &(xstat_fs_Results.data));
+ printf("%s: [bufflen=%d, buffer at %p]\n", rn,
xstat_fs_Results.data.AFS_CollData_len,
xstat_fs_Results.data.AFS_CollData_val);
}
xstat_fs_Results.probeOK =
RXAFS_GetXStats(curr_conn->rxconn,
- clientVersionNumber,
- *currCollIDP,
+ clientVersionNumber, *currCollIDP,
&srvVersionNumber,
&(xstat_fs_Results.probeTime),
&(xstat_fs_Results.data));
-
+
/*
* Now that we (may) have the data for this connection,
* call the associated handler function. The handler does
code = xstat_fs_Handler();
if (code)
fprintf(stderr,
- "[%s] Handler returned error code %d\n",
- rn, code);
-
- } /*For each collection*/
- } /*Valid Rx connection*/
-
+ "[%s] Handler returned error code %d\n", rn,
+ code);
+
+ } /*For each collection */
+ }
+
+ /*Valid Rx connection */
/*
* Advance the xstat_fs connection pointer.
*/
curr_conn++;
- } /*For each xstat_fs connection*/
+ } /*For each xstat_fs connection */
/*
* All (valid) connections have been probed. Fall asleep for the
* that case, we need to signal our caller that we're done.
*/
if (xstat_fs_debug)
- printf("[%s] Polling complete for probe round %d.\n",
- rn, xstat_fs_Results.probeNum);
+ printf("[%s] Polling complete for probe round %d.\n", rn,
+ xstat_fs_Results.probeNum);
if (xstat_fs_oneShot) {
/*
- * One-shot execution desired. Signal our main procedure
- * that we've finished our collection round.
+ * One-shot execution desired.
*/
- if (xstat_fs_debug)
- printf("[%s] Signalling main process at 0x%x\n",
- rn, &terminationEvent);
- oneShotCode = LWP_SignalProcess(&terminationEvent);
- if (oneShotCode)
- fprintf(stderr,
- "[%s] Error %d from LWP_SignalProcess()",
- rn, oneShotCode);
- break; /*from the perpetual while loop*/
- } /*One-shot execution*/
- else {
+ break;
+ } else {
/*
* Continuous execution desired. Sleep for the required
- * number of seconds.
+ * number of seconds or wakeup sooner if forced.
*/
- tv.tv_sec = xstat_fs_ProbeFreqInSecs;
- tv.tv_usec = 0;
- if (xstat_fs_debug)
- printf("[%s] Falling asleep for %d seconds\n",
- rn, xstat_fs_ProbeFreqInSecs);
- code = IOMGR_Select(0, /*Num fids*/
- 0, /*Descs ready for reading*/
- 0, /*Descs ready for writing*/
- 0, /*Descs w/exceptional conditions*/
- &tv); /*Ptr to timeout structure*/
- if (code)
- fprintf(stderr,
- "[%s] IOMGR_Select returned code %d\n",
- rn, code);
- } /*Continuous execution*/
- } /*Service loop*/
-
-} /*xstat_fs_LWP*/
-
+ gettimeofday(&tv, NULL);
+ wait.tv_sec = tv.tv_sec + xstat_fs_ProbeFreqInSecs;
+ wait.tv_nsec = tv.tv_usec * 1000;
+ opr_mutex_enter(&xstat_fs_force_lock);
+ code = opr_cv_timedwait(&xstat_fs_force_cv, &xstat_fs_force_lock, &wait);
+ opr_mutex_exit(&xstat_fs_force_lock);
+ } /*Continuous execution */
+ } /*Service loop */
+ return NULL;
+}
/*------------------------------------------------------------------------
* [exported] xstat_fs_Init
*
* Description:
* Initialize the xstat_fs module: set up Rx connections to the
- * given set of File Servers, start up the probe and callback LWPs,
+ * given set of File Servers, start up the probe and callback threads,
* and associate the routine to be called when a probe completes.
* Also, let it know which collections you're interested in.
*
* Sets up just about everything.
*------------------------------------------------------------------------*/
-int xstat_fs_Init(a_numServers, a_socketArray, a_ProbeFreqInSecs, a_ProbeHandler,
- a_flags, a_numCollections, a_collIDP)
- int a_numServers;
- struct sockaddr_in *a_socketArray;
- int a_ProbeFreqInSecs;
- int (*a_ProbeHandler)();
- int a_flags;
- int a_numCollections;
- afs_int32 *a_collIDP;
-
-{ /*xstat_fs_Init*/
-
- static char rn[] = "xstat_fs_Init"; /*Routine name*/
- register afs_int32 code; /*Return value*/
- static struct rx_securityClass *CBsecobj; /*Callback security object*/
- struct rx_securityClass *secobj; /*Client security object*/
- struct rx_service *rxsrv_afsserver; /*Server for AFS*/
- int arg_errfound; /*Argument error found?*/
- int curr_srv; /*Current server idx*/
- struct xstat_fs_ConnectionInfo *curr_conn; /*Ptr to current conn*/
- char *hostNameFound; /*Ptr to returned host name*/
- int conn_err; /*Connection error?*/
- int PortToUse; /*Callback port to use*/
- int collIDBytes; /*Num bytes in coll ID array*/
+int
+xstat_fs_Init(int a_numServers, struct sockaddr_in *a_socketArray,
+ int a_ProbeFreqInSecs, int (*a_ProbeHandler) (void), int a_flags,
+ int a_numCollections, afs_int32 * a_collIDP)
+{
+ static char rn[] = "xstat_fs_Init"; /*Routine name */
+ afs_int32 code; /*Return value */
+ static struct rx_securityClass *CBsecobj; /*Callback security object */
+ struct rx_securityClass *secobj; /*Client security object */
+ struct rx_service *rxsrv_afsserver; /*Server for AFS */
+ int arg_errfound; /*Argument error found? */
+ int curr_srv; /*Current server idx */
+ struct xstat_fs_ConnectionInfo *curr_conn; /*Ptr to current conn */
+ char *hostNameFound; /*Ptr to returned host name */
+ int conn_err; /*Connection error? */
+ int collIDBytes; /*Num bytes in coll ID array */
+ char hoststr[16];
/*
* If we've already been called, snicker at the bozo, gently
*/
if (xstat_fs_initflag) {
fprintf(stderr, "[%s] Called multiple times!\n", rn);
- return(0);
- }
- else
- xstat_fs_initflag = 1;
+ return (0);
+ } else
+ xstat_fs_initflag = 1;
+
+ opr_mutex_init(&xstat_fs_force_lock);
+ opr_cv_init(&xstat_fs_force_cv);
/*
* Check the parameters for bogosities.
*/
arg_errfound = 0;
if (a_numServers <= 0) {
- fprintf(stderr, "[%s] Illegal number of servers: %d\n",
- rn, a_numServers);
+ fprintf(stderr, "[%s] Illegal number of servers: %d\n", rn,
+ a_numServers);
arg_errfound = 1;
}
if (a_socketArray == (struct sockaddr_in *)0) {
arg_errfound = 1;
}
if (a_ProbeFreqInSecs <= 0) {
- fprintf(stderr, "[%s] Illegal probe frequency: %d\n",
- rn, a_ProbeFreqInSecs);
+ fprintf(stderr, "[%s] Illegal probe frequency: %d\n", rn,
+ a_ProbeFreqInSecs);
arg_errfound = 1;
}
- if (a_ProbeHandler == (int (*)())0) {
- fprintf(stderr, "[%s] Null probe handler function argument\n",
- rn);
+ if (a_ProbeHandler == NULL) {
+ fprintf(stderr, "[%s] Null probe handler function argument\n", rn);
arg_errfound = 1;
}
if (a_numCollections <= 0) {
- fprintf(stderr, "[%s] Illegal collection count argument: %d\n",
- rn, a_numServers);
+ fprintf(stderr, "[%s] Illegal collection count argument: %d\n", rn,
+ a_numServers);
arg_errfound = 1;
}
- if (a_collIDP == (afs_int32 *)0) {
+ if (a_collIDP == NULL) {
fprintf(stderr, "[%s] Null collection ID array argument\n", rn);
arg_errfound = 1;
}
if (arg_errfound)
- return(-1);
+ return (-1);
/*
* Record our passed-in info.
*/
- xstat_fs_debug = (a_flags & XSTAT_FS_INITFLAG_DEBUGGING);
- xstat_fs_oneShot = (a_flags & XSTAT_FS_INITFLAG_ONE_SHOT);
- xstat_fs_numServers = a_numServers;
- xstat_fs_Handler = a_ProbeHandler;
+ xstat_fs_debug = (a_flags & XSTAT_FS_INITFLAG_DEBUGGING);
+ xstat_fs_oneShot = (a_flags & XSTAT_FS_INITFLAG_ONE_SHOT);
+ xstat_fs_numServers = a_numServers;
+ xstat_fs_Handler = a_ProbeHandler;
xstat_fs_ProbeFreqInSecs = a_ProbeFreqInSecs;
- xstat_fs_numCollections = a_numCollections;
+ xstat_fs_numCollections = a_numCollections;
collIDBytes = xstat_fs_numCollections * sizeof(afs_int32);
- xstat_fs_collIDP = (afs_int32 *)(malloc(collIDBytes));
+ xstat_fs_collIDP = malloc(collIDBytes);
memcpy(xstat_fs_collIDP, a_collIDP, collIDBytes);
if (xstat_fs_debug) {
- printf("[%s] Asking for %d collection(s): ", rn, xstat_fs_numCollections);
+ printf("[%s] Asking for %d collection(s): ", rn,
+ xstat_fs_numCollections);
for (curr_srv = 0; curr_srv < xstat_fs_numCollections; curr_srv++)
- printf("%d ", *(xstat_fs_collIDP+curr_srv));
+ printf("%d ", *(xstat_fs_collIDP + curr_srv));
printf("\n");
}
*/
code = xstat_fs_CleanupInit();
if (code)
- return(code);
+ return (code);
/*
* Allocate the necessary data structures and initialize everything
* else.
*/
- xstat_fs_ConnInfo =
- (struct xstat_fs_ConnectionInfo *)
- malloc(a_numServers * sizeof(struct xstat_fs_ConnectionInfo));
+ xstat_fs_ConnInfo = malloc(a_numServers
+ * sizeof(struct xstat_fs_ConnectionInfo));
if (xstat_fs_ConnInfo == (struct xstat_fs_ConnectionInfo *)0) {
fprintf(stderr,
- "[%s] Can't allocate %d connection info structs (%d bytes)\n",
+ "[%s] Can't allocate %d connection info structs (%" AFS_SIZET_FMT " bytes)\n",
rn, a_numServers,
(a_numServers * sizeof(struct xstat_fs_ConnectionInfo)));
- return(-1); /*No cleanup needs to be done yet*/
+ return (-1); /*No cleanup needs to be done yet */
}
/*
*/
if (xstat_fs_debug)
printf("[%s] Initializing Rx\n", rn);
- PortToUse = XSTAT_FS_CBPORT;
-
- do {
- code = rx_Init(htons(PortToUse));
- if (code) {
- if (code == RX_ADDRINUSE) {
- if (xstat_fs_debug)
- fprintf(stderr,
- "[%s] Callback port %d in use, advancing\n",
- rn, PortToUse);
- PortToUse++;
- }
- else {
- fprintf(stderr, "[%s] Fatal error in rx_Init()\n", rn);
- return(-1);
- }
- }
- } while (code);
+ code = rx_Init(0);
+ if (code) {
+ fprintf(stderr, "[%s] Fatal error in rx_Init()\n", rn);
+ return (-1);
+ }
if (xstat_fs_debug)
- printf("[%s] Rx initialized on port %d\n", rn, PortToUse);
+ printf("[%s] Rx initialized\n", rn);
/*
* Create a null Rx server security object, to be used by the
fprintf(stderr,
"[%s] Can't create callback listener's security object.\n",
rn);
- xstat_fs_Cleanup(1); /*Delete already-malloc'ed areas*/
- return(-1);
+ xstat_fs_Cleanup(1); /*Delete already-malloc'ed areas */
+ return (-1);
}
if (xstat_fs_debug)
printf("[%s] Callback server security object created\n", rn);
-
+
/*
* Create a null Rx client security object, to be used by the
- * probe LWP.
+ * probe thread.
*/
- secobj = (struct rx_securityClass *) rxnull_NewClientSecurityObject();
+ secobj = rxnull_NewClientSecurityObject();
if (secobj == (struct rx_securityClass *)0) {
fprintf(stderr,
- "[%s] Can't create probe LWP client security object.\n",
- rn);
- xstat_fs_Cleanup(1); /*Delete already-malloc'ed areas*/
- return(-1);
+ "[%s] Can't create probe thread client security object.\n", rn);
+ xstat_fs_Cleanup(1); /*Delete already-malloc'ed areas */
+ return (-1);
}
if (xstat_fs_debug)
- printf("[%s] Probe LWP client security object created\n", rn);
+ printf("[%s] Probe thread client security object created\n", rn);
curr_conn = xstat_fs_ConnInfo;
conn_err = 0;
* printable name if possible.
*/
if (xstat_fs_debug) {
- printf("[%s] Copying in the following socket info:\n",
- rn);
- printf("[%s] IP addr 0x%lx, port %d\n", rn,
- (a_socketArray + curr_srv)->sin_addr.s_addr,
- (a_socketArray + curr_srv)->sin_port);
+ char hoststr[16];
+ printf("[%s] Copying in the following socket info:\n", rn);
+ printf("[%s] IP addr %s, port %d\n", rn,
+ afs_inet_ntoa_r((a_socketArray + curr_srv)->sin_addr.s_addr,hoststr),
+ ntohs((a_socketArray + curr_srv)->sin_port));
}
- memcpy(&(curr_conn->skt), a_socketArray + curr_srv, sizeof(struct sockaddr_in));
-
+ memcpy(&(curr_conn->skt), a_socketArray + curr_srv,
+ sizeof(struct sockaddr_in));
+
hostNameFound =
hostutil_GetNameByINet(curr_conn->skt.sin_addr.s_addr);
- if (hostNameFound == (char *)0) {
+ if (hostNameFound == NULL) {
fprintf(stderr,
- "[%s] Can't map Internet address %lu to a string name\n",
- rn, curr_conn->skt.sin_addr.s_addr);
+ "[%s] Can't map Internet address %s to a string name\n",
+ rn, afs_inet_ntoa_r(curr_conn->skt.sin_addr.s_addr,hoststr));
curr_conn->hostName[0] = '\0';
- }
- else {
+ } else {
strcpy(curr_conn->hostName, hostNameFound);
if (xstat_fs_debug)
- printf("[%s] Host name for server index %d is %s\n",
- rn, curr_srv, curr_conn->hostName);
+ printf("[%s] Host name for server index %d is %s\n", rn,
+ curr_srv, curr_conn->hostName);
}
-
+
/*
* Make an Rx connection to the current server.
*/
if (xstat_fs_debug)
- printf("[%s] Connecting to srv idx %d, IP addr 0x%lx, port %d, service 1\n",
- rn, curr_srv, curr_conn->skt.sin_addr.s_addr,
- curr_conn->skt.sin_port);
-
- curr_conn->rxconn =
- rx_NewConnection(curr_conn->skt.sin_addr.s_addr, /*Server addr*/
- curr_conn->skt.sin_port, /*Server port*/
- 1, /*AFS service #*/
- secobj, /*Security obj*/
- 0); /*# of above*/
+ printf
+ ("[%s] Connecting to srv idx %d, IP addr %s, port %d, service 1\n",
+ rn, curr_srv, afs_inet_ntoa_r(curr_conn->skt.sin_addr.s_addr,hoststr),
+ ntohs(curr_conn->skt.sin_port));
+
+ curr_conn->rxconn = rx_NewConnection(curr_conn->skt.sin_addr.s_addr, /*Server addr */
+ curr_conn->skt.sin_port, /*Server port */
+ 1, /*AFS service # */
+ secobj, /*Security obj */
+ 0); /*# of above */
if (curr_conn->rxconn == (struct rx_connection *)0) {
fprintf(stderr,
- "[%s] Can't create Rx connection to server '%s' (%lu)\n",
- rn, curr_conn->hostName, curr_conn->skt.sin_addr.s_addr);
+ "[%s] Can't create Rx connection to server '%s' (%s)\n",
+ rn, curr_conn->hostName, afs_inet_ntoa_r(curr_conn->skt.sin_addr.s_addr,hoststr));
conn_err = 1;
}
if (xstat_fs_debug)
- printf("[%s] New connection at 0x%lx\n",
- rn, curr_conn->rxconn);
+ printf("[%s] New connection at %p\n", rn, curr_conn->rxconn);
/*
* Bump the current xstat_fs connection to set up.
*/
curr_conn++;
- } /*for curr_srv*/
+ } /*for curr_srv */
/*
* Create the AFS callback service (listener).
*/
if (xstat_fs_debug)
printf("[%s] Creating AFS callback listener\n", rn);
- rxsrv_afsserver =
- rx_NewService(0, /*Use default port*/
- 1, /*Service ID*/
- "afs", /*Service name*/
- &CBsecobj, /*Ptr to security object(s)*/
- 1, /*# of security objects*/
- RXAFSCB_ExecuteRequest); /*Dispatcher*/
+ rxsrv_afsserver = rx_NewService(0, /*Use default port */
+ 1, /*Service ID */
+ "afs", /*Service name */
+ &CBsecobj, /*Ptr to security object(s) */
+ 1, /*# of security objects */
+ RXAFSCB_ExecuteRequest); /*Dispatcher */
if (rxsrv_afsserver == (struct rx_service *)0) {
- fprintf(stderr,
- "[%s] Can't create callback Rx service/listener\n",
+ fprintf(stderr, "[%s] Can't create callback Rx service/listener\n",
rn);
- xstat_fs_Cleanup(1); /*Delete already-malloc'ed areas*/
- return(-1);
+ xstat_fs_Cleanup(1); /*Delete already-malloc'ed areas */
+ return (-1);
}
if (xstat_fs_debug)
printf("[%s] Callback listener created\n", rn);
*/
if (xstat_fs_debug)
printf("[%s] Starting up callback listener.\n", rn);
- rx_StartServer(0); /*Don't donate yourself to LWP pool*/
+ rx_StartServer(0); /*Don't donate yourself to LWP pool */
/*
* Start up the probe LWP.
*/
if (xstat_fs_debug)
- printf("[%s] Creating the probe LWP\n", rn);
- code =
- LWP_CreateProcess(xstat_fs_LWP, /*Function to start up*/
- LWP_STACK_SIZE, /*Stack size in bytes*/
- 1, /*Priority*/
- 0, /*Parameters*/
- "xstat_fs Worker", /*Name to use*/
- &probeLWP_ID); /*Returned LWP process ID*/
+ printf("[%s] Creating the probe thread\n", rn);
+ code = pthread_create(&xstat_fs_thread, NULL, xstat_fs_LWP, NULL);
if (code) {
- fprintf(stderr,
- "[%s] Can't create xstat_fs LWP! Error is %d\n",
- rn, code);
- xstat_fs_Cleanup(1); /*Delete already-malloc'ed areas*/
- return(code);
+ fprintf(stderr, "[%s] Can't create xstat_fs thread! Error is %d\n", rn,
+ code);
+ xstat_fs_Cleanup(1); /*Delete already-malloc'ed areas */
+ return (code);
}
- if (xstat_fs_debug)
- printf("[%s] Probe LWP process structure located at 0x%x\n",
- rn, probeLWP_ID);
/*
* Return the final results.
*/
if (conn_err)
- return(-2);
+ return (-2);
else
- return(0);
-
-} /*xstat_fs_Init*/
+ return (0);
+}
/*------------------------------------------------------------------------
* [exported] xstat_fs_ForceProbeNow
*
* Description:
- * Wake up the probe LWP, forcing it to execute a probe immediately.
+ * Wake up the probe thread, forcing it to execute a probe immediately.
*
* Arguments:
* None.
* As advertised.
*------------------------------------------------------------------------*/
-int xstat_fs_ForceProbeNow()
-
-{ /*xstat_fs_ForceProbeNow*/
-
- static char rn[] = "xstat_fs_ForceProbeNow"; /*Routine name*/
+int
+xstat_fs_ForceProbeNow(void)
+{
+ static char rn[] = "xstat_fs_ForceProbeNow"; /*Routine name */
/*
* There isn't a prayer unless we've been initialized.
*/
if (!xstat_fs_initflag) {
fprintf(stderr, "[%s] Must call xstat_fs_Init first!\n", rn);
- return(-1);
+ return (-1);
}
/*
* Kick the sucker in the side.
*/
- IOMGR_Cancel(probeLWP_ID);
+ opr_mutex_enter(&xstat_fs_force_lock);
+ opr_cv_signal(&xstat_fs_force_cv);
+ opr_mutex_exit(&xstat_fs_force_lock);
/*
* We did it, so report the happy news.
*/
- return(0);
+ return (0);
+}
+
+/**
+ * Fill the xstat full perf data structure from the data collection array.
+ *
+ * This function is a client-side decoding of the non-portable xstat_fs full
+ * performance data. The full perf structure includes timeval structures,
+ * which have platform dependent size.
+ *
+ * To make things even more interesting, the word ordering of the time
+ * values on hosts with 64-bit time depend on endianess. The ordering
+ * within a given afs_int32 is handled by xdr.
+ *
+ * @param[out] aout an address to a stats structure pointer
+ * @param[in] ain array of int32s received
+ * @param[in] alen length of ain
+ * @param[inout] abuf a buffer provided by the caller
+ *
+ * @return 0 on success
+ */
+int
+xstat_fs_DecodeFullPerfStats(struct fs_stats_FullPerfStats **aout,
+ afs_int32 * ain,
+ afs_int32 alen,
+ struct fs_stats_FullPerfStats *abuf)
+{
+ int i;
+ afs_int32 *p;
+ int snbo = -2; /* detected remote site has network-byte ordering */
+
+ static const int XSTAT_FPS_LEN = sizeof(struct fs_stats_FullPerfStats) / sizeof(afs_int32); /* local size of fps */
+ static const int XSTAT_FPS_SMALL = 424; /**< fps size when sizeof(timeval) is 2*sizeof(afs_int32) */
+ static const int XSTAT_FPS_LARGE = 666; /**< fps size when sizeof(timeval) is 2*sizeof(afs_int64) */
+
+#define DECODE_TV(t) \
+ do { \
+ if (alen == XSTAT_FPS_SMALL) { \
+ (t).tv_sec = *p++; \
+ (t).tv_usec = *p++; \
+ } else { \
+ if (snbo) { \
+ p++; \
+ (t).tv_sec = *p++; \
+ p++; \
+ (t).tv_usec = *p++; \
+ } else { \
+ (t).tv_sec = *p++; \
+ p++; \
+ (t).tv_usec = *p++; \
+ p++; \
+ } \
+ } \
+ } while (0)
+
+ if (alen != XSTAT_FPS_SMALL && alen != XSTAT_FPS_LARGE) {
+ return -1; /* unrecognized size */
+ }
+
+ if (alen == XSTAT_FPS_LEN && alen == XSTAT_FPS_SMALL) {
+ /* Same size, and xdr dealt with byte ordering; no decoding needed. */
+ *aout = (struct fs_stats_FullPerfStats *)ain;
+ return 0;
+ }
+
+ if (alen == XSTAT_FPS_LARGE) {
+ /* Attempt to detect the word ordering of the time values. */
+ struct fs_stats_FullPerfStats *fps =
+ (struct fs_stats_FullPerfStats *)ain;
+ afs_int32 *epoch = (afs_int32 *) & (fps->det.epoch);
+ if (epoch[0] == 0 && epoch[1] != 0) {
+ snbo = 1;
+ } else if (epoch[0] != 0 && epoch[1] == 0) {
+ snbo = 0;
+ } else {
+ return -2; /* failed to detect server word ordering */
+ }
+ }
+
+ if (alen == XSTAT_FPS_LEN && alen == XSTAT_FPS_LARGE
+#if defined(WORDS_BIGENDIAN)
+ && snbo
+#else /* WORDS_BIGENDIAN */
+ && !snbo
+#endif /* WORDS_BIGENDIAN */
+ ) {
+ /* Same size and order; no decoding needed. */
+ *aout = (struct fs_stats_FullPerfStats *)ain;
+ return 0;
+ }
+
+ /* Either different sizes, or different ordering, or both. Schlep over
+ * each field, decoding time values. The fields up to the first time value
+ * can be copied in bulk. */
+ if (xstat_fs_debug) {
+ printf("debug: Decoding xstat full perf stats; length=%d", alen);
+ if (alen == XSTAT_FPS_LARGE) {
+ printf(", order='%s'", (snbo ? "big-endian" : "little-endian"));
+ }
+ printf("\n");
+ }
+
+ p = ain;
+ memset(abuf, 0, sizeof(struct fs_stats_FullPerfStats));
+ memcpy(abuf, p, sizeof(struct afs_PerfStats));
+ p += sizeof(struct afs_PerfStats) / sizeof(afs_int32);
+
+ DECODE_TV(abuf->det.epoch);
+ for (i = 0; i < FS_STATS_NUM_RPC_OPS; i++) {
+ struct fs_stats_opTimingData *td = abuf->det.rpcOpTimes + i;
+ td->numOps = *p++;
+ td->numSuccesses = *p++;
+ DECODE_TV(td->sumTime);
+ DECODE_TV(td->sqrTime);
+ DECODE_TV(td->minTime);
+ DECODE_TV(td->maxTime);
+ }
+ for (i = 0; i < FS_STATS_NUM_XFER_OPS; i++) {
+ struct fs_stats_xferData *xd = abuf->det.xferOpTimes + i;
+ xd->numXfers = *p++;
+ xd->numSuccesses = *p++;
+ DECODE_TV(xd->sumTime);
+ DECODE_TV(xd->sqrTime);
+ DECODE_TV(xd->minTime);
+ DECODE_TV(xd->maxTime);
+ xd->sumBytes = *p++;
+ xd->minBytes = *p++;
+ xd->maxBytes = *p++;
+ memcpy((void *)xd->count, (void *)p,
+ sizeof(afs_int32) * FS_STATS_NUM_XFER_BUCKETS);
+ p += FS_STATS_NUM_XFER_BUCKETS;
+ }
+ *aout = abuf;
+ return 0;
+#undef DECODE_TV
+}
-} /*xstat_fs_ForceProbeNow*/
+/*
+ * Wait for the collection to complete. Returns after one cycle if running in
+ * one-shot mode, otherwise wait for a given amount of time.
+ *
+ * Args:
+ * int sleep_secs : time to wait in seconds when running
+ * in continuous mode. 0 means wait forever.
+ *
+ * Returns:
+ * 0 on success
+ */
+int
+xstat_fs_Wait(int sleep_secs)
+{
+ static char rn[] = "xstat_fs_Wait"; /*Routine name */
+ int code;
+ struct timeval tv; /*Time structure */
+
+ if (xstat_fs_oneShot) {
+ /*
+ * One-shot operation; just wait for the collection to be done.
+ */
+ if (xstat_fs_debug)
+ printf("[%s] Calling pthread_join\n", rn);
+ code = pthread_join(xstat_fs_thread, NULL);
+ if (xstat_fs_debug)
+ printf("[%s] Returned from pthread_join()\n", rn);
+ if (code) {
+ fprintf(stderr,
+ "[%s] Error %d encountered by pthread_join()\n",
+ rn, code);
+ }
+ } else if (sleep_secs == 0) {
+ /* Sleep forever. */
+ if (xstat_fs_debug)
+ fprintf(stderr, "[ %s ] going to sleep ...\n", rn);
+ while (1) {
+ code = select(0, /*Num fds */
+ 0, /*Descriptors ready for reading */
+ 0, /*Descriptors ready for writing */
+ 0, /*Descriptors with exceptional conditions */
+ NULL); /* NULL timeout means "forever" */
+ if (code < 0) {
+ fprintf(stderr, "[%s] select() error %d\n", rn, errno);
+ break;
+ }
+ }
+ } else {
+ /* Let's just fall asleep while. */
+ if (xstat_fs_debug)
+ printf
+ ("xstat_fs service started, main thread sleeping for %d secs.\n",
+ sleep_secs);
+ tv.tv_sec = sleep_secs;
+ tv.tv_usec = 0;
+ code = select(0, /*Num fds */
+ 0, /*Descriptors ready for reading */
+ 0, /*Descriptors ready for writing */
+ 0, /*Descriptors with exceptional conditions */
+ &tv); /*Timeout structure */
+ if (code < 0)
+ fprintf(stderr, "[%s] select() error %d\n", rn, errno);
+ }
+ return code;
+}