summaryrefslogtreecommitdiffstats
path: root/pablo/PabloHDF_RT.c
diff options
context:
space:
mode:
Diffstat (limited to 'pablo/PabloHDF_RT.c')
-rw-r--r--pablo/PabloHDF_RT.c1473
1 files changed, 1473 insertions, 0 deletions
diff --git a/pablo/PabloHDF_RT.c b/pablo/PabloHDF_RT.c
new file mode 100644
index 0000000..66ecc72
--- /dev/null
+++ b/pablo/PabloHDF_RT.c
@@ -0,0 +1,1473 @@
+/* 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 *
+//======================================================================*/
+#include "H5config.h"
+#include "SystemDepend.h"
+#include "Trace.h"
+#include "TraceParam.h"
+#include "ProcIDs.h"
+#include "HDFTrace.h"
+#include "SDDFparam.h"
+#include <string.h>
+#include <stdio.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 HAVE_PARALLEL
+#include "MPIO_Init.h"
+#include "MPIO_EventArgs.h"
+#include "MPIO_TraceParams.h"
+#endif
+
+#ifndef TRgetThreadID
+#define TRgetThreadID TRgetNode
+#endif
+
+#ifndef TRnumNodes
+#define TRnumNodes 1
+#endif
+
+#define AllThreads -1
+
+#define set_c_mappedID( fd ) (fd)
+#define c_mappedID( fd ) (fd)
+/*======================================================================*
+// 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 *, unsigned );
+void HDFendTrace_RT( void );
+int initproctracert_( void );
+int initHDFProcTrace_RT( void );
+void HDFtraceEvent_RT( int , char *, unsigned ) ;
+void BeginIOEventRecord ( int, double , void * );
+void EndIOEventRecord ( int , double , void *);
+void BeginMPIOEventRecord ( int, double, void * );
+void EndMPIOEventRecord ( int , double , void *);
+void BeginHDFEventRecord( int , double );
+void EndHDFEventRecord ( int , double ,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 );
+/*======================================================================*
+// 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;
+/*======================================================================*
+// NAME *
+// HDFinitTrace_RT-- initialize HDF real-time tracing *
+// USAGE *
+// VOID HDFinitTrace_RT( fileName, procTraceMask) *
+// *
+// char *fileName; IN: name of output file *
+// unsigned procTraceMask; IN: families of procedures to trace *
+// RETURNS *
+// None. *
+//======================================================================*/
+void HDFinitTrace_RT( char *fileName, unsigned procTraceMask )
+{
+ int error;
+ TR_LOCK criticalSection;
+ TRgetClock( &epoch );
+ criticalSection = TRlock();
+ error = initHDFProcTrace_RT() ;
+ procTrace = procTraceMask;
+ TRunlock( criticalSection );
+ if ( error != SUCCESS ) {
+ fprintf (stderr,"Unable to Initialize properly. Exiting program\n");
+ exit(-1);
+ }
+ FileName = ( char * ) malloc ( strlen( fileName ) + 1 );
+ strcpy( FileName, fileName ) ;
+#ifdef HAVE_PARALLEL
+ /*==============================================================*
+ // In the parallel case, initialize MPI-IO tracing. This will *
+ // set the trace file name. *
+ //==============================================================*/
+/* initMPIOTrace( FileName, RUNTIME_TRACE ); */
+#else
+ /*==============================================================*
+ // In the non-parallel case, set the trace file name and *
+ // initialize the trace library. *
+ //==============================================================*/
+ setTraceFileName(FileName);
+ basicLibraryInit( );
+#endif /* HAVE_PARALLEL */
+}
+/*======================================================================*
+// NAME *
+// HDFendTrace-- end HDF tracing *
+// USAGE *
+// VOID HDFendTrace_RT(void) *
+// RETURNS *
+// None. *
+//======================================================================*/
+void HDFendTrace_RT( )
+{
+ int j, numSetIDs;
+ HDFnode_t *P;
+ char **Names;
+ char* mapFile;
+
+ /*==============================================================*
+ // Assing pablo ids to named identifiers and tag records *
+ //==============================================================*/
+ HDFassignPabloIDs( &numSetIDs, &Names );
+ mapFile = (char *)malloc( strlen(FileName) + 5 );
+ strcpy(mapFile,FileName);
+ strcat(mapFile,".map");
+ printFileMappingsRT( mapFile, Names, numSetIDs );
+ /*==============================================================*
+ // Print SDDF summary records *
+ //==============================================================*/
+ writeHDFRecDescrptrsRT();
+ writeHDFNamePacketsRT( Names, numSetIDs );
+ for ( j = 0; j < NumHDFProcs; ++j ) {
+ HDFSummarySDDF( HDFQueues[j], j );
+ }
+ endTracing();
+ /*==============================================================*
+ // Clean up storage *
+ //==============================================================*/
+ free( (void *)mapFile );
+ for ( j = 0; j < numSetIDs; ++j ) {
+ if ( Names[j] != NULL ) {
+ free((void *)Names[j]);
+ }
+ }
+ free( (void *)Names );
+ P = CallStack;
+ if ( P->ptr != NULL ) {
+ fprintf(stderr,"CallStack not empty at termination\n");
+ } else {
+ free((void *)P);
+ }
+ free((void *)HDFQueues) ;
+}
+/*======================================================================*
+// 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, j, size;
+ int numProcs = NumHDFProcs;
+
+ if ( traceProcessorNumber == -1 ) {
+ traceProcessorNumber = TRgetDefaultProcessor();
+ }
+ /*==============================================================*
+ // Initialize InitNode used for node initialization. *
+ //==============================================================*/
+ InitNode.ptr = NULL;
+ InitNode.eventID = 0;
+ InitNode.lastIOtime = 0;
+ InitNode.record.nCalls = 0;
+ InitNode.record.lastCall = 0;
+ InitNode.record.incDur = 0;
+ InitNode.record.excDur = 0;
+ InitNode.record.hdfID = 0;
+ InitNode.record.xRef = 0;
+ for ( j = 0; j < nTallyFields; ++j ) {
+ InitNode.record.times[j] = 0;
+ }
+ 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 = 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 )
+{
+ TR_LOCK criticalSection;
+ CLOCK currentTime;
+ double seconds;
+
+ criticalSection = TRlock();
+ currentTime = getClock();
+ seconds = clockToSeconds( currentTime );
+
+ if ( isBeginIOEvent ( eventType ) ) {
+ BeginIOEventRecord ( eventType, seconds, dataPtr ) ;
+ } else if ( isEndIOEvent( eventType ) ) {
+ EndIOEventRecord ( eventType, seconds, dataPtr );
+ } else if ( isBeginHDFEvent( eventType ) ) {
+ BeginHDFEventRecord ( eventType , seconds ) ;
+ } else if ( isEndHDFEvent( eventType ) ) {
+ EndHDFEventRecord ( eventType, seconds, dataPtr );
+#ifdef HAVE_PARALLEL
+ } else if ( isBeginMPIOEvent( eventType ) ) {
+ BeginMPIOEventRecord ( eventType, seconds, dataPtr ) ;
+ } else if ( isEndMPIOEvent( eventType ) ) {
+ EndMPIOEventRecord ( eventType, seconds, dataPtr );
+#endif /* HAVE_PARALLEL */
+ } else {
+ fprintf(stderr,"eventType %d, dataLen = %d\n",eventType,dataLen);
+ }
+ TRunlock( criticalSection );
+}
+/*======================================================================*
+// BeginIOEventRecord: *
+// This routine simply records the time in the record on the top of *
+// the stack. *
+//======================================================================*/
+void BeginIOEventRecord ( int eventType, double 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, double secs, void *dataPtr )
+{
+ double incDur;
+ int i, Field, ByteField, bytes;
+
+ incDur = secs - CallStack->lastIOtime;
+ Field = getHDFFieldIndex( eventType ) ;
+ 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 = *((long *)dataPtr);
+ CallStack->record.hdfID = openInfo.setID;
+ HDFrecordFileName ( &openInfo );
+ break;
+ default:
+ break;
+ }
+
+}
+#ifdef HAVE_PARALLEL
+/*======================================================================*
+// BeginMPIOEventRecord: *
+// This routine simply records the time in the record on the top of *
+// the stack. *
+//======================================================================*/
+void BeginMPIOEventRecord( int eventType, double seconds, void *dataPtr )
+{
+ /*==============================================================*
+ // 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. *
+ // in most cases, this is the file ID. For mpiOpen, it is the *
+ // name of the file. For mpiDelete, no information is of any *
+ // use. *
+ //==============================================================*/
+ switch ( eventType )
+ {
+ case mpiGetSizeBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiGetSizeBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiGetGroupBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiGetGroupBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiGetAmodeBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiGetAmodeBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiGetViewBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiGetViewBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiGetPositionBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiGetPositionBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiGetByteOffsetBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiGetByteOffsetBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiGetTypeExtentBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiGetTypeExtentBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiGetAtomicityBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiGetAtomicityBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiOpenBeginID:
+ strcpy( openName,
+ ((struct mpiOpenBeginArgs *)dataPtr)->fileName);
+ break;
+ case mpiCloseBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiCloseBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiDeleteBeginID:
+ break;
+ case mpiSetSizeBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiSetSizeBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiPreallocateBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiPreallocateBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiSetViewBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiSetViewBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiReadAtBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiReadAtBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiReadAtAllBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiReadAtAllBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiWriteAtBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiWriteAtBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiWriteAtAllBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiWriteAtAllBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiIreadAtBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiIreadAtBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiIwriteAtBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiIwriteAtBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiReadBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiReadBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiReadAllBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiReadAllBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiWriteBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiWriteBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiWriteAllBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiWriteAllBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiIreadBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiIreadBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiIwriteBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiIwriteBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiSeekBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiSeekBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiSetAtomicityBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiSetAtomicityBeginArgs *)dataPtr)->fileID;
+ break;
+ case mpiSyncBeginID:
+ CallStack->record.hdfID
+ = ((struct mpiSyncBeginArgs *)dataPtr)->fileID;
+ 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, double seconds, void *dataPtr )
+{
+ double incDur;
+
+ incDur = seconds - CallStack->lastIOtime;
+ CallStack->record.times[MPI] += incDur;
+ ++CallStack->record.counts[MPI];
+ if ( eventType == mpiOpenEndID ) {
+ /*===========================================================*
+ // complete the file information for the case of a file *
+ // open and record the information. *
+ //===========================================================*/
+ openInfo.setName = openName;
+ openInfo.setID = ((struct mpiOpenEndArgs *)dataPtr)->fileID;
+ CallStack->record.hdfID = openInfo.setID;
+ HDFrecordFileName ( &openInfo );
+ }
+}
+#endif /* HAVE_PARALLEL */
+/*======================================================================*
+// 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, double 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 ( int eventID, double seconds, void *dataPtr )
+{
+ HDFsetInfo *info;
+ HDFnode_t *HDFrec;
+ double incSecs;
+ static int dummyIDs = -4;
+ int procIndex;
+ /*==============================================================*
+ // Find the procIndex in the table. *
+ //==============================================================*/
+ procIndex = ProcIndexForHDFExit( eventID );
+ /*==============================================================*
+ // 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 = seconds - 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_ ] += 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, 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, hdfID, xRef, PabloID = 1;
+ 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 = 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 = sizeof(NamePkt) + strlen(fName) ;
+ NamePkt.fileType = 0; /* not currently used */
+ NamePkt.fileID = j;
+ NamePkt.nameLen = 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( )
+{
+ HDFnode_t *P, *Q;
+ int 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, hdfID, xRef, eventID;
+ 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, arrayLen;
+ char buff[1024];
+ char *Packet;
+ HDFnode_t *Q;
+ struct {
+ int packetLen,
+ packetTag,
+ packetType,
+ eventID,
+ threadID,
+ nCalls;
+ double Seconds,
+ IncDur,
+ ExcDur;
+ long HDFid,
+ XREFid;
+ } Header;
+
+ Packet = buff;
+ Header.packetLen = sizeof(Header)
+ + 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 */
+ + nByteFields*sizeof(int) /* array lens */
+ + nByteFields*nBkts*sizeof(int) /* byte hist */
+ + sizeof(int) ; /* Name len */
+ Header.packetTag = ( procIndex + 1 )*HDF_FAMILY | RECORD_TRACE ;
+ Header.packetType = PKT_DATA;
+ Header.threadID = TRgetNode();
+ while ( P != NULL ) {
+ Q = P->ptr;
+ Header.eventID = Q->eventID;
+ Header.Seconds = Q->record.lastCall;
+ Header.IncDur = Q->record.incDur;
+ Header.ExcDur = Q->record.excDur;
+ Header.HDFid = Q->record.hdfID;
+ Header.XREFid = Q->record.xRef;
+ memcpy( Packet, &Header, sizeof(Header) );
+ Packet += sizeof(Header);
+ /*===========================================================*
+ // copy length of times array and times array to Packet. *
+ //===========================================================*/
+ arrayLen = nTallyFields;
+ memcpy( Packet, &arrayLen, sizeof(int) );
+ Packet += sizeof(int);
+ memcpy( Packet, Q->record.times, nTallyFields*sizeof(int) );
+ Packet += nTallyFields*sizeof(int);
+ /*===========================================================*
+ // copy length of counts array and counts array to Packet. *
+ //===========================================================*/
+ arrayLen = nTallyFields;
+ memcpy( Packet, &arrayLen, sizeof(int) );
+ Packet += sizeof(int);
+ memcpy( Packet, Q->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, Q->record.counts, nByteFields*sizeof(int) );
+ Packet += nByteFields*sizeof(int);
+ /*===========================================================*
+ // copy length of historgram arrays and arrays to Packet. *
+ //===========================================================*/
+ arrayLen = nBkts;
+ for ( i = 0; i < nByteFields; ++i ) {
+ memcpy( Packet, &arrayLen, sizeof(int) );
+ Packet += sizeof(int);
+ memcpy( Packet, Q->record.Hists[i], nBkts*sizeof(int) );
+ Packet += nBkts*sizeof(int);
+ }
+ arrayLen = 0; /* name length */
+ memcpy( Packet, &arrayLen, sizeof(int) );
+ putBytes( buff, Header.packetLen );
+ free((void *)P);
+ 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, j, allIOCount;
+ double allIOTime;
+ allIOTime = 0;
+ for ( j = FirstIO; j <= LastIO; ++j ) {
+ allIOTime += T->times[j];
+ }
+ T->times[AllIO] = allIOTime;
+
+ allIOCount = 0;
+ for ( j = FirstIO; j <= LastIO; ++j ) {
+ allIOCount += T->counts[j];
+ }
+ T->counts[AllIO] = allIOCount;
+
+ T->excDur = T->incDur - ( T->times[HDF_] + T->times[MPI]
+ + T->times[AllIO] );
+
+ S->nCalls += T->nCalls;
+ S->lastCall = max( S->lastCall, T->lastCall );
+ S->incDur += T->incDur;
+ S->excDur += T->excDur;
+ for ( j = 0; j < nTallyFields; ++j ) {
+ 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 < nByteFields; ++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;
+ 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, 17 );
+ WRITE_HDF_FIELD( "Event Identifier",
+ "Event ID",
+ "Corresponding Event",
+ INTEGER, 0 );
+ WRITE_HDF_FIELD( "Processor Number",
+ "Node",
+ "Processor number",
+ INTEGER, 0 );
+ WRITE_HDF_FIELD( "N Calls",
+ "N Calls",
+ "Number of Calls to this Proc",
+ 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( "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( "HDF Name",
+ "HDF Name",
+ "Name of File,Data Set or Dim accessed",
+ CHARACTER, 1 );
+ /*===================================================================
+ // The entire record descriptor packet has been written. *
+ // Compute and update the record length. *
+ // Write the completed record. *
+ //==================================================================*/
+ recordLength = hdfRecordPointer - recordBuffer;
+
+ hdfRecordPointer = recordBuffer;
+ sddfWriteInteger( &hdfRecordPointer, recordLength );
+
+ putBytes( recordBuffer, (unsigned) recordLength );
+}
+
+/*======================================================================*
+// Internal Routine: writeHDFRecDescrptrsRT *
+// Writes record descriptors for the HDF events. *
+//======================================================================*/
+void writeHDFRecDescrptrsRT()
+{
+ char HDFProcNames[][40] = {
+# include "HDFentryNames.h"
+ "HDF_Last_Entry"
+ };
+ int j;
+ char BUF1[256], BUF2[256] ;
+ _hdfNameDescriptor(); /* Descriptor for named identifiers */
+ for ( j = 0; j < NumHDFProcs; ++j ) {
+ if ( HDFQueues[j] != NULL ) {
+ strcpy( BUF2, "HDF ");
+ strcat( BUF2, HDFProcNames[j] );
+ strcat( BUF2, " Procedure Summary");
+ strcpy( BUF1, BUF2 );
+ strcat( BUF1, " Trace");
+ _hdfDescriptorRT( BUF1, BUF2, (j+1)*HDF_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()
+{
+ static char recordBuffer[ 4096 ];
+ int recordLength;
+
+#ifdef DEBUG
+ fprintf( debugFile, "_hdfExitTraceDescriptor entered\n" );
+ fflush( debugFile );
+#endif /* DEBUG */
+ 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 = hdfRecordPointer - recordBuffer;
+
+ hdfRecordPointer = recordBuffer;
+ sddfWriteInteger( &hdfRecordPointer, recordLength );
+
+ putBytes( recordBuffer, (unsigned) recordLength );
+}