#include <afs/param.h>
#include <roken.h>
+#include <afs/opr.h>
#include "xstat_fs.h" /*Interface for this module */
-#include <lwp.h> /*Lightweight process package */
+#include <pthread.h>
#include <afs/afsutil.h>
#include <afs/afscbint.h>
-#define LWP_STACK_SIZE (16 * 1024)
-
/*
* Exported variables.
*/
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 */
afs_int32 xstat_fsData[AFS_MAX_XSTAT_LONGS]; /*Buffer for collected data */
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 PROCESS probeLWP_ID; /*Probe LWP process ID */
+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 */
-
-/*
- * 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 opr_mutex_t xstat_fs_force_lock; /*Lock to wakeup probe */
+static opr_cv_t xstat_fs_force_cv; /*Condvar to wakeup probe */
/*------------------------------------------------------------------------
* [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.
static void *
xstat_fs_LWP(void *unused)
{
- static char rn[] = "xstat_fs_LWP"; /*Routine name */
+ static char rn[] = "xstat_fs_thread"; /*Routine name */
afs_int32 code; /*Results of calls */
- int oneShotCode; /*Result of one-shot signal */
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 # */
if (xstat_fs_debug) {
printf
- ("%s: Calling RXAFS_GetXStats, conn=%" AFS_PTR_FMT ", clientVersionNumber=%d, collectionNumber=%d, srvVersionNumberP=%" AFS_PTR_FMT ", timeP=%" AFS_PTR_FMT ", dataP=%" AFS_PTR_FMT "\n",
+ ("%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 %" AFS_PTR_FMT "]\n", rn,
+ printf("%s: [bufflen=%d, buffer at %p]\n", rn,
xstat_fs_Results.data.AFS_CollData_len,
xstat_fs_Results.data.AFS_CollData_val);
}
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 %" AFS_PTR_FMT "\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);
+ 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_Verify(code == 0 || code == ETIMEDOUT);
+ opr_mutex_exit(&xstat_fs_force_lock);
} /*Continuous execution */
} /*Service loop */
return NULL;
*
* 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.
*
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 */
char hoststr[16];
} else
xstat_fs_initflag = 1;
+ opr_mutex_init(&xstat_fs_force_lock);
+ opr_cv_init(&xstat_fs_force_cv);
+
/*
* Check the parameters for bogosities.
*/
a_ProbeFreqInSecs);
arg_errfound = 1;
}
- if (a_ProbeHandler == (int (*)())0) {
+ if (a_ProbeHandler == NULL) {
fprintf(stderr, "[%s] Null probe handler function argument\n", rn);
arg_errfound = 1;
}
*/
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
/*
* Create a null Rx client security object, to be used by the
- * probe LWP.
+ * probe thread.
*/
secobj = rxnull_NewClientSecurityObject();
if (secobj == (struct rx_securityClass *)0) {
fprintf(stderr,
- "[%s] Can't create probe LWP client security object.\n", rn);
+ "[%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;
conn_err = 1;
}
if (xstat_fs_debug)
- printf("[%s] New connection at %" AFS_PTR_FMT "\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.
* 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 */
- (void *)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,
+ 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 %" AFS_PTR_FMT "\n", rn,
- probeLWP_ID);
/*
* Return the final results.
* [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.
/*
* 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;
#undef DECODE_TV
}
+
+/*
+ * 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;
+}