xstat: Don't cast returns from malloc()
[openafs.git] / src / xstat / xstat_fs.c
index 146b7e4..e35469e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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 */
@@ -64,7 +46,7 @@ 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 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 */
@@ -99,7 +81,7 @@ 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 */
@@ -242,7 +224,7 @@ static void *
 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 */
@@ -252,8 +234,6 @@ xstat_fs_LWP(void *unused)
     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.
      */
@@ -303,12 +283,12 @@ xstat_fs_LWP(void *unused)
 
                    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);
                    }
@@ -360,7 +340,7 @@ xstat_fs_LWP(void *unused)
             * 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)
@@ -426,11 +406,11 @@ xstat_fs_LWP(void *unused)
 
 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 */
@@ -497,7 +477,7 @@ xstat_fs_Init(int a_numServers, struct sockaddr_in *a_socketArray,
     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,
@@ -519,11 +499,11 @@ xstat_fs_Init(int a_numServers, struct sockaddr_in *a_socketArray,
      * 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 */
@@ -636,7 +616,7 @@ xstat_fs_Init(int a_numServers, struct sockaddr_in *a_socketArray,
            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.
@@ -690,7 +670,7 @@ xstat_fs_Init(int a_numServers, struct sockaddr_in *a_socketArray,
        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);
 
     /*
@@ -724,7 +704,7 @@ xstat_fs_Init(int a_numServers, struct sockaddr_in *a_socketArray,
  *------------------------------------------------------------------------*/
 
 int
-xstat_fs_ForceProbeNow()
+xstat_fs_ForceProbeNow(void)
 {
     static char rn[] = "xstat_fs_ForceProbeNow";       /*Routine name */
 
@@ -746,3 +726,137 @@ xstat_fs_ForceProbeNow()
      */
     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
+}