Logo Search packages:      
Sourcecode: hdf5 version File versions

PabloHDF_RT.c

/*  This file is part of the Pablo Performance Analysis Environment
// 
//           (R)
//  The Pablo    Performance Analysis Environment software is NOT in
//  the public domain.  However, it is freely available without fee for
//  education, research, and non-profit purposes.  By obtaining copies
//  of this and other files that comprise the Pablo Performance Analysis
//  Environment, you, the Licensee, agree to abide by the following
//  conditions and understandings with respect to the copyrighted software:
//  
//  1.  The software is copyrighted in the name of the Board of Trustees
//      of the University of Illinois (UI), and ownership of the software
//      remains with the UI. 
// 
//  2.  Permission to use, copy, and modify this software and its documentation
//      for education, research, and non-profit purposes is hereby granted
//      to Licensee, provided that the copyright notice, the original author's
//      names and unit identification, and this permission notice appear on
//      all such copies, and that no charge be made for such copies.  Any
//      entity desiring permission to incorporate this software into commercial
//      products should contact:
// 
//           Professor Daniel A. Reed                 reed@cs.uiuc.edu
//           University of Illinois
//           Department of Computer Science
//           2413 Digital Computer Laboratory
//           1304 West Springfield Avenue
//           Urbana, Illinois  61801
//           USA
// 
//  3.  Licensee may not use the name, logo, or any other symbol of the UI
//      nor the names of any of its employees nor any adaptation thereof in
//      advertizing or publicity pertaining to the software without specific
//      prior written approval of the UI.
// 
//  4.  THE UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE
//      SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS
//      OR IMPLIED WARRANTY.
// 
//  5.  The UI shall not be liable for any damages suffered by Licensee from
//      the use of this software.
// 
//  6.  The software was developed under agreements between the UI and the
//      Federal Government which entitle the Government to certain rights.
// 
// *************************************************************************
// 
//  Developed by: The Pablo Research Group
//                University of Illinois at Urbana-Champaign
//                Department of Computer Science
//                1304 W. Springfield Avenue
//                Urbana, IL     61801
// 
//                http://www-pablo.cs.uiuc.edu
// 
//  Send comments to: pablo-feedback@guitar.cs.uiuc.edu
// 
//  Copyright (c) 1987-1998
//  The University of Illinois Board of Trustees.
//       All Rights Reserved.
// 
//  PABLO is a registered trademark of
//  The Board of Trustees of the University of Illinois
//  registered in the U.S. Patent and Trademark Office.
// 
//  Project Manager and Principal Investigator:
//       Daniel A. Reed (reed@cs.uiuc.edu)
//
// Funded in part by the Defense Advanced Research Projects Agency 
// under DARPA contracts DABT63-94-C0049 (SIO Initiative), 
// F30602-96-C-0161, and DABT63-96-C-0027 by the National Science 
// Foundation under the PACI program and grants NSF CDA 94-01124 and
// ASC 97-20202, and by the Department of Energy under contracts
// DOE B-341494, W-7405-ENG-48, and 1-B-333164.
*/ 
/*======================================================================*
// File:  PabloHDF_RT                                       *
// Purpose: support use of Pablo trace library to analyze HDF           *
//        performance                                       *
// Contents:                                                *
//  HDFinitTrace_RT        : initialize real-time tracing         *
//  HDFendTrace_RT         : complete trace                       *
//  initHDFProcTrace_RT    : sets up data structures at init time.      *
//  initproctracert_()     : fortran interface                    *
//  HDFtraceEvent_RT       : called to record event information         *
//  HDFrecordSum     : adds fields of one record to those of      *
//                     another                              *
//  HDFnodeInit      : initializes linked list node         *
//  HDFrecordFileName      : records named HDF identifiers        *
//  BeginIOEventRecord     : initialize before I/O call                 *
//  EndIOEventRecord       : finalize after I/O call              *
//  BeginMPIOEventRecord   : initialize before MPI-I/O call       *
//  EndMPIOEventRecord     : finalize after MPI-I/O call          *
//  BeginHDFEventRecord    : initialize before HDF call                 *
//  EndHDFEventRecord      : finalizie after HDF call             *
//  HDFrecordFileName      : record named identifier information  *
//  HDFassignPabloIDs      : assigns a number to named identifiers      *
//  writeHDFNamePacketsRT  : write SDDF packets for identifier names    *
//  HDFupdateProcLists     : adds records in queue to entries in  *
//                     tables                         *
//  HDFupdateProcs         : called by HDFupdateProcLists to do   *
//                     addition                             *
//  HDFSummarySDDF         : write SDDF event summary packets           *
//  HDFnodeInit      : initialize event node                *
//  HDFrecordSum     : add one event record to another            *
//  getHDFFieldIndex       : get Field Index for counts and times *
//  getHDFByteFieldIndex   : get field index for bytes                  *
//  writeHDFRecDescrptrsRT : write HDF Record Descriptor packets  *
//  printFileMappingsRT    : print map of named identifiers       *
//  _hdfNameDescriptor()   : writes SDDF descriptor packet for names    *
//======================================================================*/
#ifndef PCF_BUILD
#ifdef _HDF5_
#include "H5config.h"
#endif
#include "SystemDepend.h"
#include "Trace.h"
#include "TraceParam.h"
#include "ProcIDs.h"
#include "IO_TraceParams.h"
#include "IOTrace.h"
#include "HDFTrace.h"
#include "SDDFparam.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
/*======================================================================* 
// on ipsc/860 don't include this or you'll get multiply defined SEEK_  *
//======================================================================*/
#ifndef __NX
#include <unistd.h>
#endif
 
#ifndef SUCCESS
#define SUCCESS 0
#define FAILURE   1
#endif

#ifndef TRUE
#define TRUE 1
#define FALSE     0
#endif
#define NEG_THREAD_ID -999

#include "HDFrecord_RT.h"

#ifdef H5_HAVE_MPIOTRACE
#include "mpi.h"
#include "MPIO_EventArgs.h"
#endif

#ifndef TRgetThreadID
#define TRgetThreadID  TRgetNode
#endif

#ifndef TRnumNodes
#define TRnumNodes 1
#endif

#define AllThreads -1

/*======================================================================*
//  User output file pointer.                               *
//======================================================================*/
FILE *outP;
/*======================================================================*
// Data Structures:                                         *
//                                                    *
// HDFQueues:   an array of linked list.  Each list corresponds to an   *
//              HDF event and contains an entry for each different      *
//          thread and data set referenced by a call to that event  *
//                                                    *
// CallStack:     a stack of HDFnode_t objects.  At any given time, the   *
//          stack represents the calling stack of the HDF routines      *
//                                                    *
// HDFfileList: a linked list of named identifiers and identifier       *
//          numbers.  This is processed later to assign a single  *
//          numbers to identifiers with the same name.            *
//======================================================================*/
HDFnode_t **HDFQueues;
HDFnode_t *CallStack;
HDFnode_t *TagQueue;
fileRec_t *HDFfileList;
/*======================================================================*
// Internal Function prototypes                                   *
//======================================================================*/
void HDFinitTrace_RT( char *, int, int );
void HDFendTrace_RT();
int initproctracert_( void );
int initHDFProcTrace_RT( void );
void HDFtraceEvent_RT( int , char *, unsigned ) ;
void BeginIOEventRecord ( int, CLOCK , void * );
void EndIOEventRecord ( int , CLOCK , void * );
void BeginMPIOEventRecord ( int, CLOCK , void *, int ); 
void EndMPIOEventRecord ( int , CLOCK  , void *, int);
void BeginHDFEventRecord( int , CLOCK  );
void EndHDFEventRecord ( CLOCK  ,void *);
void HDFrecordFileName( HDFsetInfo * );
void HDFassignPabloIDs( int *, char *** );
void writeHDFNamePacketsRT( char **, int );
void HDFupdateProcLists( void );
void HDFupdateProcs( HDFnode_t * );
void HDFSummarySDDF( HDFnode_t *, int );
void HDFnodeInit ( HDFnode_t * ) ;
void HDFrecordSum ( HDFrec_t *, HDFrec_t * );
int getHDFFieldIndex( int );
int getHDFByteFieldIndex( int );
void writeHDFRecDescrptrsRT( void );
void printFileMappingsRT( char *, char **, int );
void _hdfNameDescriptor( void );
void _hdfDescriptorRT( char *, char *, int );
void HDFfinalTimeStamp( void );
void getHDFprocName( int index, char buff[41] );
void IOtraceInit( char*, int, int );
/*======================================================================*
// Global variables                                               *
//======================================================================*/
HDFnode_t InitNode;           /* Node used in initialization            */
HDFrec_t Tally;               /* Node used to get total           */
char *FileName;               /* Name of Trace file               */
HDFsetInfo openInfo;          /* Info about file opened           */
char openName[256];           /* Name of opened file              */
extern char *hdfRecordPointer;
extern char HDFprocNames[][40];
/*======================================================================*
// NAME                                                     *
//     HDFinitTrace_RT-- initialize HDF real-time tracing         *
// USAGE                                              *
//     VOID HDFinitTrace_RT( fileName )                           *
//                                                    *
//     char *fileName;        IN: name of output file             *
// RETURNS                                            *
//     None.                                                *
//======================================================================*/
void HDFinitTrace_RT( char *fileName, int procNum, int OUTSW )
{
   int error;
   TRgetClock( &epoch );
   error = initHDFProcTrace_RT() ;
   if ( error != SUCCESS ) 
   {
      fprintf (stderr,"Unable to Initialize properly.  Exiting program\n");
      exit(-1);
   }
   FileName = ( char * ) malloc ( strlen( fileName ) + 10 );
   /*===================================================================*
   // Here the library was built to linked with the MPI and MPIO  *
   // libraries.  However, the use may chose not to run with MPI. *
   // A check is made to see if MPI has been initialized.  If so,       *
   // a trace file is assigned to the current node with the number      *
   // of the node as a suffix; if not, only one file is opened    *
   // and it is not given a suffix.                         *
   //===================================================================*/
   IOtraceInit( fileName, procNum, OUTSW );
}
/*======================================================================*
// NAME                                                     *
//     HDFendTrace-- end HDF tracing                              *
// USAGE                                              *
//     VOID HDFendTrace_RT(void)                            *
// RETURNS                                            *
//     None.                                                *
//======================================================================*/
void HDFendTrace_RT( )
{
   int j, numSetIDs;
   HDFnode_t *P;
   char **Names;

   HDFfinalTimeStamp();
   /*===================================================================*
   //  Assing pablo ids to named identifiers and tag records            *
   //===================================================================*/
   HDFassignPabloIDs( &numSetIDs, &Names );
   /*===================================================================*
   //  Create a file name for the File map file.                  *
   //  Disable for now.                                     *
   //===================================================================*/
/*    mapFile = (char *)malloc( strlen(FileName) + 4 );
   strcpy(mapFile,FileName);
   strcat(mapFile,".map"); */
   /*===================================================================*
   //  print the file mappings.                                   *
   //===================================================================*/
/*        printFileMappingsRT( mapFile, Names, numSetIDs ); */
   /*===================================================================*
   // Print SDDF summary records                            *
   //===================================================================*/
   writeHDFRecDescrptrsRT();
   writeHDFNamePacketsRT( Names, numSetIDs );
      for ( j = 0; j < NumHDFProcs; ++j ) {
      HDFSummarySDDF( HDFQueues[j], j );
   }  
   endTracing();
}
/*======================================================================*
// initHFDProcTrace_RT                                      *
//    This function initializes data structures specific to       * 
//    the HDF real-time procedure entry/exit tracing extensions of      *
//      the Pablo instrumentation library.                        *
//======================================================================*/
int initproctracert_( void )

{
   return initHDFProcTrace_RT();
}

int initHDFProcTrace_RT( void )
{
   int i; 
   int j; 
   int size;
   int numProcs = NumHDFProcs;

   if ( traceProcessorNumber == -1 ) 
   {
      traceProcessorNumber = TRgetDefaultProcessor();
   }
   /*===================================================================*
   // Initialize InitNode used for node initialization.           *
   //===================================================================*/
   InitNode.ptr = NULL;
   InitNode.eventID = 0;             
   InitNode.lastIOtime = zeroClock;
   InitNode.record.nCalls = 0;             
   InitNode.record.lastCall = zeroClock;
   InitNode.record.incDur = zeroClock;              
   InitNode.record.excDur = zeroClock;              
   InitNode.record.hdfID = 0;             
   InitNode.record.xRef = 0;             
   for ( j = 0; j < nTallyFields; ++j ) 
   {
           InitNode.record.times[j] = zeroClock; 
   }
   for ( j = 0; j < nTallyFields; ++j ) 
   {
           InitNode.record.counts[j] = 0; 
   }
   for ( j = 0; j < nByteFields; ++j ) 
   {
           InitNode.record.bytes[j] = 0; 
   }
   for ( i = 0; i < nByteFields; ++i ) 
   {
      for ( j = 0; j < nBkts; ++j ) 
      {
         InitNode.record.Hists[i][j] = 0;
      }
   }
   /*===================================================================*
   // initialize linked list used to keep track of named hdf            *
   // identifiers.                                          *
   //===================================================================*/
   HDFfileList = NULL;
   /*===================================================================*
   // Allocate a one dimensional array of pointers to queues of   *
   // HDFnodes.  There is one queue for each thread and one for   *
   // each HDF procedure.  Each queue will be a list of summary   *
   // records distinquished by file type and                      *
   //===================================================================*/
   size = (int)(numProcs*sizeof( HDFnode_t * ));
   HDFQueues = (HDFnode_t **)malloc( size );
   if ( HDFQueues == NULL ) 
   {
      fprintf(stderr,"Failed to allocate HDFQueues in initHDFProcTrace\n");
      return FAILURE;
   }
   for ( j = 0; j < numProcs; ++j ) 
   {
      HDFQueues[j] = NULL;
   }
   /*===================================================================*
   // Initialize call stack to a dummy node and TagQueue to NULL        *
   //===================================================================*/
   CallStack = (HDFnode_t *)malloc( sizeof(HDFnode_t) );
   *CallStack = InitNode;
   TagQueue = NULL ;
   return SUCCESS;
}
/*======================================================================*
// This is called from the HDF and I/O routines when real-time summary  *
// tracing is used.  It sets up a call stack for the specific thread in *
// use if no stack is yet set up.  It then calls calls a routine to     *
// handle the event based on whether it is an I/O or HDF call.          *
//======================================================================*/
void HDFtraceEvent_RT( int eventType, char *dataPtr, unsigned dataLen ) 
{
   CLOCK    seconds;

   seconds = getClock();

   if ( isBeginIOEvent ( eventType ) || eventType == ID_malloc ) 
   {
      BeginIOEventRecord ( eventType, seconds, dataPtr ) ;
   } 
   else if ( isEndIOEvent( eventType )  || eventType == -ID_malloc) 
   {
      EndIOEventRecord ( eventType, seconds, dataPtr );
   } 
   else if ( isBeginHDFEvent( eventType ) ) 
   { 
      BeginHDFEventRecord ( eventType , seconds ) ;
   } 
   else if ( isEndHDFEvent( eventType ) ) 
   {
      EndHDFEventRecord ( seconds, dataPtr );
#ifdef  H5_HAVE_MPIOTRACE
   } 
   else if ( isBeginMPIOEvent( eventType ) ) 
   { 
      BeginMPIOEventRecord ( eventType, seconds, dataPtr, dataLen ) ;
   } 
   else if ( isEndMPIOEvent( eventType ) ) 
   {
      EndMPIOEventRecord ( eventType, seconds, dataPtr, dataLen );
#endif  /* H5_HAVE_MPIOTRACE */
   } 
   else 
   {
      fprintf(stderr,"eventType %d, dataLen = %u\n",eventType,dataLen);
   } 
}
/*======================================================================* 
// BeginIOEventRecord:                                                  *
//  This routine simply records the time in the record on the top of    *
//  the stack.                                              *
//======================================================================*/ 
void BeginIOEventRecord ( int eventType, CLOCK seconds, void *dataPtr  )
{
   char *name;
   /*===================================================================*
   // save the time value temporarily in top of stack             *
   // When the end record is received, the duration can be computed.    *
   //===================================================================*/
   CallStack->lastIOtime = seconds;
   /*===================================================================*
   // get the ID or name of the file accessed from the structure  *
   // passed as dataPtr.                                    *
   //===================================================================*/
   switch ( eventType )
   {
      case fopenBeginID:
      case openBeginID:
      {
         name = (char *)(dataPtr) + 2*sizeof(int);
         strcpy( openName, name );
       break;
      }
      case fcloseBeginID:
      case closeBeginID:
      {
         CallStack->record.hdfID = *( long *)dataPtr;
       break;
      }
      case readBeginID:
      case freadBeginID:
      case writeBeginID:
      case fwriteBeginID:
      case lseekBeginID:
      case fseekBeginID:
      case fsetposBeginID:
      case rewindBeginID:
      {
         CallStack->record.hdfID = *(int *)dataPtr;
       break;
      }
      default:
      {
         break;
      }
   }
}
/*======================================================================* 
// EndIOEventRecord:                                        *
//  This routine retrieves the entry time saved on the top of the stack *
//  and computes the duration of the I/O event.  This is added to the   *
//  record field corresponding to this type of I/O.  The Bytes field in *
//  the record is updated if this is a read or write operation.         *
//======================================================================*/ 
void EndIOEventRecord ( int eventType, CLOCK secs, void *dataPtr )
{
   CLOCK incDur;
   int i, Field, ByteField, bytes;
   
   incDur = clockSubtract(secs,CallStack->lastIOtime) ;
   Field = getHDFFieldIndex( eventType ) ;
   CallStack->record.times[Field] 
   = clockAdd ( CallStack->record.times[Field] , incDur ) ;
   ++CallStack->record.counts[Field];
   ByteField = getHDFByteFieldIndex( Field ) ;
   switch ( eventType ) 
   {
      case readEndID:
      case freadEndID:
      case writeEndID:
      case fwriteEndID:
      case -ID_malloc:
      {
         bytes = *((int *)dataPtr);
         CallStack->record.bytes[ByteField] += bytes;
         /*======================================================
         // update histogram                          *
         //=====================================================*/
         i = -1;
         while ( bytes >= BktLim[i+1] ) ++i  ;
         if ( i >= 0 ) ++CallStack->record.Hists[ByteField][i];
         break;
      }
      case fopenEndID:
      case openEndID:
      {
         openInfo.setName = openName;
         openInfo.setID = (int)(*((long *)dataPtr));
         CallStack->record.hdfID = openInfo.setID;
         HDFrecordFileName ( &openInfo );
         break;
      }
      default:
      {
         break;
      }
   }
                  
}
#ifdef H5_HAVE_MPIOTRACE
/*======================================================================*
// BeginMPIOEventRecord:                                                *
//  This routine simply records the time in the record on the top of    *
//  the stack.                                              *
//======================================================================*/ 
void BeginMPIOEventRecord( int eventType, 
                         CLOCK seconds, 
                         void *data,
                         int dataLen )
{
   HDFsetInfo *dataPtr;
   dataPtr = (HDFsetInfo *)data;
   /*===================================================================*
   // save the time value temporarily in top of stack             *
   // When the end record is received, the duration can be        *
   // computed.                                             *
   //===================================================================*/
   CallStack->lastIOtime = seconds;
   /*===================================================================*
   // get useful info from the structure pointed to by dataPtr.         *
   // Form most cases, this is the file ID.  For mpiOpen, it is the     *
   // name of the file.  For mpiDelete, no information is of any  *
   // use.                                            *
   //===================================================================*/
   if ( dataLen == 0 ) return;
   CallStack->record.hdfID = dataPtr->setID; 
   switch ( eventType ) 
   {
      case HDFmpiOpenID:
      {
         strcpy( openName, dataPtr->setName );
         break;
      }
      case HDFmpiReadAtID:
      {
         CallStack->record.bytes[MPIOreadBytesReq] += dataPtr->numBytes;
         break;
      }
      case HDFmpiReadAtAllID:
      {
         CallStack->record.bytes[MPIOreadAllBytesReq] += dataPtr->numBytes;
         break;
      }
      case HDFmpiWriteAtID:
      {
         CallStack->record.bytes[MPIOwriteBytesReq] += dataPtr->numBytes;
         break;
      }
      case HDFmpiWriteAtAllID:
      {
         CallStack->record.bytes[MPIOwriteAllBytesReq] += dataPtr->numBytes;
         break;
      }
      case HDFmpiIreadAtID:
      {
         CallStack->record.bytes[MPIOiReadBytesReq] += dataPtr->numBytes;
         break;
      }
      case HDFmpiIwriteAtID:
      {
         CallStack->record.bytes[MPIOiWriteBytesReq] += dataPtr->numBytes;
         break;
      }
      case HDFmpiReadID:
      {
         CallStack->record.bytes[MPIOreadBytesReq] += dataPtr->numBytes;
         break;
      }
      case HDFmpiReadAllID:
      {
         CallStack->record.bytes[MPIOreadAllBytesReq] += dataPtr->numBytes;
         break;
      }
      case HDFmpiWriteID:
      {
         CallStack->record.bytes[MPIOwriteBytesReq] += dataPtr->numBytes;
         break;
      }
      case HDFmpiWriteAllID:
      {
         CallStack->record.bytes[MPIOwriteAllBytesReq] += dataPtr->numBytes;
         break;
      }
      case HDFmpiIreadID:
      {
         CallStack->record.bytes[MPIOiReadBytesReq] += dataPtr->numBytes;
         break;
      }
      case HDFmpiIwriteID:
      {
         CallStack->record.bytes[MPIOiWriteBytesReq] += dataPtr->numBytes;
         break;
      }
      default:
      {
         break;
      }
   }
}
/*======================================================================*
// EndMPIOEventRecord:                                      *
//  This routine retrieves the entry time saved on the top of the stack *
//  and computes the duration of the MPI-I/O event.  This is added to   *
//  the record field corresponding MPI-I/O.                       *
//======================================================================*/ 
void EndMPIOEventRecord ( int eventType, 
                        CLOCK secs, 
                        void *data,
                        int dataLen )
{
   CLOCK incDur;

   HDFsetInfo* dataPtr;
   incDur = clockSubtract(secs,CallStack->lastIOtime) ;
   CallStack->record.times[MPI] 
          = clockAdd ( CallStack->record.times[MPI], incDur );
   ++CallStack->record.counts[MPI];
   if ( dataLen == 0 ) 
   {
      return;
   }
   dataPtr = (HDFsetInfo *)data;
   switch ( eventType ) 
   {
      case -HDFmpiOpenID:
      {
         /*===========================================================*
         // open and record the information.                      *
         //===========================================================*/
       openInfo.setName = openName;
       openInfo.setID = dataPtr->setID;
       CallStack->record.hdfID = openInfo.setID;
       HDFrecordFileName ( &openInfo );
         break;
      }
      case -HDFmpiReadAtID:
      {
         ++CallStack->record.counts[MPIOread] ;
         CallStack->record.times[MPIOread] 
          = clockAdd ( CallStack->record.times[MPIOread], incDur );
         CallStack->record.bytes[MPIOreadBytesTrans] += dataPtr->numBytes; 
         break;
      }
      case -HDFmpiReadAtAllID:
      {
         ++CallStack->record.counts[MPIOreadAll] ;
         CallStack->record.times[MPIOreadAll] 
          = clockAdd ( CallStack->record.times[MPIOreadAll], incDur );
         CallStack->record.bytes[MPIOreadAllBytesTrans] += dataPtr->numBytes;
         break;
      }
      case -HDFmpiWriteAtID:
      {
         ++CallStack->record.counts[MPIOwrite] ;
         CallStack->record.times[MPIOwrite] 
          = clockAdd ( CallStack->record.times[MPIOwrite], incDur );
         CallStack->record.bytes[MPIOwriteBytesTrans] += dataPtr->numBytes;
         break;
      }
      case -HDFmpiWriteAtAllID:
      {
         ++CallStack->record.counts[MPIOwriteAll] ;
         CallStack->record.times[MPIOwriteAll] 
          = clockAdd ( CallStack->record.times[MPIOwriteAll], incDur );
         CallStack->record.bytes[MPIOwriteAllBytesTrans] += dataPtr->numBytes;
         break;
      }
      case -HDFmpiIreadAtID:
      {
         ++CallStack->record.counts[MPIOiRead] ;
         CallStack->record.times[MPIOiRead] 
             = clockAdd ( CallStack->record.times[MPIOiRead], incDur );
         break;
      }
      case -HDFmpiIwriteAtID:
      {
         ++CallStack->record.counts[MPIOiWrite] ;
         CallStack->record.times[MPIOiWrite] 
             = clockAdd ( CallStack->record.times[MPIOiWrite], incDur );
         break;
      }
      case -HDFmpiReadID:
      {
         ++CallStack->record.counts[MPIOread] ;
         CallStack->record.times[MPIOread] 
          = clockAdd ( CallStack->record.times[MPIOread], incDur );
         CallStack->record.bytes[MPIOreadBytesTrans] += dataPtr->numBytes;
         break;
      }
      case -HDFmpiReadAllID:
      {
         ++CallStack->record.counts[MPIOreadAll] ;
         CallStack->record.times[MPIOreadAll] 
          = clockAdd ( CallStack->record.times[MPIOreadAll], incDur );
         CallStack->record.bytes[MPIOreadAllBytesTrans] += dataPtr->numBytes;
         break;
      }
      case -HDFmpiWriteID:
      {
         ++CallStack->record.counts[MPIOwrite] ;
         CallStack->record.times[MPIOwrite] 
          = clockAdd ( CallStack->record.times[MPIOwrite], incDur );
         CallStack->record.bytes[MPIOwriteBytesTrans] += dataPtr->numBytes;
         break;
      }
      case -HDFmpiWriteAllID:
      {
         ++CallStack->record.counts[MPIOwriteAll] ;
         CallStack->record.times[MPIOwriteAll] 
          = clockAdd ( CallStack->record.times[MPIOwriteAll], incDur );
         CallStack->record.bytes[MPIOwriteAllBytesTrans] += dataPtr->numBytes;
         break;
      }
      case -HDFmpiIreadID:
      {
         ++CallStack->record.counts[MPIOiRead] ;
         CallStack->record.times[MPIOiRead] 
          = clockAdd ( CallStack->record.times[MPIOiRead], incDur );
         break;
      }
      case -HDFmpiIwriteID:
      {
         ++CallStack->record.counts[MPIOiWrite] ;
         CallStack->record.times[MPIOiWrite] 
          = clockAdd ( CallStack->record.times[MPIOiWrite], incDur );
         break;
      }
      default:
      {
         ++CallStack->record.counts[MPIOother] ;
         CallStack->record.times[MPIOother] 
          = clockAdd ( CallStack->record.times[MPIOiWrite], incDur );
         break;
      }
   }
}
#endif /* H5_HAVE_MPIOTRACE */
/*======================================================================*
//   BeginHDFEventRecord:                                   * 
//    This function puts a trace record on the stack corresponding to   *
//    this thread.  If no stack exists, one is created.  If no record   * 
//    exist, a record is created.                                       * 
//======================================================================*/ 
void BeginHDFEventRecord( int eventID, CLOCK secs )
{
      HDFnode_t *HDFrec;
      /*==============================================================*
      // Create a record. Push it onto the call stack.                *
      //==============================================================*/
        HDFrec = (HDFnode_t *)malloc( sizeof(HDFnode_t) );
        HDFnodeInit( HDFrec ) ;
      HDFrec->eventID = eventID;
      HDFrec->ptr = CallStack;
      CallStack = HDFrec ;
      /*==============================================================*
      // save time stamp in record.                         *
      //==============================================================*/
      HDFrec->record.lastCall = secs;
}
/*======================================================================* 
// EndHDFEventRecord:                                       *
//  This routine pops the HDF record from the top of the stack          *
//  corresponding to this thread and computes the inclusive duration    *
//  and adds it to the inclusive duration field of this record and to   *
//  the HDF time field of the calling routines record.                  *
//======================================================================*/ 
void EndHDFEventRecord ( CLOCK secs, void *dataPtr )
{
        HDFsetInfo      *info;
      HDFnode_t   *HDFrec;
      CLOCK             incSecs;
      static int  dummyIDs = -4;
      /*==============================================================*
      // pop record from top of the stack, compute inclusive duration   *
      // and set the corresponding record field and increment nCalls.   *
      //==============================================================*/
      HDFrec = CallStack;
      CallStack = CallStack->ptr;
      if ( CallStack == NULL ) {
         fprintf(stderr,">>> EndHDFEventRecord: Call Stack is empty. <<<\n");
         return;
      }
      incSecs = clockSubtract(secs,HDFrec->record.lastCall) ;
                  
      HDFrec->record.incDur = incSecs;
      ++HDFrec->record.nCalls;
      /*==============================================================*
      // add old record to chain to have its xRef field tagged.   *
      //==============================================================*/
      HDFrec->ptr = TagQueue;
      TagQueue = HDFrec;
      /*==============================================================*
      // Add set ID information.                            *
      //==============================================================*/
      if ( dataPtr != NULL ) {
         info = (HDFsetInfo *)dataPtr;
         if ( info->setName != NULL ) {
            if ( info->setID == 0 ) {
               info->setID = dummyIDs--;
            }
            HDFrecordFileName ( info );
         }
         HDFrec->record.hdfID = info->setID;
      }
      /*==============================================================*
      // Update the HDF totals for the calling program.           *
      //==============================================================*/
        CallStack->record.times[ HDF_ ] 
           = clockAdd( CallStack->record.times[ HDF_ ] , incSecs ) ;
        ++CallStack->record.counts[ HDF_ ] ;
      /*==============================================================*
      // If the stack has only one record it represents the main  * 
      // program.  Tag all of the records on the TagQueue and tally   * 
      // them up.                                     * 
      //==============================================================*/
        if ( CallStack->ptr == NULL ) {
           HDFupdateProcLists( );
      }
}
/*======================================================================* 
// This routine keeps track of the identifier names and tags.  Some     *
// names may be associated with more than one tag.  This will be  *
// rectified when final tallies are done.                   *
//======================================================================*/
void HDFrecordFileName( HDFsetInfo *info )
{
      fileRec_t *P;
      char *t;
      int match; 
      long id;
      P = HDFfileList;
      match = FALSE;
      id = info->setID;
      while ( P != NULL && match == FALSE ) {
         if ( strcmp( P->fileName, info->setName ) != 0 && P->hdfID == id ) {
            match = TRUE;
         } else {
            P = P->ptr;
         }
      }
      if ( match == FALSE ) {
         P = ( fileRec_t *) malloc( sizeof( fileRec_t ) );
         P->ptr = HDFfileList;
         HDFfileList = P;
         t = (char *)malloc( strlen( info->setName ) + 1 );
         strcpy ( t, info->setName ) ;
         P->fileName = t;
         P->hdfID = info->setID;
         P->PabloID = 0;
      } 
}  
/*======================================================================* 
// This routine assigns a unique Pablo ID to each unique name           *
// regardless of the HDF tag.                               *
// It then goes through the HDFRecordQueue and marks each record with   *
// the PabloID corresponding to the hdfID and xRef fields or 0.         *
//======================================================================*/
void HDFassignPabloIDs( int *nSetIDs, char ***Names )
{
      fileRec_t *F, *G;
      HDFnode_t *P;
      int j; 
      long PabloID = 1;
      long hdfID, xRef;
      char *fName, **T;

      F = HDFfileList;
        /*==============================================================*
        // Assign the same ID to identical names.                 *
        //==============================================================*/
      while ( F != NULL ) {
         if ( F->PabloID == 0 ) {
            F->PabloID = PabloID++;
            fName = F->fileName;
            G = F->ptr;
            while ( G != NULL ) {
               if ( strcmp( G->fileName , fName ) == 0 ) {
                  G->PabloID = F->PabloID;
               }
               G = G->ptr;
            }
         }
         F = F->ptr;
      }
      *nSetIDs = (int)(PabloID - 1);
        if ( *nSetIDs <= 0 ) return;
        /*==============================================================*
      // Repace hdfID and xRef fields with corresponding Pablo ID *
        //==============================================================*/
      for ( j = 0; j < NumHDFProcs; ++j ) {
         P = HDFQueues[j] ;
         while ( P != NULL ) {
            hdfID = P->record.hdfID;
            if ( hdfID != 0 ) {
               PabloID = 0;
                 F = HDFfileList;
               while ( F != NULL && PabloID == 0 ) {
                    if ( hdfID == F->hdfID ) {
                     PabloID = F->PabloID;
                  }
                  F = F->ptr;
               }
               P->record.hdfID = PabloID;
            }
            xRef = P->record.xRef;
            if ( xRef != 0 ) {
               PabloID = 0;
                 F = HDFfileList;
               while ( F != NULL && PabloID == 0 ) {
                    if ( xRef == F->hdfID ) {
                     PabloID = F->PabloID;
                  }
                  F = F->ptr;
               }
               P->record.xRef = PabloID;
            }
              P = P->ptr;
         } /* end while ( P != NULL ) */
        } /* end for */
      /*==============================================================*
      // get a list of all the unique names and order them according  *
      // to their Pablo IDs.                                *
      //==============================================================*/
      T = ( char ** )malloc( (*nSetIDs+1) * sizeof( char * ) );
      for ( j = 0; j <= *nSetIDs; ++j ) {
         T[j] = NULL;
      }
      F = HDFfileList;
      while ( F != NULL ) {
         PabloID = F->PabloID  ;
         if ( T[PabloID] == NULL ) {
            T[PabloID] = ( char * )malloc( strlen( F->fileName ) + 1 );
            strcpy( T[PabloID], F->fileName ) ;
         }
         free((void *)(F->fileName));
         G = F;
         F = F->ptr;
         free ( (void *)G );
      }
      *Names = T;
}
/*======================================================================* 
// This routine writes SDDF packets to SDDF file containing information *
// about the named identifiers found in the program.              *
//======================================================================*/
void writeHDFNamePacketsRT( char **Names, int numSetIDs )
{
      int j;
      HDFNamePacket_t NamePkt;
      char *BUFF, *fName;
      int buffSize;
      /*==============================================================*
      // Allocate a buffer to hold the packet.  Allow 80 chars for      *
      // identifier name.                                   *
      //==============================================================*/
      buffSize = sizeof(HDFNamePacket_t) + 80;
      BUFF = (char *)malloc(buffSize);
      /*==============================================================*
      // Fill in constant information                             *
      //==============================================================*/
      NamePkt.packetType = PKT_DATA;
      NamePkt.packetTag = FAMILY_NAME;
      /*==============================================================*
      // Fill in named identifier information and write to SDDF file    *
      //==============================================================*/
      for ( j = 1; j <= numSetIDs; ++j ) {
         fName = Names[j];
         NamePkt.packetLength = (int)(sizeof(NamePkt) + strlen(fName));
         NamePkt.fileType = 0;            /* not currently used   */
         NamePkt.fileID = j;
         NamePkt.nameLen = (int)strlen(fName) ;
         if ( buffSize < NamePkt.packetLength ) {
            free((void *)BUFF) ;
            buffSize = NamePkt.packetLength + 80;
            BUFF = (char *)malloc( buffSize ) ;
         }
         /*===========================================================*
         // Copy packet data and tack on identifier name          *
         //===========================================================*/
         memcpy( BUFF, &NamePkt, sizeof(NamePkt) );
         memcpy( BUFF + sizeof(NamePkt) , fName, strlen(fName) );
         putBytes( BUFF , NamePkt.packetLength ) ;
      }
      free((void *)BUFF);
}
/*======================================================================*
// Tag xRef field of all records in this queue with the hdfID of the    *
// highest level caller. Also                               *
// This routine takes the records after they have been tagged and adds  *
// their fields to the apporopriate position in the HDFQueues structure *
//======================================================================*/
void HDFupdateProcLists( void )
{
      HDFnode_t *P, *Q;
      long hdfID;

      hdfID = TagQueue->record.hdfID;
      P = TagQueue;
      while ( P != NULL ) {
         P->record.xRef = hdfID;
         Q = P->ptr;
         HDFupdateProcs( P );
         P = Q;
      }
        TagQueue = NULL;
}
/*======================================================================*
// This routine takes as input a node pointer P  and looks for a Total  *
// record with this same eventID, hdfID and xRef.  If such a record     *
// exists, P is added to the record, otherwise a record is created and  *
// its values are set to P's.                               *
//======================================================================*/
void HDFupdateProcs( HDFnode_t *P )
{
      int procIndex, eventID;
      long hdfID, xRef;
      HDFnode_t *Q;
      eventID = P->eventID;
      procIndex = ProcIndexForHDFEntry( eventID );
        hdfID = P->record.hdfID;
        xRef = P->record.xRef;
      Q = HDFQueues[ procIndex ];
      /*==============================================================*
      // First determine if a tally node exists that matches the        *
      // eventID, hdfID and xRef of P.                      *
      //==============================================================*/
      while ( Q != NULL && 
            (( Q->record.hdfID != hdfID ) || ( Q->record.xRef != xRef )) ) {
           Q = Q->ptr;
      }
      if ( Q == NULL ) {
         /*===========================================================*
         // No tally record matches the hdfID and xRef so put P in    *
         // the queue.                                      *
         //===========================================================*/
         P->ptr = HDFQueues[ procIndex ];
         HDFQueues[ procIndex ] = P;
      } else {
         /*===========================================================*
         // add P to the exiting record and free it.              *
         //===========================================================*/
           HDFrecordSum ( &Q->record , &P->record );
         free((void *)P);
      }
}
/*======================================================================*
// Print SDDF records for all records in this linked list.        *
//======================================================================*/
void HDFSummarySDDF( HDFnode_t *P, int procIndex )
{
      int i, j, arrayLen, nodeID, nCalls;
      int allIOCount;
      CLOCK allIOTime, excDur;
      double t;
      char buff[1024];
      char *Packet;
      HDFnode_t *Q;
        struct
        {
           int packetLen;
           int packetType;
           int packetTag;
           int eventID;
           double Seconds;
           double IncDur;
           double ExcDur;
           long HDFid;
           long XREFid;
      }  Header;

      Header.packetLen = sizeof(Header) 
                       + sizeof(int)                   /* n Calls     */
                       + sizeof(int)                   /* array len   */
                   + nTallyFields*sizeof(double)       /* times array */
                       + sizeof(int)                   /* array len   */
                       + nTallyFields*sizeof(int)      /* count array */
                       + sizeof(int)                   /* array len   */
                       + nByteFields*sizeof(int)       /* bytes array */
                       + nHistFields*sizeof(int)       /* array lens  */
                       + nHistFields*nBkts*sizeof(int) /* byte hist   */
                       + sizeof(int);                  /* nodeID      */
      Header.packetTag = HDF_SUMMARY_FAMILY +
                     ( procIndex + 1 )*8 + RECORD_TRACE ;
      Header.packetType = PKT_DATA;
      nodeID = TRgetNode();
        while ( P != NULL ) {
         Q = P->ptr;
         /*===========================================================*
         // Total the I/O time and counts                         *
         //===========================================================*/
           allIOTime = zeroClock;
           for ( j = FirstIO; j <= LastIO; ++j ) {
              allIOTime = clockAdd( allIOTime, P->record.times[j] );
           }
           P->record.times[AllIO] = allIOTime;
 
           allIOCount = 0;
           for ( j = FirstIO; j <= LastIO; ++j ) {
              allIOCount += P->record.counts[j];
           }
           P->record.counts[AllIO] = allIOCount;
         /*===========================================================*
         // compute exclusive duration.                     *
         //===========================================================*/
         excDur = clockSubtract(P->record.incDur,allIOTime);
         excDur = clockSubtract(excDur,P->record.times[HDF_]);
         excDur = clockSubtract(excDur,P->record.times[MPI]);
         /*===========================================================*
         // print header information.                             *
         //===========================================================*/
         Header.eventID = P->eventID;
           Header.Seconds = clockToSeconds(P->record.lastCall);
         Header.IncDur  = clockToSeconds( P->record.incDur );
         Header.ExcDur  = clockToSeconds(excDur);
         Header.HDFid   = P->record.hdfID;
         Header.XREFid  = P->record.xRef;
         Packet = buff;
         memcpy( Packet, &Header, sizeof(Header) );
         Packet += sizeof(Header);
         /*===========================================================*
         // copy number of calls to Packet.                       *
         //===========================================================*/
         nCalls  = P->record.nCalls;
         memcpy( Packet, &nCalls, sizeof(int) );
         Packet += sizeof(int);
         /*===========================================================*
         // copy length of times array and times array to Packet. *
         //===========================================================*/
         arrayLen = nTallyFields;
         memcpy( Packet, &arrayLen, sizeof(int) );
         Packet += sizeof(int);
           for ( j = 0; j < nTallyFields; ++j ) {
            t = clockToSeconds(P->record.times[j]); 
            memcpy( Packet, &t, sizeof(double) );
            Packet += sizeof(double);
         }
         /*===========================================================*
         // copy length of counts array and counts array to Packet.     *
         //===========================================================*/
         arrayLen = nTallyFields;
         memcpy( Packet, &arrayLen, sizeof(int) );
         Packet += sizeof(int);
         memcpy( Packet, P->record.counts, nTallyFields*sizeof(int) );
         Packet += nTallyFields*sizeof(int);
         /*===========================================================*
         // copy length of bytes array and bytes array to Packet. *
         //===========================================================*/
         arrayLen = nByteFields;
         memcpy( Packet, &arrayLen, sizeof(int) );
         Packet += sizeof(int);
         memcpy( Packet, P->record.bytes, nByteFields*sizeof(int) );
         Packet += nByteFields*sizeof(int);
         /*===========================================================*
         // copy length of historgram arrays and arrays to Packet.      *
         //===========================================================*/
         arrayLen = nBkts;
         for ( i = 0; i < nHistFields; ++i ) 
           {
            memcpy( Packet, &arrayLen, sizeof(int) );
            Packet += sizeof(int);
            memcpy( Packet, P->record.Hists[i], nBkts*sizeof(int) );
            Packet += nBkts*sizeof(int);
         }
         memcpy( Packet, &nodeID, sizeof(int) );
         Packet += sizeof(int);
           arrayLen = Packet-buff;
           memcpy(buff,&arrayLen,sizeof(int));
         putBytes( buff, Packet-buff ); 
           P = Q;
      } 
}
/*======================================================================*
// Initialize a node.                                       *
//======================================================================*/
void HDFnodeInit ( HDFnode_t *S ) 
{
   *S = InitNode;
}
/*======================================================================*
//      Compute IO totals, exclusive durations of the input record T    *
//      then add the fields of T to that of S.                          *
//======================================================================*/
void HDFrecordSum ( HDFrec_t *S, HDFrec_t *T )
{
   int i;
   int j;
      
   S->nCalls    += T->nCalls;
   if ( clockCompare ( S->lastCall, T->lastCall ) < 0 ) 
   {
      S->lastCall  =  T->lastCall ;
   }
   S->incDur    = clockAdd ( S->incDur, T->incDur );
   for ( j = 0; j < nTallyFields; ++j ) 
   {
      S->times[j] =  clockAdd( S->times[j] , T->times[j] ) ;
   }
   for ( j = 0; j < nTallyFields; ++j ) 
   {
      S->counts[j] += T->counts[j] ;
   }
   for ( j = 0; j < nByteFields; ++j ) 
   {
      S->bytes[j] += T->bytes[j] ;
   }
   for ( j = 0; j < nHistFields; ++j ) 
   {
      for ( i = 0; i < nBkts; ++i ) 
      {
         S->Hists[j][i] += T->Hists[j][i] ;
      }
   }
}
/*======================================================================*
// Return the field index corresponding to an IO event ID.  The fields  *
// are specified in an enum statement in an include file.         *
//======================================================================*/
int getHDFFieldIndex( int eventID )
{
   int result = -1;
   switch ( eventID )
   {
      case ID_malloc:
      case -ID_malloc:
      {
         result = Malloc;
         break;
      }
      case openBeginID:
      case openEndID:
      case fopenBeginID:
      case fopenEndID:
      {
         result = Open;
         break;
      }
      case closeBeginID:
      case closeEndID:
      case fcloseBeginID:
      case fcloseEndID:
      {
         result = Close;
         break;
      }
      case readBeginID:
      case readEndID:
      case freadBeginID:
      case freadEndID:
      {
         result = Read;
         break;
      }
      case lseekBeginID:
      case lseekEndID:
      case fseekBeginID:
      case fseekEndID:
      {
         result = Seek;
         break;
      }
      case writeBeginID:
      case writeEndID:
      case fwriteBeginID:
      case fwriteEndID:
      {
         result = Write;
         break;
      }
      case fflushBeginID:
      case fflushEndID:
      case flushBeginID:
      case flushEndID:
      {
         result = Misc;
         break;
      }
      case rewindBeginID:
      case rewindEndID:
      case fsetposBeginID:
      case fsetposEndID:
      {
         result = Misc;
         break;
      }
#ifdef      creadBeginID
      case creadBeginID:
      case creadEndID:
      case creadvBeginID:
      case creadvEndID:
      {
         result = Read;
         break;
      }
      case cwriteBeginID:
      case cwriteEndID:
      case cwritevBeginID:
      case cwritevEndID:
      {
         result = Write;
         break;
      }
      case ireadBeginID:
      case ireadEndID:
      case ireadvBeginID:
      case ireadvEndID:
      {
         result = Aread;
         break;
      }
      case iwriteBeginID:
      case iwriteEndID:
      case iwritevBeginID:
      case iwritevEndID:
      {
         result = Awrite;
         break;
      }
      case iowaitBeginID:
      case iowaitEndID:
      {
         result = Wait;
         break;
      }
      case iodoneBeginID:
      case iodoneEndID:
      {
         result = Misc;
         break;
      }
      case gopenBeginID:
      case gopenEndID:
      {
         result = Open;
         break;
      }
      case iomodeBeginID:
      case iomodeEndID:
      case setiomodeBeginID:
      case setiomodeEndID:
      case lsizeBeginID:
      case lsizeEndID:
      case forflushBeginID:
      case forflushEndID:
      {
         result = Misc;
         break;
      }
#endif      
   }
   return result;
}
/*======================================================================*
// This routine determines the field index in the bytes array of the    *
// HDF records which correspond to a given IO operation.  If the        *
// operation does not transfer bytes, (e.g., open operation), -1 is     *
// returned.                                                *
//======================================================================*/
int getHDFByteFieldIndex( int Operation ) 
{
   int result;
   switch ( Operation )
   {
      case Malloc:
      {
         result = MallocBytes;
         break;
      }
      case Read:
      {
         result = ReadBytes;
         break;
      }
      case Write:
      {
         result = WriteBytes;
         break;
      }
      case Aread:
      {
         result = AreadBytes;
         break;
      }
      case Awrite:
      {
         result = AwriteBytes;
         break;
      }
      case MPIOread:
      {
         result = MPIOreadBytesReq;
         break;
      }
      case MPIOwrite:
      {
         result = MPIOwriteBytesReq;
         break;
      }
      case MPIOreadAll:
      {
         result = MPIOreadAllBytesReq;
         break;
      }
      case MPIOwriteAll:
      {
         result = MPIOwriteAllBytesReq;
         break;
      }
      case MPIOiRead:
      {
         result = MPIOiReadBytesReq;
         break;
      }
      case MPIOiWrite:
      {
         result = MPIOiWriteBytesReq;
         break;
      }
      case MPIOreadTrans:
      {
         result = MPIOreadBytesTrans;
         break;
      }
      case MPIOwriteTrans:
      {
         result = MPIOwriteBytesTrans;
         break;
      }
      case MPIOreadAllTrans:
      {
         result = MPIOreadAllBytesTrans;
         break;
      }
      case MPIOwriteAllTrans:
      {
         result = MPIOwriteAllBytesTrans;
         break;
      }
      default:
      {
         result = -1;
         break;
      }
   }
   return result;
}
/*======================================================================*
// This routine writes the SDDF packet descriptors for the HDF summary  *
// records to the output file.                                    *
//======================================================================*/
void _hdfDescriptorRT( char *recordName, char *recordDescription, 
                                                       int recordFamily )
{
    static char   recordBuffer[ 4096 ];
    int           recordLength;

    hdfRecordPointer = recordBuffer;
    /*==================================================================*
    // Allow space at the beginning of the record for the packet  *
    //length which will be computed after the packet is complete. *
    //==================================================================*/
    sddfWriteInteger( &hdfRecordPointer, 0 );
    /*==================================================================* 
    // The record type, tag, and name                             * 
    //==================================================================*/
    sddfWriteInteger( &hdfRecordPointer, PKT_DESCRIPTOR );
    sddfWriteInteger( &hdfRecordPointer, ( recordFamily | RECORD_TRACE ) );
    sddfWriteString( &hdfRecordPointer, recordName );
    /*==================================================================* 
    // The record attribute count and string pair                 * 
    //==================================================================*/
    sddfWriteInteger( &hdfRecordPointer, 1 );
    sddfWriteString( &hdfRecordPointer, "description" );
    sddfWriteString( &hdfRecordPointer, recordDescription );
    /*==================================================================*
    // The record field count                                     *
    //==================================================================*/
    sddfWriteInteger( &hdfRecordPointer, 16 );
    WRITE_HDF_FIELD( "Event Identifier", 
                   "Event ID",
                     "Corresponding Event",
                   INTEGER, 0 );
    WRITE_HDF_FIELD( "Seconds", 
                 "Seconds", 
                     "Floating Point Timestamp", 
                  DOUBLE, 0 );
    WRITE_HDF_FIELD( "Inclusive Duration", 
                   "Inclusive Duration", 
                   "Inclusive Duration of this Procedure",
                  DOUBLE, 0 );
    WRITE_HDF_FIELD( "Exclusive Duration", 
                   "Exclusive Duration", 
                   "Excludes IO, MPI-IO and other HDF calls",
                  DOUBLE, 0 );
    WRITE_HDF_FIELD2("HDF ID",
                     "HDF ID", "Identifier number",
                     "0", "No HDF ID specified",
                     LONG, 0 );
    WRITE_HDF_FIELD( "Xref ID",
                     "Cross Reference", 
                     "Index of related HDF ID or 0 if none",
                 LONG, 0 );
    WRITE_HDF_FIELD( "N Calls", 
                 "N Calls", 
                 "Number of Calls to this Proc", 
                 INTEGER, 0 );
    WRITE_HDF_FIELD( "Times Array",
                     "Times Array",
                   "Array of Total Operation Times",
                 DOUBLE, 1 );
    WRITE_HDF_FIELD( "Counts Array",
                     "Counts Array",
                   "Array of Total Operation Counts",
                 INTEGER, 1 );
    WRITE_HDF_FIELD( "Bytes Array",
                     "Bytes Array",
                   "Array of Total Bytes Transferred",
                 INTEGER, 1 );
    WRITE_HDF_FIELD( "Malloc Histogram",
                     "Malloc Histogram",
                   "Historgram of size Malloc Requests",
                 INTEGER, 1 );
    WRITE_HDF_FIELD( "Read Histogram",
                     "Read Histogram",
                   "Historgram of size Read Requests",
                 INTEGER, 1 );
    WRITE_HDF_FIELD( "Write Histogram",
                     "Write Histogram",
                   "Historgram of size Write Requests",
                 INTEGER, 1 );
    WRITE_HDF_FIELD( "Aread Histogram",
                     "Aread Histogram",
                   "Historgram of size Asynch Read Requests",
                 INTEGER, 1 );
    WRITE_HDF_FIELD( "Awrite Histogram",
                     "Awrite Histogram",
                   "Historgram of size Asynch Write Requests",
                 INTEGER, 1 );
    WRITE_HDF_FIELD( "Processor Number", 
                 "Node", 
                 "Processor number", 
                 INTEGER, 0 );
    /*=================================================================== 
    // The entire record descriptor packet has been written.            * 
    // Compute and update the record length.                      * 
    // Write the completed record.                          * 
    //==================================================================*/
    recordLength = (int)(hdfRecordPointer - recordBuffer);

    hdfRecordPointer = recordBuffer;
    sddfWriteInteger( &hdfRecordPointer, recordLength );

    putBytes( recordBuffer, (unsigned) recordLength );
}

/*======================================================================* 
//   Internal Routine:  writeHDFRecDescrptrsRT                          * 
//                      Writes record descriptors for the HDF events.   * 
//======================================================================*/
void writeHDFRecDescrptrsRT( void ) 
{
      int j, FAMILY;
        char BUF1[256], BUF2[256] ;
        char buff[41];
      _hdfNameDescriptor();   /* Descriptor for named identifiers */
        for ( j = 0; j < NumHDFProcs; ++j ) {
           if ( HDFQueues[j] != NULL ) {
              getHDFprocName( j, buff );
              strcpy( BUF2, "HDF ");
              strcat( BUF2, buff );
              strcat( BUF2, " Procedure Summary");
              strcpy( BUF1, BUF2 );
              strcat( BUF1, " Trace");
            FAMILY = HDF_SUMMARY_FAMILY + (j + 1)*8;
              _hdfDescriptorRT( BUF1, BUF2, FAMILY );
           }
        }
        return;
}
/*======================================================================*
// This routine prints the Pablo IDs assigned to named HDF identifiers  *
//======================================================================*/
void printFileMappingsRT( char *mapFile, char **Names, int nPabloIDs )
{
      int i;
      FILE *ptr;
      ptr = fopen( mapFile, "w" );
 
        if ( ptr == NULL ) {
          fprintf(stderr,
                    "Couldn't open map file %s - none created.\n",mapFile);
            return;
        }
 
      fprintf(ptr,"\n\nPablo ID to HDF Name mappings:\n");
      fprintf(ptr,"------------------------------\n");
        for ( i = 1; i <= nPabloIDs; i++ ) {
           fprintf(ptr,"%4d %s\n",i,Names[i] );
      }
      fprintf(ptr,"\n\n");
      fclose( ptr );
}
/************************************************************************/
/*    _hdfNameDescriptor                                    */
/*       Generate a SDDF binary format record descriptor for the  */
/*       named identifiers used during execution.                 */
/************************************************************************/
void _hdfNameDescriptor( void )
{
    static char recordBuffer[ 4096 ];
    int         recordLength;

#ifdef PABLODEBUG
      fprintf( debugFile, "_hdfExitTraceDescriptor entered\n" );
      fflush( debugFile );
#endif /* PABLODEBUG */
    hdfRecordPointer = recordBuffer;
    /********************************************************************/
    /* Allow space at the beginning of the record for the packet        */
    /*length which will be computed after the packet is complete.       */
    /********************************************************************/
    sddfWriteInteger( &hdfRecordPointer, 0 );
    /********************************************************************/
    /* The record type, tag, and name                                   */
    /********************************************************************/
    sddfWriteInteger( &hdfRecordPointer, PKT_DESCRIPTOR );
    sddfWriteInteger( &hdfRecordPointer, ( FAMILY_NAME ) );
    sddfWriteString( &hdfRecordPointer, "HDF Name Identifier Record" );
    /********************************************************************/
    /* The record attribute count and string pair                       */
    /********************************************************************/
    sddfWriteInteger( &hdfRecordPointer, 1 );
    sddfWriteString( &hdfRecordPointer, "description" );
    sddfWriteString( &hdfRecordPointer, "HDF Name Identifier Record" );
    /********************************************************************/
    /* The record field count                                           */
    /********************************************************************/
    sddfWriteInteger( &hdfRecordPointer, 3);
    /********************************************************************/
    /* Create fields                                                    */
    /********************************************************************/
    WRITE_HDF_FIELD(  "Identifier Type", 
                  "Data Set Type", 
                  "Data Set Identifier Type", 
                  INTEGER, 0 );
    WRITE_HDF_FIELD2( "HDF ID",
                      "HDF ID", "File, Data Set or Dim Identifier number",
                      "0", "No HDF ID specified",
                      INTEGER, 0 ); 
    WRITE_HDF_FIELD( "HDF Name",
                     "HDF Name", "Name of File, Data Set or Dim",
                      CHARACTER, 1 );

    recordLength = (int)(hdfRecordPointer - recordBuffer);

    hdfRecordPointer = recordBuffer;
    sddfWriteInteger( &hdfRecordPointer, recordLength );

    putBytes( recordBuffer, (unsigned) recordLength );
}
#endif /* PCF_BUILD */

Generated by  Doxygen 1.6.0   Back to index