Start of change

Statistics Sysplex Owner Operations Information

Purpose

Returns information about the number of calls processed on the local system as a result of a message sent from another system. Vnode operation statistics are returned for each client system that accessed a file system owned on the local server.

Format

syscall_parmlist
  opcode               int                 253         STATOP_SVI
  parms[0]             int                 offset to   STAT_API
  parms[1]             int                 Offset of output following STAT_API
  parms[2]             int                 0
  parms[3]             int                 0
  parms[4]             int                 0
  parms[5]             int                 0
  parms[6]             int                 0

STAT_API

  sa_eye               char[4]             "STAP"
  sa_len               int                 length of buffer that 
                                           follows STAT_API
  sa_ver               int                 1
  sa_flags             char[1]             0x00
  SA_RESET                                 0x80 Reset statistics
  sa_fill              char[3]             0
  sa_supported_ver     int                 version of data returned or reserved
  sa_reserve           int[3]              0
  posix_time_high      unsigned int        high order 32 bits since epoch
  posix_time_low       unsigned int        low order 32 bits since epoch
  posix_useconds       unsigned int        microseconds
  pad1                 int

CT_HEADER
  ct_eye               char[4]             "CTHD"
  ct_length            short               Length of the structure
  ct_version           short               Structure version
  number_of_ct_sys     unsigned int        Number of CT_SYS_STATS structures
  number_of_ct_call    unsigned int        Number of CT_CALL_STATS structures

CT_SYS_STATS[number_of_ct_sys]                     
  cs_eye               char[4]             "CTSY"
  cs_length            short               Length of the structure
  cs_version           short               Structure version
  cs_sysname           char[9]             Name of system.  A value of 0 
                                           means there is no information in 
                                           this record and any subsequent 
                                           record (end of list)
  reserved             char[7]
  
CT_CALL_STATS[number_of_ct_call]
  cc_eye               char[4]             "CTCL"
  cc_length            short               Length of structure
  cc_version           short               Structure version
  cc_count             unsigned long long  Number of calls of that type
                                           since last statistics reset.
  cc_xcfreq            unsigned long long  Indicates if an XCF request
                                           was required to process the call.
                                           Number of XCF requests that were 
                                           required to make callbacks to one 
                                           or more clients to process 
                                           the requests.                                          
  cc_qwait             unsigned long long  Number of times a request had
                                           to wait in queue before being
                                           dispatched to a processing
                                           task at the owner, valid only
                                           for SVI report
  cc_avg_wait_whole    int                 Average time for system to 
                                           process call in milliseconds.
                                           This will be average time for the 
                                           owner to process the call for SVI 
                                           reports.  This is the part 
                                           before the decimal point.
  cc_avg_wait_decimal  int                 The part after the decimal
                                           point for avg. waits time.
                                           This is microseconds.
  cc_name              char[25]
  reserved             char[7]

CT_CALL_STATS
  cc_eye               char[4]             "CTCL"
  cc_length            short               Length of structure
  cc_version           short               Structure version
  cc_count             unsigned long long  Number of calls of that type
                                           since last statistics reset.
  cc_xcfreq            unsigned long long  Indicates if an XCF request
                                           was required to process the call.
                                           Number of XCF requests that were 
                                           required to make callbacks to one 
                                           or more clients to process 
                                           the requests.                                          
  cc_qwait             unsigned long long  Number of times a request had
                                           to wait in queue before being
                                           dispatched to a processing
                                           task at the owner, valid only
                                           for SVI report
  cc_avg_wait_whole    int                 Average time for system to 
                                           process call in milliseconds.
                                           This will be average time for the 
                                           owner to process the call for SVI 
                                           reports.  This is the part 
                                           before the decimal point.
  cc_avg_wait_decimal  int                 The part after the decimal
                                           point for avg. waits time.
                                           This is microseconds.
  cc_name              char[25]
  reserved             char[7]

Return_value    0 if request is successful, -1 if it is not successful

Return_code
    EINTR         ZFS is shutting down
    EINVAL        Invalid parameter list
    EMVSERR       Internal error using an osi service

Reason_code
    0xEFnnxxxx    See z/OS Distributed File Service Messages and Codes

Usage notes

  • Users of the API supply as input a buffer that contains a syscall_parmlist followed by a STAT_API structure, followed by an output buffer.
  • Output consists of a CT_HEADER followed by an array of CT_SYS_STATS structures and an array of CT_CALL_STATS structures. The number of elements in each array is returned in number_of_ct_sys and number_of_ct_call respectively.
  • If the output buffer is not large enough to contain all of the output, E2BIG is returned and the required size is placed in sa_len. The caller can then try the request again with a larger buffer.
  • A CT_SYS_STATS structure is returned only for client systems that sent the local server system messages since the last statistics reset.

Privilege required

None.

Related services

  • Start of changeStatistics Server Token Management Information End of change
  • Start of changeStatistics Sysplex Client Operations InformationEnd of change

Restrictions

None.

Examples

#pragma linkage(BPX1PCT, OS)
#pragma LANGLVL(EXTENDED)

extern void BPX1PCT(char *, int, int, char *, int *, int *, int *);

#include <stdio.h>

#define ZFSCALL_STATS 0x40000007     
#define STATOP_SVI    254   /* inbound calls from remote clients */
#define E2BIG         145

typedef struct syscall_parmlist_t {
  int opcode;                  /* Operation code to perform */
  int parms[7];                /* Specific to type of operation, */

} syscall_parmlist;

typedef  struct  reset_time {
  unsigned int   posix_time_high;   
  unsigned int   posix_time_low;    
  unsigned int   posix_usecs;       
  int            pad1;             
} RESET_TIME;

typedef struct stat_api_t {
#define   SA_EYE "STAP"
  char    sa_eye[4];           /* 4 byte identifier must be */
  int     sa_len;              /* length of the buffer to put data into*/
                               /* this buffer area follows this struct*/
  int     sa_ver;              /* the version number currently always 1*/
#define   SA_VER_INIT 0x01
  char    sa_flags;            /* command field  must be x00 or x80, */
                               /* x80 means reset statistics         */
#define   SA_RESET 0x80
  char    sa_fill[3];          /* spare bytes */
  int     sa_reserve[4];       /* Reserved */
  struct  reset_time reset_time_info;
} STAT_API;

typedef struct CT_CALL_STATS_t {
  char  cc_eye[4];
#define CC_EYE "CTCL"
  short cc_length;
  short cc_version;
#define CC_VER_INITIAL 1
  unsigned long long cc_count;
  unsigned long long cc_xcfreq;
  unsigned long long cc_qwait; /* number of waits */
  int   cc_avg_wait_whole;     /* average wait time for */
                               /* calls of this type    */
  int   cc_avg_wait_decimal;
  char  cc_name[25];
  char  reserved[7];
} CT_CALL_STATS;

typedef struct CT_SYS_STATS_t {
  char  cs_eye[4];
#define CS_EYE "CTSY"
  short cs_length;
  short cs_version;
#define CS_VER_INITIAL 1
  char  cs_sysname[9];
  char  reserved[7];
} CT_SYS_STATS;

typedef struct CT_HEADER_t {
  char         ct_eye[4];
#define        CT_EYE "CTHD"
  short        ct_length;
  short        ct_version;
#define        CT_VER_INITIAL 1
  unsigned int number_of_ct_sys;
  unsigned int number_of_ct_call;
} CT_HEADER;

int main(int argc, char** argv)
{
  int  buff_fill_len = 0;
  int  bpxrv, bpxrc, bpxrs;
  char sysname[9];
  int  num_systems;
  int  num_calls;
  int  entry_size;
  int  mypsize;
  int  buflen;
  int  i,j,t;
  int  buffer_success = 0;

  STAT_API          local_req;
  STAT_API*         st_req     = NULL;
  syscall_parmlist* parmp      = NULL;
  CT_HEADER*        ct_p       = NULL;
  CT_SYS_STATS*     ct_sysp    = NULL;
  CT_CALL_STATS*    ct_callp   = NULL;
  char*             p          = NULL;
  char*             buffp      = NULL;

  /* Initialize the local_req to 0s */
  st_req = &local_req;
  memset( st_req, 0x00, sizeof(STAT_API) );

  strcpy( local_req.sa_eye, SA_EYE, sizeof(local_req.sa_eye) );
  local_req.sa_len = 0;
  local_req.sa_ver = SA_VER_INIT;

  /* Allocate Buffer */
  buffp = (char*) malloc(sizeof(syscall_parmlist) + sizeof(STAT_API));
  if( buffp == NULL )
  {
    printf("Malloc Error\n");
    return 0;
  }
  memset( buffp, 0x00, sizeof(syscall_parmlist) + sizeof(STAT_API));

  /* Set the run parms */
  parmp = (syscall_parmlist*) &buffp[0];
  parmp->opcode   = STATOP_SVI;
  parmp->parms[0] = buff_fill_len = sizeof(syscall_parmlist);
  parmp->parms[1] = buff_fill_len + sizeof(STAT_API);
  parmp->parms[2] = 0;
  parmp->parms[3] = 0;
  parmp->parms[4] = 0;
  parmp->parms[5] = 0;
  parmp->parms[6] = 0;
    
  st_req = (STAT_API*) &buffp[buff_fill_len];
  memcpy( st_req, &local_req, sizeof(STAT_API) );
  buff_fill_len += sizeof(STAT_API);
           
  BPX1PCT("ZFS     ",
          ZFSCALL_STATS,              /* Aggregate operation */
          buff_fill_len,              /* Length of Argument */
          (char*) buffp,              /* Pointer to Argument */
          &bpxrv,                     /* Pointer to Return_value */
          &bpxrc,                     /* Pointer to Return_code */
          &bpxrs);                    /* Pointer to Reason_code */

  printf("bpxrv %d\n", bpxrv);

  for(t = 0; t < 1000 && buffer_success == 0; t++)
  {
    if( bpxrv < 0 )
    {
      /* Look for E2BIG to get required file size back in the st_req */
      if( bpxrc == E2BIG ) 
      {
        buflen  = st_req->sa_len;
        mypsize = sizeof(syscall_parmlist) + 
                  sizeof(STAT_API) + buflen;

        free(buffp);

        buffp = (char*) malloc(mypsize);
        if( buffp == NULL )
        {
          printf("Malloc Error\n");
          return 0;
        }
        memset( buffp, 0x00, mypsize );
        printf("Need buffer size of %d, for a total of %d\n", 
               buflen, mypsize);

        /* Set the run parms */
        parmp = (syscall_parmlist*) &buffp[0];
        parmp->opcode   = STATOP_SVI;
        parmp->parms[0] = buff_fill_len = sizeof(syscall_parmlist);
        parmp->parms[1] = buff_fill_len + sizeof(STAT_API);
        parmp->parms[2] = 0;
        parmp->parms[3] = 0;
        parmp->parms[4] = 0;
        parmp->parms[5] = 0;
        parmp->parms[6] = 0;
            
        st_req = (STAT_API*) &buffp[buff_fill_len];
        memcpy( st_req->sa_eye, SA_EYE, 4 );
        buff_fill_len += sizeof(STAT_API);
        st_req->sa_ver = SA_VER_INIT;
        st_req->sa_len = buflen;

        BPX1PCT("ZFS     ",
                ZFSCALL_STATS,          /* Aggregate operation */
                mypsize,                /* Length of Argument */
                (char*) buffp,          /* Pointer to Argument */
                &bpxrv,                 /* Pointer to Return_value */
                &bpxrc,                 /* Pointer to Return_code */
                &bpxrs);                /* Pointer to Reason_code */

        if( bpxrv != 0 && bpxrc == E2BIG )
          printf("E2BIG: %d times total\n", t);
        else if( bpxrv == 0 )
        {
          buffer_success = 1;
          ct_p = (CT_HEADER*) &buffp[buff_fill_len];
          buff_fill_len += ct_p->ct_length;
          ct_sysp = (CT_SYS_STATS*) &buffp[buff_fill_len];
          buff_fill_len += ct_sysp->cs_length;
          ct_callp = (CT_CALL_STATS*) &buffp[buff_fill_len];
        
          /* Make sure there are systems */
          num_systems = ct_p->number_of_ct_sys;
          if( num_systems == 0 )
          {
            printf("Svi stats completed successfully. "
                   "There is no information to display\n");
            free(buffp);
            return 0;
          }
          num_calls  = ct_p->number_of_ct_call;
          entry_size = ct_sysp->cs_length + 
            (ct_callp->cc_length * num_calls);

          for (j = 0; j < num_systems; j++)
          {
            printf("SV");
            printf("%30cSVI Calls from System %s\n", ' ', 
                   ct_sysp->cs_sysname);
            printf("  ");                                        
            printf("%30c------------------------------\n", ' ');
            printf("SVI Call                 "
                   "Count                 "
                   "Qwait             "
                   "XCF Req.          "
                   "Avg. Time\n");
            printf("--------------------     "
                   "--------------------  "
                   "----------------  ----------------  "
                   "----------\n");
                          
            for (i = 0; i < num_calls-1; i++)
            {
              printf("%-25s%20llu  %16llu  %16llu%8u.%3.3u\n",
                     ct_callp[i].cc_name,
                     ct_callp[i].cc_count,
                     ct_callp[i].cc_qwait,
                     ct_callp[i].cc_xcfreq,
                     ct_callp[i].cc_avg_wait_whole,
                     ct_callp[i].cc_avg_wait_decimal);
            }

            /* Put out the Totals entry */
            printf("--------------------     "
                   "--------------------  "
                   "----------------  ----------------  "
                   "----------\n");
            printf("%-25s%20llu  %16llu  %16llu%8u.%3.3u\n",
                   ct_callp[i].cc_name,
                   ct_callp[i].cc_count,
                   ct_callp[i].cc_qwait,
                   ct_callp[i].cc_xcfreq,
                   ct_callp[i].cc_avg_wait_whole,
                   ct_callp[i].cc_avg_wait_decimal);

            printf("\n");
        
            /* Get the pointers to the next system entry */
            p = (char*) ct_sysp;
            p += entry_size;
            ct_sysp = (CT_SYS_STATS*) p;
        
            p += ct_sysp->cs_length;
            ct_callp = (CT_CALL_STATS*) p;
          }
        }
        else
        {
          /* Second API call failed */
          printf("Error on next request for svi stats\n");
          printf("Return Value: %d "
                 "Return Code: %d "
                 "Reason Code: %x\n",
                 bpxrv, bpxrc, bpxrs); 
          buffer_success = -1;
        }
      }
      else
      {
        /* Expecting E2BIG and it was a different error */
        printf("Error on storage stats trying to get required size\n");
        printf("BPXRV = %d BPXRC = %d BPXRS = %x\n", 
               bpxrv, bpxrc, bpxrs);
        buffer_success = -1;
      }
    }
    else
    {
      /* If rv is 0, most likely there was no data to get */
      if (st_req->sa_len == 0) 
      {
        printf("No data\n");
        printf("BPXRV = %d BPXRC = %d BPXRS = %x\n", 
               bpxrv, bpxrc, bpxrs);
      } 
      else 
      {   /* There was some other problem with getting required size */
        printf("Error getting size required\n");
        printf("BPXRV = %d BPXRC = %d BPXRS = %x\n", 
               bpxrv, bpxrc, bpxrs);
      }
      buffer_success = -1;
    }
  }

  if( t == 1000 )
    printf("Number of failed buffer resizes exceeded.\n");

  free(buffp);
  return 0;
}
End of change