/*
* 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 <roken.h>
#include "xstat_fs.h" /*Interface for this module */
#include <lwp.h> /*Lightweight process package */
#include <afs/afsutil.h>
-#include <string.h>
+#include <afs/afscbint.h>
#define LWP_STACK_SIZE (16 * 1024)
/*
- * 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 */
-
-/*
- * 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_ProbeUUID();
-extern afs_int32 SRXAFSCB_GetCE();
-extern afs_int32 SRXAFSCB_GetLock();
-
-/*
* Exported variables.
*/
int xstat_fs_numServers; /*Num connected servers */
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 int (*xstat_fs_Handler) (void); /*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 */
*------------------------------------------------------------------------*/
static int
-xstat_fs_CleanupInit()
+xstat_fs_CleanupInit(void)
{
afs_int32 code; /*Return code from callback stubs */
struct rx_call *rxcall; /*Bogus param */
xstat_fs_LWP(void *unused)
{
static char rn[] = "xstat_fs_LWP"; /*Routine name */
- register afs_int32 code; /*Results of calls */
+ afs_int32 code; /*Results of calls */
int oneShotCode; /*Result of one-shot signal */
struct timeval tv; /*Time structure */
int conn_idx; /*Connection index */
afs_int32 numColls; /*Number of collections to get */
afs_int32 *currCollIDP; /*Curr collection ID desired */
- static afs_int32 xstat_VersionNumber; /*Version # of server */
-
/*
* Set up some numbers we'll need.
*/
if (xstat_fs_debug) {
printf
- ("%s: Calling RXAFS_GetXStats, conn=0x%" AFS_PTR_FMT ", clientVersionNumber=%d, collectionNumber=%d, srvVersionNumberP=0x%" AFS_PTR_FMT ", timeP=0x%" AFS_PTR_FMT ", dataP=0x%" AFS_PTR_FMT "\n",
+ ("%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",
rn, curr_conn->rxconn, clientVersionNumber,
*currCollIDP, &srvVersionNumber,
&(xstat_fs_Results.probeTime),
&(xstat_fs_Results.data));
- printf("%s: [bufflen=%d, buffer at 0x%" AFS_PTR_FMT "]\n", rn,
+ printf("%s: [bufflen=%d, buffer at %" AFS_PTR_FMT "]\n", rn,
xstat_fs_Results.data.AFS_CollData_len,
xstat_fs_Results.data.AFS_CollData_val);
}
* that we've finished our collection round.
*/
if (xstat_fs_debug)
- printf("[%s] Signalling main process at 0x%" AFS_PTR_FMT "\n", rn,
+ printf("[%s] Signalling main process at %" AFS_PTR_FMT "\n", rn,
&terminationEvent);
oneShotCode = LWP_SignalProcess(&terminationEvent);
if (oneShotCode)
int
xstat_fs_Init(int a_numServers, struct sockaddr_in *a_socketArray,
- int a_ProbeFreqInSecs, int (*a_ProbeHandler) (), int a_flags,
+ 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 */
- register afs_int32 code; /*Return value */
+ 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 */
xstat_fs_ProbeFreqInSecs = a_ProbeFreqInSecs;
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,
* 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 */
conn_err = 1;
}
if (xstat_fs_debug)
- printf("[%s] New connection at 0x%" AFS_PTR_FMT "\n", rn, curr_conn->rxconn);
+ printf("[%s] New connection at %" AFS_PTR_FMT "\n", rn, curr_conn->rxconn);
/*
* Bump the current xstat_fs connection to set up.
return (code);
}
if (xstat_fs_debug)
- printf("[%s] Probe LWP process structure located at 0x%" AFS_PTR_FMT "\n", rn,
+ printf("[%s] Probe LWP process structure located at %" AFS_PTR_FMT "\n", rn,
probeLWP_ID);
/*
*------------------------------------------------------------------------*/
int
-xstat_fs_ForceProbeNow()
+xstat_fs_ForceProbeNow(void)
{
static char rn[] = "xstat_fs_ForceProbeNow"; /*Routine name */
*/
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
+}